Background
Blast was created by Blur founder Pacman (Tieshun Roquerre, The Ethereum Layer2 network launched by aka. Tieshun launched the mainnet on February 29. Currently, approximately 19,500 ETH and 640,000 stETH are pledged on the Blast mainnet.
The attacked project Munchables is a high-quality project that won the Bigbang competition organized by Blast.
Blast official will issue ordinary points to users who pledge ETH on the Blast main network:
In order to encourage users to participate in DeFi projects on the Blast ecosystem , Blast officials will select high-quality projects for recommendation, and encourage users to pledge ETH a second time into DeFi to obtain faster points increase and gold points. Therefore, a considerable number of users pledge ETH on the Blast main network. Arrived at the newly created DeFi project.
The maturity and security of these DeFi projects have yet to be examined. Whether these contracts have sufficient security considerations to safeguard users’tens of millions, Even hundreds of millions of dollars.
Incident Overview
Less than a month after the Blast mainnet was launched, an attack on SSS occurred on March 21, 2024 Token (Super Sushi Samurai) attack, there is a transfer logic error in the Token contract, which allows the attacker to increase the SSS Token balance of the specified account out of thin air. In the end, the project lost more than1310 ETH (approximately $4.6 million).
Less than a week after the SSS Token attack, another larger attack occurred on Blast. The Munchables project was swept away by the attacker. 17413.96 ETH was taken away, a total of approximately 62.5 million US dollars.
Half an hour after the attack transaction occurred, 73.49 WETH in the project contract was also stolen by a hacker at another address.
At this time, there are still 7276 WETH, 7758267 USDB, and 4 ETH stored in the project's contract address, which may fall into the hands of hackers at any time. The hackers had access to all the funds in the entire project, leaving a total of about $97 million at risk.
In the immediate aftermath of the incident, X (Twitter)’s well-known on-chain detective zachXBT pointed out that the root cause of this attack was due to the hiring of hackers from a certain country. To.
Let's take a closer look at how a "hacker from a certain country" completed an attack worth nearly $100 million.
Live restoration
[UTC+0] 21:37, March 26, 2024 (5 minutes after the attack ), Munchables officially posted on X (Twitter) stating that it was under attack.
According to the investigation of on-chain detective Zach We hired the Munchables attacker to do some game development work. He was very rough and really looked like a Chinese hacker, and we fired him within a month. He also tried to get us to hire one of his friends, who was probably He is also a hacker."
Since this attack caused huge losses to users in the community, we immediately launched an on-chain investigation. Let’s take an in-depth look at this "a certain country" Hacker's attack details.
[UTC+0] At 21:32 on March 26, 2024, an attack involving 17413.96 ETH occurred.
We can see this attack transaction through Blastscan: https://blastscan.io/tx/0x9a7e4d16ed15b0367b8ad677eaf1db6a2a54663610696d69e1b4aa1a08f55c95
Damaged contract (0x29..1F ) is a proxy contract that stores the user's pledged funds. We can see that the attacker called the unlock function of the pledge contract, passed all permission checks, and transferred all the ETH in the contract to the attacker's address 1. (0x6E..c5).
It seems that the attacker called an unlock function similar to withdraw behavior and took away most of the ETH on the damaged contract (0x29..1F).
Did the project party forget to lock the vault?
The unlockin the damaged contract (0x29..1F) has two related checks, let’s look at them one by one.
First of all, we found that in the process of verifying permissions, the isRegistered method of the contract (0x16..A0) was called to view the current msg.sender, also That is, whether hacker address 1 (0x6E..c5) has been registered:
The answer is: passed the verification.
This involves the contract (0x16..A0) and its corresponding latest logical contract (0xe7..f1)
[UTC+0]2024 At 08:39 on March 24, 2019 (2 days before the attack), the logical contract corresponding to the contract (0x16..A0) was upgraded.
Logic contract upgrade transaction:
https://blastscan.io/tx/0x9c431e09a80d2942319853ccfdaae24c5de23cedfcef0022815fdae42a7e2ab6
The logic contract is updated to 0xe7..f1.
The original logical contract address can be seen here, which is 0x9e..CD.
https://blastscan.io/tx/0x7ad050d84c89833aa1398fb8e5d179ddfae6d48e8ce964f6d5b71484cc06d003
At this time, we suspect that the hacker is updating the logic implementation contract of the agent contract, which will be 0x9e. .CD becomes malicious 0xe7..f1, completing the bypass of verification permissions.
Is this really the case?
In Web3.0, you never need to guess or listen to others. You only need to master the technology to get the answer yourself.
By comparing the two contracts (not open source contracts), there are some obvious differences between the original 0x9e..CD contract and the updated 0xe7..f1:< /p>
The initialize function part of 0xe7..f1 is implemented as follows:
The initialize function part of 0x9e..CD is implemented as follows:
As you can see, the attacker In the original logical contract (0x9e..CD), the attacker's address (0x6e..c5) is set to register, and two other attacker addresses 0xc5..0d and 0xbf..87 are also registered. And their field0 is set to the block time during initialization. The use of field0 will be explained later.
In fact, contrary to what we guessed, the real logic contract with a backdoor existed at the beginning, and was updated later. is normal!
Wait, this update appeared at 08:39 on March 24, 2024 [UTC+0] (2 days before the attack ), that is, before this incident, the logic contract has become a contract without backdoor. Why can the attacker still complete the attack later?
This is because of delegatecall, so the actual state storage update is in the contract (0x16..A0), which also results in the logical contract even after After being updated to the logical contract 0xe7..f1 without backdoor, the changed slot in the contract (0x16..A0) will still not be restored.
Let's verify:
As you can see, the corresponding slot in the contract (0x16....A0) has a numerical value.
This allows the attacker to pass the isRegistered method verification:
The attacker later replaced the backdoor contract with a normal contract to deceive others. In fact, the backdoor had already been Plant.
In addition, the unlock process also involves the second verification:
For the lock time check, this part is to ensure that the locked assets will not be transferred before expiration.
The attacker needs to ensure that the block time when unlock is called is greater than the required lock expiration time (field3).
This part of the verification involves the damaged contract (0x29..1F) and the corresponding logical contract 0xf5..cd.
In the transaction at 11:54 on March 21, 2024 [UTC+0] (5 days before the attack),
< p style="text-align: left;">https://blastscan.io/tx/0x3d08f2fcfe51cf5758f4e9ba057c51543b0ff386ba53e0b4f267850871b88170
We can see that the original logical contract of the damaged contract (0x29..1F) contract is 0x91..11, And just four minutes later, at
https://blastscan.io/tx/0xea1d9c0d8de4280b538b6fe6dbc3636602075184651dfeb837cb03f8a19ffc4f
was upgraded to 0xf5..cd.
We also compare the two contracts, and we can find that the attacker also made tricks in the initialize function as before,
Partial implementation of the initialize function of 0xf5..cd:
Partial implementation of the initialize function of 0x91..11:
As you can see, it is obvious that the same technique is used again. He tampered with the amount of ETH he held and the unlocking time, and then replaced it with the normal contract to deceive others. When the project team and security researchers debugged, all the logic contracts they saw were normal, and because the contracts were all As the contract is not open source, it is even more difficult to see the core of the problem.
So far, we understand this transaction involving 17413 ETH and how the attacker did it, but is there only this much information behind this incident?
In our above analysis, we actually saw that the hacker built 3 addresses into the contract:
0x6e..c5 (attacker address 1)
0xc5..0d (attacker address 2)
0xbf..87 (attacker address 3)
Only one of the attack transactions we found above Seeing 0x6e..c5, what did the other two addresses do? And what secrets are hidden in address(0), _dodoApproveAddress, and _uniswapV3Factorty?
Let’s first take a look at attacker address 3 (0xbf..87), which stole 73.49 WETH through the same method:
https://blastscan.io/tx/0xfc7bfbc38662b659bf6af032bf20ef224de0ef20a4fd8418db87f78f9370f233
And attack the source address of gas (0x97..de) , while providing handling fees to both 0xc5..0d (attacker address 2) and 0xbf..87 (attacker address 3).
The source of the 0.1 ETH that attacks the gas source address (0x97..de) comes from owlto.finance (cross-chain bridge).
0xc5..0d (attacker address 2) did not carry out any attack after receiving the handling fee, but it actually shouldered a hidden plan. We Keep reading.
In fact, according to the official rescue transaction, it turns out that there are more than 73.49 weth on the damaged contract (0x29..1F) address. Until the attack is over, there will be no more than 73.49 weth. There are still 7276.5 WETH & 7758267 USDB.
Rescue deal:
https://blastscan.io/tx/0x1969f10af9d0d8f80ee3e3c88d358a6f668a7bf4da6e598e5be7a3407dc6d5bb
p>
Originally the attacker planned to steal these assets. You can see that the address 0xc5..0d (attacker address 2) was originally used to steal USDB.
The _dodoApproveAddress here is 0x0000000000000000000000043000000000000000000000000000000000003
< p style="text-align: left;">is the address of usdb
0xbf..87 (attacker address 3) This address is used to steal weth:
The _uniswapV3Factory here is 0x0000000000000000000000004300000000000000000000000000000000 00004 p>
For weth’s address
And 0x6e..c5 (attacker address 1) is responsible for stealing address(0), which is the native asset ETH.
By setting field0, the attacker can steal the corresponding assets through the following logic:
Question
Why didn’t the attacker steal all the assets?
Theoretically, he can steal all the assets, namely the remaining WETH and USDB.
0xbf..87 (attacker address 3) only stole 73.49 WETH, 0xbf..87 (attacker address 3) can actually steal all 7350 WETH is taken away. You can also use 0xc5..0d (attacker address 2) to take away all 7758267 USDB. Why it stopped after taking only a little WETH is unknown to us. It may require a well-known chain detective to go deep inside. of investigation.
https://blastscan.io/tx/0xfc7bfbc38662b659bf6af032bf20ef224de0ef20a4fd8418db87f78f9370f233
Why Didn’t the attacker transfer 17413ETH to the Ethereum mainnet?
As we all know, it is possible for the Blast mainnet to intercept these ETH through a centralized method and let it stay permanently Here, there will be no substantial user losses, but once these ETH enter the Ethereum main network, there is no way to intercept it.
We have evaluated the current cross-chain bridges of Blast. There is no limit on the number of official cross-chain bridges, but they require 14 days to exit, so it is enough for Blast officials to prepare. Interception plan.
The third-party cross-chain bridge can be credited in near real-time, just like the attacker’s source of fees, and the cross-chain can be completed quickly. Why is the attack Didn’t the person cross-chain immediately?
In fact, the attacker carried out cross-chain at the first time (within 2 minutes of the attack):
https://blastscan.io/tx/0x10cf2f2b884549979a3a1dd912287256229458ef40d56df61738d6ea7d9d198f
And it took 20 seconds for the funds to arrive on the Ethereum main network. In theory, attackers can continue to cross-chain , a large amount of ETH can be transferred across chains before manual intervention by the cross-chain bridge.
As for why it can only be 3 ETH at a time, the reason is the liquidity limit of the cross-chain bridge, from Blast to ETH:
Another cross-chain bridge that supports Blast supports even less:
After this cross-chain transaction, the attacker did not continue other cross-chain operations. The reason is unknown to us. It seems that the "hacker from a certain country" did not make adequate preparations for the withdrawal of funds from Blast.
Development of events after the attack
According to community user Nearisbuilding Based on the feedback, he found more identity information of the attacker and found ways to prompt the attacker to return the funds.
https://twitter.com/Nearisbuilding/status/1772812190673756548
In the end, with the attention and efforts of the encryption community, "hackers from a certain country" provided the above three attackers to the project, perhaps because they were afraid of exposing their identities. The private key of the address and returned all funds. The project team also conducted a rescue transaction and transferred all the funds of the damaged contract to the multi-signature contract for safekeeping.