Analyzing the attack methods against THE DAO from a technical perspective

Analyzing the attack methods against THE DAO from a technical perspective

The content of this article is not original, but comes from the translation and interpretation of the following two blog posts.

Blog 1: http://vessenes.com/more-ethereum-attacks-race-to-empty-is-the-real-deal/
Blog 2: http://vessenes.com/deconstructing-thedao-attack-a-brief-code-tour/

1. Decoding the attack method

Since the attacker is creating a childDAO and continuously transferring Ether into it, this is currently the only viable mechanism to extract Ether, so the focus starts with the splitDAO function.

splitDAO will create a childDAO (if it does not exist), transfer the Ether owned by the splitter to the childDAO, pay any spawned Reward (currently should be 0) and then return.

According to the design of the white paper, the original intention of splitDAO is to protect the minority in a disadvantaged position in voting and prevent them from being legally exploited by the majority through voting. By splitting off a small-scale DAO, they are given a mechanism to vote with their feet, while still ensuring that they can obtain the possible benefits generated by external funding before the split.

But the road to hell is paved with flowers.

According to BLOG 2, in DAO.sol, the function splitDAO has this line:

In the contract, the balance of dao currency recorded for msg.sender is reset to zero, the total amount of dao currency totalSupply is deducted, etc., all of which occur after sending it back to msg.sender. This is a typical "anti-pattern" pointed out by the blogger in Blog 1.

Next, let’s look at the withdrawRewardFor function. The latest code currently available on GitHub is not the code deployed on Ethereum livenet. The blogger said that the problematic code is as follows:

paidOut[_account] += reward was placed after the payOut function call in the original code, but was moved before payOut in the latest github code.
Let’s look at the payOut function call. The type of rewardAccount is ManagedAccount, which can be seen in ManagedAccount.sol:

Note the line marked with a depth: a call is made to _recipient to transfer _amount Wei. By default, the call will use all the remaining gas. The number of code steps executed by the call may be large, and is basically limited only by the available gas of the message sent by the attacker.
Putting these together, the hacker's attack method emerges:
1) Preparation

The hacker creates his own hacker contract HC, which comes with an anonymous fallback function. According to the solidity specification, the fallback function will be automatically executed when HC receives Ether (without data). This fallback function will trigger multiple calls to THE DAO's splitDAO function through recursion (but not too many times to avoid insufficient gas). The current call depth should also be recorded in the process to control stack usage.

2) Start the attack <br/>The hacker submits split proposals to THE DAO multiple times, and sets the recipient address of each proposal to the HC address, and sets an appropriate gasLimit. The call stack will be like this:


Submit a split proposal
—> splitDAO function (No. 1)
—> withdrawRewardFor function (No. 1, the hacker’s dao balance and dao total amount have not changed at this time!)
—> papOut function (No. 1, first time sending ether to HC)
—> HC fallback function (No. 1)
—->If the recursion does not reach the preset depth: call the split DAO function (No. 2)
—> withdrawRewardFor function (No. 2, the hacker dao balance remains unchanged!)
—> payOut function (No. 2, sending ether to HC for the second time)
—> HC fallback function (No. 2)
—> (continue recursion)

3) Transfer the money and leave <br/>The money transferred to childDAO can be withdrawn according to the original contract after a certain period of time. It is time for hackers to reap the profits.

2. Prevention and Thinking

Judging from the code, there are two factors that led to the success of this attack: one is that the order of the two steps of dao balance deduction and Ether transfer is wrong, and the other is the unrestricted execution of unknown code.

In terms of the order of application code, the balance of dao should be deducted before transferring Ether, because the balance check of dao is a prerequisite for transferring Ether, and the balance status of dao must be able to reflect the latest status in a timely manner. In the implementation of the problematic code, although the deepest recursion returns and successfully deducts the hacker's dao balance, the deduction of the hacker's dao balance is useless at this time, because the balance checks in the recursive calls above it have all ended successfully, and there is no chance to determine the latest balance.

Regarding the unrestricted execution of unknown code, although hackers currently use the anonymous fallback function provided by Solidity, this execution of unknown code can in principle occur in more scenarios, because the message passing between contracts is completely similar to the method call in object-oriented program development, and providing an interface to wait for callbacks is a common technique in design patterns, so it is entirely possible to execute an unknown ordinary function.

Similar hacking incidents are not limited to Ethereum, and are likely to happen again on platforms such as Rootstock in the future. This is because the vulnerability is at the application level, not a problem with Ethereum itself, and cannot even be attributed to "Turing completeness" because this attack can work even on a non-Turing complete platform. In general, the more complex the application, the higher the probability of security issues in the application.

This hacking incident has given us a lot to think about: Should we trust unknown code on TRUST MACHINE? Should decentralized systems include emergency intervention codes at the beginning of their design to prepare for "temporary suspension"? Should there be contingency plans in terms of public opinion control and information disclosure after problems occur? Should projects be subject to longer community review and testing before going online?

This hacking incident does not mean the end of Ethereum, decentralization, or blockchain. Although the lesson is profound, if we can learn from it, it will not only benefit THE DAO and Ethereum, but the entire blockchain community.


<<:  A Beihang University graduate: Earned 500 million from Bitcoin and became a shareholder of a listed company

>>:  What went wrong with Proof of Stake (PoS)?

Recommend

Why is it said that Wuyou's tears will hurt people?

No emotion arises without reason. If there is, it...

Ethereum Developer Virgil Griffith Jailed Again After Checking Coinbase Accounts

Ethereum developer Virgil Griffith has violated t...

People with fleshy hands have very good fortunes? Why?

The hands of different people are different. Some...

The worst female star

The female celebrity with the ugliest face. Pleas...

What does a branched lifeline mean?

There are three palm lines in our palms, which ar...

Bitcoin mining difficulty is about to rise by 8.91%

According to BTC.com data, the difficulty of Bitc...

Fidelity: Why Corporate Treasury Should Consider Bitcoin

Written by Ria Bhutoria and Tess McCurdy, both fr...

Philtrum face reading

Everyone has a long and thin line under the nose,...

Picture of a woman with wide cheekbones

The word "zygomatic" means "power&...

In-depth analysis of stETH depegging: a false alarm or another crypto crisis?

What is Lido? Cobie published a blog post introdu...