#38686 [BC-Low] Nodes with trusted peers vulnerable to pending peer flooding and DoS
Submitted on Jan 10th 2025 at 04:18:26 UTC by @Blobism for Attackathon | Ethereum Protocol
Report ID: #38686
Report Type: Blockchain/DLT
Report severity: Low
Target: https://github.com/paradigmxyz/reth
Impacts:
Shutdown of less than 10% of network processing nodes without brute force actions, but does not shut down the network
Increasing less than 25% of network processing node resource consumption by at least 30% without brute force actions, compared to the preceding 24 hours
Causing less than 25% of network processing nodes to process transactions from the mempool beyond set parameters (e.g. prevents processing transactions from the mempool)
Description
Brief/Intro
The latest reth
release (v1.1.5
) contains a peer management vulnerability which allows both unlimited pending peers and DoS attacks which disable the connection of new peers. These attacks can be carried out on any reth
node with trusted peers. The unlimited peers issue results from the peer manager allowing in new pending connections even after pending limits are exceeded. The DoS attack comes from disconnecting pending peers which have exceeded this limit, leading to a subtraction overflow which results in the pending limit being permanently exceeded.
Vulnerability Details
Unlimited Pending Peers
The vulnerability is found in crates/net/network/src/peers.rs
, in the function on_incoming_pending_session
. The primary bug is found on these lines:
The return should be inside of the if
block. Due to it being after the if
block, this code path will allow unlimited pending peers through, even when num_pending_in
has exceeded max_inbound
. Additionally, the <=
check here should be a <
check, as it is currently allowing in pending connections 1 beyond max_inbound
.
To reach this point in the code, the number of established peer connections needs to have reached its maximum. The node must have at least 1 trusted peer, but it does not matter if that peer is connected or not. This is due to an additional bug in the following line:
The check here should be <
. This check is meant to allow in pending peers in case one of the node's trusted peers is not yet connected. However, this check currently will return True
even when all trusted peers are connected, due to the check being <=
. This expands the impact of the primary bug, because it makes it easier to reach the code which allows for unlimited pending peers to be allowed through.
Peer Connection DoS
Let us look at the lines of code with the primary bug once again:
Observe that this always allows a pending connection to be created, but it only increments num_pending_in
if the value is within bounds. This means that if the bounds are exceeded, a pending connection will be created, but num_pending_in
will not be incremented to reflect this, under-counting the number of pending connections.
Now consider what happens if the pending bounds are exceeded and all of these pending connections are closed. Depending on how these pending connections are closed, many different functions could be called in the peer manager (on_incoming_pending_session_dropped
for example), but all of these pending session close functions will call self.connection_info.decr_pending_in()
. The function decr_pending_in
then does a decrement:
This will overflow because the number of actual pending connections which are getting closed will exceed the value of num_pending_in
. Now, we will have an extremely large num_pending_in
. The DoS comes from the fact that if an established connection is now closed, the overflow will permanently prevent new pending connections due to this check in on_incoming_pending_session
:
The on_incoming_pending_session
function is shown below with bugs noted in comments:
Impact Details
This exploit allows an attacker to flood a reth
node with pending peers, beyond the set limits of the node. Additionally, new peers can easily be prevented from connecting to this node by exploiting the primary bug. The node remains connected to its current peers when this happens, which could enable a strategic network partition by an attacker.
The percentage of reth
execution nodes is 2% according to clientdiversity.org
. Additionally, the node must have at least one trusted peer for this exploit to be possible. Therefore, this is a Low vulnerability bug that falls into the following categories:
"Shutdown of less than 10% of network processing nodes without brute force actions, but does not shut down the network" - With a debug build, a node would truly panic and shut down due to the subtraction overflow exploit. With a release build, no new incoming peers will be accepted, so this processing node could potentially no longer propagate or receive new transactions.
"Causing less than 25% of network processing nodes to process transactions from the mempool beyond set parameters (e.g. prevents processing transactions from the mempool)" - This exploit falls in this category in the sense that the mempool will no longer contain transactions that it would normally have, because the DoS attack can cut it off from peers.
"Increasing less than 25% of network processing node resource consumption by at least 30% without brute force actions, compared to the preceding 24 hours" - Flooding a node with pending peers could achieve this due to the unlimited pending peer bug.
References
https://github.com/paradigmxyz/reth/blob/v1.1.5/crates/net/network/src/peers.rs
Link to Proof of Concept
https://gist.github.com/blobism/867808c4fd6793b26bbd596d02e2306d
Proof of Concept
Proof of Concept
I believe that unit tests are sufficient in demonstrating the severity of these exploits. Integration or private testnet PoCs can be provided if needed. There are 2 versions of the exploit demonstrated, to show that the exploit can work regardless of the state of the trusted peer:
Awaiting Trusted Peers - In this case we are awaiting the connection of a trusted peer, so it is expected behavior that pending connections will be allowed in even when established connections have reached their max.
Trusted Peers Connected - In this case all trusted peers have established connections. Pending connections are still allowed in due to one of the bugs described above.
In both cases we show how pending peers are allowed beyond the limit, then how the DoS attack can occur to prevent new pending peers. These PoC unit tests should be added to crates/net/network/src/peers.rs
Unit PoC 1: Awaiting Trusted Peers
This PoC uses the following procedure:
Add a trusted peer, but do not connect it
fill established inbound slots with untrusted peers
Saturate the pending inbound slots, which is allowed since the trusted peer has not connected
Add pending inbound connections beyond the limit (this is where a flooding exploit could occur)
Drop all of these pending connections (subtraction overflow occurs here)
Disconnect one of the established peers
Observe that any new incoming pending peers are rejected, when they should be allowed through
We expect the debug build to have an early subtraction overflow panic:
The release build shows the final DoS attack, as it rejects a pending connection that should be allowed:
Unit PoC 2: Trusted Peers Connected
This PoC uses the following procedure (very similar to the previous):
Add a trusted peer and establish its connection
Fill remaining established inbound slots with untrusted peers
Add pending inbound connections (This is where a flooding exploit could occur. Note that correct behavior would be to reject all of these connections, since established inbound slots are full AND one of those is our trusted peer)
Drop all of these pending connections (subtraction overflow occurs here)
Disconnect one of the untrusted established peers
Observe that any new incoming pending peers are rejected, when they should be allowed through
We expect the debug build to have an early subtraction overflow panic:
The release build shows the final DoS attack, as it rejects a pending connection that should be allowed:
Last updated
Was this helpful?