Since Ethereum also uses a P2P network to send and receive messages, I thought an eclipse attack was also possible on this platform. Eventually, based on this paper released on March 1st, it is possible to completely isolate a single node with just two nodes. This paper summarizes the problems that came up in the bounty program from January, and 3 main methods of possible attack.
In order to understand the first problem, you must first understand how Ethereum manages its P2P network. The most important thing when it comes to network graph configuration is how it will find other nodes. This is commonly called node discovery. Ethereum utilizes its own edited version of a DHT(Distributed Hash Table) protocol called Kademlia.
The biggest difference in Kademlia from other DHTs is that it measures distance between nodes by XOR distance. The distance in XOR distance is symmetric. Thus, with just the node’s ID, the distance from node A to node B(according to node A), the distance from node B to node A(according to node B), and the distance between node A and node B(according to node C) are all the same. Consequently, if each node knows and communicates with only nearby nodes, then a large network can be configured using a small amount of connections. According to Kademlia’s paper, if there are N nodes, then only O(log(N)) connections have to be maintained.
The root cause of why Ethereum was especially vulnerable to Eclipse attacks lie here. In the Kademlia protocol, the distance is calculated based on the node’s ID, which means the ID of every node within a network must be known as the same value. This is the only way to bring out about the efficiency claimed by Kademlia. However, the problem is that there is no way for each node to agree with each other’s IDs in a distributed environment. Thus, the node that is requesting a connection must give its public key. The public key goes through a process of Keccak hashing and this becomes the ID. This means that every node defines its own ID. As a result, one machine can create many node IDs and a bad user can use one machine to pretend to be many nodes in order to carry out a Sybil attack.
In order to prevent this, the IP address and the node ID must be remembered in conjunction. This should make it impossible to create many keys from a single address; however, a solution has not yet be implemented.
The second method of attack is to control the server’s time. Ethereum records the message’s sent time in order to prevent a replay-attack. If the received message’s time has a difference of more than 20 seconds, it assumes that it was a message that intended a replay-attack and is ignored. The problem is that it only checks the message’s recorded time, and you cannot know the true time the message was actually sent. For instance, if the time difference between two nodes is greater than 20 seconds, then even a normal message will never be processed.
In a modern day server environment, this will likely never happen. Server times are usually never set manually and it periodically synchronized using the NTP(Network Time Protocol). Thus most server’s time will only have a margin of error of only a couple seconds. However, this is only true in normal situations. For instance, what if someone hacks the NTP server that was supposed to be used by some node for time synchronization purposes? Or what if NTP messages are intercepted so that time cannot be synchronized properly? What if the NTP message was edited so that the time shown is pulled more than 20 seconds forward from its true time stamp? In the last case, the affected node will have a different time value from the rest of the nodes on the network, and thus, all the nodes will elect to ignore the messages originating from the affected node. This results in the affected node to be forgotten, and that node will only communicate with the one that attacked the NTP server.
The Ethereum protocol tried to prevent replay-attacks by just using the written timestamp, and this was the problem. In order to stop these type of problems, each session, or perhaps, each message should use the nonce to sign. However, a solution of this type also does not seem to exist yet in Ethereum. Thus, servers that are running the Ethereum node needs to be checked periodically whether they are all synchronizing the time properly or not.
The last type of attack is a sort of timing attack. In order to reduce the over-utilization of resources on the network, Ethereum limits the maximum amount of connections for communication purposes. Currently, the maximum connection is limited to 25, and if a greater amount of connection is made, it requests new connections or simply rejects them. Conversely, if a certain node can occupy 25 connections, this node will no longer request or accept new connections. How is this possible? Simple. You have to aim for the moment the connection is zero. No matter what kind of server it is, when it first starts, the number of connections will be at zero. You must aim for this timing and make the 25 connections first. However, how will you find the moment the server is restarted?
There are many reasons to restart a server, such as facing hardware issues, having to update the OS or the Ethereum client, etc. However, there are ways to make a more offensive DoS attack in order to kill the Ethereum client. Normally, when the Ethereum mining node’s server is shut down, it restarts right away. Thus, killing a server with a DoS attack makes the server restart automatically, and one can aim to request 25 connections at this point.
Preventing this method of attack is simpler than the two previous methods explained above. The two methods above require the editing of the protocol itself; however, this attack can be prevented by modifying the implementation. Apart from the limit of the total number of connections allowed, you can simply limit the number of incoming connections from the outside. More specifically, if I make at least a few nodes to connect to the nodes that I am requesting, then the risk of my connection being monopolized by someone else disappears. This solution have been implemented starting from go-ethereum 1.8 version that was released in February.
Originally published at medium on April 26, 2018.