You need more than the luck of the Irish to protect yourself from attacks due to misconfigured Ethereum clients. But it is a good start.
Blockdaemon has a developer and deployment team in Ireland since the beginning of the year. We are now ready to make it official. Ireland is a world leader in data centre management, and we aim to use the local expertise in running huge data networks for all major blockchain protocols (aggregating data cost across Bitcoin, Ethereum, Quorum, Stellar, Corda etc. allows for better scalability and security). In addition to the opening of our office in Galway, we are planning on adding Blockdaemon data centres in Ireland for customers that have strict EU data privacy requirements.
Our Blockdaemon lead in Ireland is Jonas Pfannschmidt, who joined us earlier in the year for Hewlett Packard Enterprise (HPE), where he implemented blockchain based solutions and helped customers adopt this new technology. He has 15 years of experience across every aspect of the software development cycle and is based in our new Galway offices.
Jonas has built out our Ethereum deployment tool (go check it out on our website, use promo code “IRELAND”), which offers the best possible out of the gate configuration for an Ethereum geth node. We have asked him to provide a more technical overview explaining why it is so important to set up your nodes correctly from the get-go, how attacks happen, and what you can do about them.
Here is what Jonas has to say about good geth, stealing (a no-no,) and how to nip attacks in the asal (that is some Irish there for you):
Why is it important to configure your nodes correctly
According to the Chinese security researchers at NetLab, ether with a value of currently around $20 Million dollars has been stolen from misconfigured Ethereum clients.
NetLab’s own Network Scan Monitor reports roughly 60,000 scans dailyscanning for misconfigured clients. With that much scanning going on it’s inevitable that the attackers find vulnerable Ethereum installation.
These kinds of attacks aren’t new, over the years there have been many reports where attacker attempted (sometimes successfully) to steal funds from misconfigured Ethereum clients. A couple of examples:
How does the attack work
The rest of this article focuses on geth, the Go Ethereum Client one of the most popular Ethereum clients. Other clients have similar functionality which makes them potentially vulnerable to same attack.
Geth typically operates as a long running background process. In order to interact with geth, it exposes two interfaces:
- IPC (Inter-process communication) is used to connect locally running processes to geth
- RPC (Remote Procedure Calls) is used to connect processes to geth over the network (although the default configuration restricts it to locally running processes)
Both interfaces allow bi-directional communication with geth. Examples of processes communicating with the geth client are:
- The geth console which comes with every geth installation
- MetaMask (depending on it’s configuration)
The APIs exposed via those two interfaces consists of two sub-APIs:
- The web3 API is standardized across all Ethereum clients. This API is typically used by DApps (https://github.com/ethereum/wiki/wiki/JSON-RPC)
- The Management APIs allow the remote management of an Ethereum client. These APIs are not standardized and differ between the various Ethereum Clients. The geth management API is described here: (https://github.com/ethereum/go-ethereum/wiki/Management-APIs)
Since IPC is only available to locally running processes, it can be considered reasonably secure as long as the attacker has no way of getting into the server that runs geth.
RPC on the other hand can easily be misconfigured to allow processes to connect to geth over the network. Let’s enable the RPC interface and see what happens:
HTTP endpoint opened url=<a class="markup--anchor markup--p-anchor" href="http://127.0.0.1:8545/" target="_blank" rel="nofollow noopener noreferrer" data-href="http://127.0.0.1:8545/">http://127.0.0.1:8545</a> tells us that the RPC port is now enabled but is by default restricted to connections from localhost (127.0.0.1) only. Some people either by accident or because they have a valid use case go further and allow outside connections:
If nothing else (Routing, Firewalls, etc.) prevents connections, this means that now everybody can connect to this instance of geth.
Let’s see how a transaction can be created using the RPC interface:
This command attempts to send one ether from a local account to 0xdb40c12FD1d2327E7ccBA1182a19fa99620338E6. The result is:
Accounts in Ethereum are secured with an additional password and need to be unlocked before using them. The unlock command leaves the account unlocked for a certain amount of time.
One way of unlocking a account is through the geth console (Side note: By default, the geth console connects to the geth client using IPC):
This unlocks the account for 300 seconds. By quickly switching to the command line window I’m now able to send the transaction:
Instead of doing this manually, attackers use scripts that try to send a transaction like this every couple of seconds. These transactions keep failing while the account is locked. Until the owner of the server unknowingly unlocks the account. At this point the transactions succeed and transfer funds from the owner’s account to the attacker’s account.
- Geth runs with publicly available RPC interface
- Through internet scans, an attacker finds the open RPC interface
- The attacker runs a script that continuously instructs geth to send ether from a local account to an account controlled by the attacker
- When the legitimate owner tries to send a transaction, they will unlock the account for a short amount of time
- As soon as the account is unlocked, the transactions created by the attacker’s script succeed in transferring ether to the attacker’s account
I’ve disabled the “personal API” — am I still vulnerable?
The personal API is part of the management API and contains the commands to unlock accounts. Without this API nobody can unlock accounts. It is possible to define which APIs are enabled in RPC using:
Unfortunately omitting personal from this list doesn’t help as it is still exposed using the IPC interface. As soon as the owner unlocks the account, the attacker has a chance to withdraw funds. It doesn’t matter which API interface is used for this. In fact, the personal API is disabled in the RPC by default which does not prevent the attack.
I don’t keep any accounts on my geth server.
Your ether should be safe even if the attacker can run transactions since there is nothing available to steal. However it means you need to take care to never store an account on this server. Plus there are other attacks like maliciously changing the mining rewards address that can make use of a misconfigured RPC interface. Therefore we recommend not to rely purely on the fact that there is no account on the server.
I followed a tutorial to secure my RPC port behind an nginx with HTTP basic auth.
This is one option but please keep in mind that HTTP basic auth transmits the credentials unencrypted and can therefore be intercepted. It needs to be combined with SSL/TLS to be reasonably secure.
I followed a tutorial to whitelist my remote IP using a firewall.
While this certainly makes the attack a lot harder, we consider it not secure enough because IPs can be spoofed.
--rpccorsdomain – am I safe?
Short answer: No
--rpccorsdomain is an option in geth that prevents browsers from making requests from arbitrary domains. Example:
geth --rpc --rpccorsdomain <a class="markup--anchor markup--p-anchor" href="https://blockdaemon.com/" target="_blank" rel="nofollow noopener noreferrer" data-href="https://blockdaemon.com/">https://blockdaemon.com</a> would allow only connections from a script running on
<a class="markup--anchor markup--p-anchor" href="https://blockdaemon.com/" target="_blank" rel="nofollow noopener noreferrer" data-href="https://blockdaemon.com/">https://blockdaemon.com</a>. Please note that this is only enforced by a users browser, not by the server. An attacker can easily circumvent this by using anything other than a browser (e.g. curl as shown in the example above) or writing a custom script.
So what do you recommend to keep remote connections secure?
If you don’t need remote connections, it’s best not to enable RPC at all.
If remote connections are necessary: Never open the RPC endpoint to the public. Luckily this is the default when running
geth --rpc. If there is a need to access geth remotely, it is possible to use SSH to create an encrypted tunnel between the remote computer and the geth server.
This makes the local RPC endpoint on the server with the IP 126.96.36.199 available on a remote computer as if it where a local endpoint there.
More details on how to setup SSH can be found at: https://help.ubuntu.com/community/SSH/OpenSSH/Configuring
For persistent connections we recommend autossh.
What do the Ethereum developers do to mitigate these issues?
The geth team introduced personal_signAndSendTransaction in 2016 and later renamed it to to personal_sendTransaction. This command takes the account password as a parameter and allows to send transactions without having to first unlock the account. Mist already uses this command, which prevents at least one attack scenario mentioned in the beginning of this post. While this certainly improves the situation with the unlock command, it means that the password is transmitted in plain text which opens up different attack vectors. As of today the unlockAccount command is still available for backwards compatibility.
Looking for a fully managed Ethereum node? Blockdaemon is the simplest and fastest way to spin up secure nodes. Our Ethereum nodes are fully synced in minutes and we follow the best practices described here to keep RPC secure. The RPC interface on our nodes is only accessible via SSH tunnel.