🛑Example Vulnerability
Incorrect assumpiton of Ethereum client implementation
Bug bounty payouts
lido: $100k
rocket finance $100k
Tranches: 44.8 eth
Current TVL of effected projects at the time of writing:
$15.03 Billion
$1.89 Billion
$10.88 Million
Refrences and further reading links:
In the ever-evolving world of blockchain, liquid staking has emerged as a transformative solution for participants unable to stake the required 32 ETH in the Ethereum 2.0 network. As a significant upgrade, Ethereum 2.0 is designed not only to enhance transaction processing capabilities but also to introduce improved security and scalability. Transitioning from Proof of Work (PoW) to Proof of Stake (PoS), Ethereum 2.0 ditches miners for validators. To become one, participants need to stake a significant 32 ETH, which given the price of Ether can be prohibitively expensive for many.
Liquid staking represents an innovative approach to traditional staking mechanisms on prominent blockchain networks. Rather than merely staking assets and waiting for returns, liquid staking introduces a layer of flexibility and liquidity that benefits users in multiple ways.
Users can stake their assets, contributing to the network's stability, and in return, they earn rewards. But what sets liquid staking apart is its ability to tokenize these staked assets. By turning them into tokens of equivalent value, users gain the ability to move, trade, or use these tokens as they wish, all while continuing to earn staking rewards.
Here's a step-by-step of how the process typically unfolds:
Users initiate the process by depositing their assets into the liquid staking platform.
The platform, in turn, pools these deposits and stakes these assets on the ethereum network to generate rewards.
A portion of the rewards generated is allocated to users in proportion to their deposits.
In parallel, the deposited assets are tokenized into a specific type of token, often compliant with popular standards like ERC-20. This token essentially represents a user's staked assets in a liquid form.
Users can store, trade, or use this token like any other digital asset in their portfolio, offering unprecedented flexibility.
Whenever users desire, they can convert these tokens back to their original assets.
In essence, liquid staking seamlessly merges the benefits of staking for network stability and rewards with the advantages of tokenized assets' liquidity.
Unmasking the Attack Vector
The upcoming vulnerability discussion stems from inherent structural issues between Liquid Staking Platforms (LSP) and outsourced node operators, coupled with certain challenges in the Ethereum 2.0 Beacon client.
To truly grasp the depth of this vulnerability, we must first acquaint ourselves with the inner workings of a typical Liquid Staking Platform.
Initially, like many, I was under the impression that the core team behind these platforms directly operated nodes. This understanding, however, proved to be a misconception. Instead of direct node operation, many LSP teams delegate this crucial task to third-party entities.
This operational model isn't exclusive to one platform; even some of the leading competitors in the liquid staking space follow a similar structure, entrusting third parties with node operations.
For a more detailed partnership example within the industry, you can refer to the relevant partnership announcements made by these platforms.
Let's delve into the architecture of the Ethereum 2.0 Beacon client.
As Ethereum evolves to its 2.0 version, it's pivoting from the Proof-of-Work (PoW) consensus to the Proof-of-Stake (PoS) mechanism. Integral to this transition is the introduction of an official Deposit Contract, designated by the address: 0x00000000219ab540356cBB839Cbe05303d7705Fa.
Below, you'll find the official code for this Deposit contract.
Once the deposit function is invoked, using parameters like pubkey
, withdrawal_credentials
, signature
, and deposit_data_root
, and the deposit finalizes, a DepositEvent
is triggered.
This event prompts Ethereum 2.0 Beacon clients, including the likes of Prysm and Lighthouse, to refresh their staking states.
Below is the code implementation for the Prysm client.
Upon examining the section that manages the Deposit Event, it's clear that the balance in the Beacon state, corresponding to the initially set Withdrawal credential for a specific pubkey
, continues to augment. This indicates that the first-set Withdrawal credential remains persistent and dominant, even if there are subsequent attempts to alter it.
Vulnerability Overview: A malicious third-party node operator can exploit the Ethereum 2.0 Beacon client's Deposit Event handling mechanism. The attack revolves around "frontrunning" legitimate deposit transactions to manipulate the withdrawal credentials for the staked Ether.
Attack Breakdown:
Initiation: A rogue validator, intending to exploit the system, prepares malicious deposit data.
Frontrunning: Before a legitimate deposit transaction of 32 ETH takes place, the malicious node operator "frontruns" it by executing their prepared transaction.
Malicious Deposit Data: This malicious transaction utilizes the same validator's public key (
pubkey
) as the upcoming legitimate deposit. However, it only deposits a minimum required amount (e.g., 1 ETH or 16 ETH in the case of certain platforms like RocketPool). Crucially, the withdrawal credential in this transaction is different from the one originally agreed upon with the protocol.System Behavior Exploitation: Due to how the Beacon client operates, if a
pubkey
hasn't been previously registered, the system would prioritize and process this new malicious deposit first, believing it to be the first time this validator's key is seen. As a result, when the genuine 32 ETH deposit transaction follows, the Beacon client simply adds this amount to the malicious operator's deposit.Outcome: The net result is that the staked 32 ETH now has the withdrawal credentials set by the attacker. Essentially, the malicious operator can now control and potentially withdraw these funds.
Impact: By exploiting this vulnerability, the malicious node operator can effectively divert and control staked assets meant for a legitimate node. This means the funds from unsuspecting pool users, expecting to stake under a set withdrawal credential, are now under the control of the attacker.
(If you haven't read our article on front running you can find it here)
Mitigation Steps for Frontrunning Attack in Ethereum 2.0 Staking Contracts:
Verification of Node Operators' Keys:
Contracts must have the capability to verify that Node Operators' keys have not been used for any malicious pre-deposits. This can be done by cross-referencing with a predefined list of authorized keys.
Establish a Deposit Security Committee:
Form a committee responsible for monitoring all deposit activities.
Their role includes validating the current state of deposits and affirming that available staking keys are safe for use.
Use Merkle Root for Key Verification:
The staking contract (like Lido in the example) should fetch the Merkle root encoding of all keys used in staking deposits.
This Merkle root data will act as a point of reference to verify the authenticity of staking keys.
Off-Chain Guardian Committee Verification:
To conserve gas costs, the Merkle root data should be checked and signed by an off-chain guardian committee. This committee will ensure that the data is accurate and untampered.
Enforce Secure Deposit Transaction:
Implement a function named
depositBufferedEther
. This function ensures that buffered ether can only be sent to the staking contract if the following conditions are met:The Merkle root data from the staking contract matches the on-chain Merkle root data.
Staking hasn't been paused.
A quorum of guardians has provided their signatures, ensuring the transaction's legitimacy.
There's a minimum block distance between deposits to prevent rapid, frequent deposits.
The block hash provided matches the expected hash for the given block number.
The staking keys operation index has not been tampered with.
Transaction Verification:
The provided signatures should be verified against the staking contract's current state. If all conditions are met, the deposit transaction is approved and executed.
Otherwise, if any data point changes (due to a deposit, modification of approved staking keys, or a blockchain reorganization) before the deposit transaction, the staking contract will reject the transaction.
Routine Updating of Deposit Transactions:
Regularly update the block number of the last deposit to monitor deposit frequency and maintain security measures.
By following these steps, staking platforms can significantly minimize the risk associated with the frontrunning attack, ensuring the integrity of staking operations.
Last updated