Smart contract security analysis, full path analysis of Vyper reentrancy lock vulnerability

Smart contract security analysis, full path analysis of Vyper reentrancy lock vulnerability

event background

A large-scale attack occurred on the chain from 21:10 on July 30 to 06:00 on July 31, resulting in the loss of funds in multiple Curve pools. The vulnerabilities are all due to a reentrant lock failure in certain versions of Vyper.

attack analysis

Through preliminary analysis of the transaction data on the chain, we summarized the transactions attacked and further analyzed the attack process because the attack involved multiple transaction pools.
pETH/ETH pool was attacked and traded:
https://etherscan.io/tx/0xa84aa065ce61dbb1eb50ab6ae67fc31a9da50dd2c74eefd561661bfce2f1620c
msETH/ETH pool was attacked and traded:
https://etherscan.io/tx/0xc93eb238ff4263252 5e990119d3edc7775299a70b56e54d83ec4f53736400964
alETH/ETH pool was attacked transaction:
https:// etherscan.io/tx/0xb676d789bb8b66a08105c844a49c2bcffb400e5c1cfabd4bc30cca4bff3c9801
CRV/ETH pool was attacked for transactions:
https://etherscan.io/tx/0x2e7dc8b2fb7e25fd00ed9565dcc0ad
4546363171d5e00f196d48103983ae477c https://etherscan.io/tx/0xcd99fadd7e28a42a063e07d9d86f67c88e10a7afe5921bd28cd1124924ae2052
Since the attack process is basically the same, we mainly attack pETH/ Detailed analysis of ETH pool attack transactions:
0xa84aa065ce61dbb1eb50ab6ae67fc31a9da50dd2c74eefd561661bfce2f1620c
The transaction is
called the attack contract 0x9420F8821aB4609Ad9FA514f8D2F5344C3c0A6Ab by 0x6ec21d1868743a44318c3c259a6d4953f9978538, and the one-time attack contract 0x466b85b49ec0c5c1eb402d5ea3c is created by this contract. 4b88864ea0f04
, and carry out the subsequent attack process in the constructor of the one-time attack contract;
image.png

The attacker obtained 80,000 WETH from Balancer through a flash loan and withdrew all of it into ETH through the contract.
image.png

Immediately thereafter, 40,000 ETH liquidity was provided to Curve’s pETH/ETH pool and approximately 32,431.41 pETH-ETH LP Tokens were received.
image.png

Then the liquidity removal function is called in the attack contract, but we can see from the contract function call stack that the contract returns to calling the fallback function of the contract itself when executing the liquidity removal, and in the fallback function The add liquidity operation of the trading pair is called again.
image.png

According to the pETH/ETH trading pair contract source code analysis, the contract is called again using the contract's fallback function during transfer. Contract reentry occurs here, but the LP contract uses reentrancy locks when adding liquidity and removing liquidity. ,As shown below:
image.png

However, reentrancy still occurred in the actual call stack, resulting in another 40,000 ETH being added to the LP Token through the attacker contract and approximately 82,182.76 pETH/ETH LP Tokens were obtained, and continued to be removed after the callback function of the attack contract ended. The initially added 32,431.41 pETH/ETH Lp Token received approximately 3,740.21 pETH and 34,316 ETH.
image.png

Then the liquidity removal function was called, and approximately 10,272.84 pETH/ETH LP Token was removed to obtain approximately 1,184.73 pETH and 47,506.53 ETH.
image.png

The remaining more than 70,000 pETH/ETH LP Tokens still remain in the attacker's contract, as shown in the figure below:
image.png
Next, the attacker exchanged approximately 4,924.94 pETH for 4,285.10 ETH through the Curve pETH/ETH pool.

Finally, the attacker converted approximately 86,106.65 ETH into WETH, returned 80,000 WETH of flash loan funds to Balancer, and transferred approximately 6,106.65 WETH of profit funds to the address 0x9420f8821ab4609ad9fa514f8d2f5344c3c0a6ab.
image.png

At this point, the analysis of the attack process on the pETH/ETH pool has been completed. It is a very classic re-entry profit operation. However, by analyzing the source code of the attacked contract, we found that the contract has a corresponding re-entry lock mechanism. Normally, It can prevent reentrancy operations, but it does not deny the attacker's reentrancy operations;
we review the description of reentrancy locks in Vyper and know that the reentrancy lock implementation uses the specified slot at the beginning of the function to store whether it is locked. operation.
image.png

We will decompile and view the bytecode of the attacked LP contract:
https://library.dedaub.com/ethereum/address/0x466b85b49ec0c5c1eb402d5ea3c4b88864ea0f04/decompiled
image.png

It can be seen that the slots for storing reentrant locks in the two functions are not consistent, which causes the reentrant locks to become invalid, which in turn can be exploited by attackers for profit.
The Vyper project official also tweeted that there is indeed a reentrancy lock failure in some versions.
image.png

By comparing its 0.2.14 version with its 0.2.15 version, it was found that there are changes in the reentrancy lock-related settings file data_positions.py corresponding to Vyper. The modified code separately sets the storage key of the reentrancy lock, and , each reentrant lock will occupy a different storage slot, resulting in the contract's reentrant lock function being unavailable.

This bug has been fixed in PR: #2439 and #2514
which fixed the issue of adding multiple reentrant storage slots, see the figure below for details:
image.png

event summary

This attack involves a wide range of attacks. The root cause is that the 0.2.15, 0.2.16, and 0.3.0 versions of the smart contract infrastructure Vyper have unreasonable reentrancy lock designs, which leads to the later use of these versions. The reentry lock failed in the project and was eventually hacked.

  • It is recommended to select a stable technology stack and corresponding version during project development, and conduct strict testing on the project to prevent similar risks.

Guess you like

Origin blog.csdn.net/weixin_28733483/article/details/132711264