Skip to content

Latest commit

 

History

History

Folders and files

NameName
Last commit message
Last commit date

parent directory

..
 
 
 
 
 
 
 
 
 
 
 
 

DAO maker

Step-by-step

  1. Call init to set yourself as owner
  2. Call emergencyExit to withdraw tokens

Detailed Description

On Sept 03, 2021 an attacker stole over 4MM USD in various tokens from an DAOMaker.

The attacker called init, which is not access-controlled, and then called emergencyExit withdrawing the tokens held.

The vulnerability is hard to detect as contracts were not verified, thus the source code is not readily available.

Nevertheless, we can see the first attack tx calls an init method with a sighash 84304ad7. The exploited contract is simply a universal-proxy-like, which delegates call to an implementation that holds the actual upgrade logic. This implementation contract did not prevent an arbitrary address to call its init method.

The init method sets as owner anyone who calls it. You can check the decompilation and look for the unknown84304ad7 method, as the decompiler calls it. Look at the bottom, you will see owner = caller.

def unknown84304ad7() payable: 
  require calldata.size - 4 >= 128
  require cd <= 4294967296
  require cd <= calldata.size
  require ('cd', 36).length <= 4294967296 and cd * ('cd', 36).length) + 36 <= calldata.size
  require cd <= 4294967296
  require cd <= calldata.size
  require ('cd', 68).length <= 4294967296 and cd * ('cd', 68).length) + 36 <= calldata.size
  ...
    log OwnershipTransferred(
        address previousOwner=owner,
        address newOwner=caller)
  owner = caller

We can be sure this transaction triggered because there is an event in the event list. See that the first one sets it from zero to an OK address, then after a while from the OK address to the attacker's.

This allowed the attacker to call emergencyExit (sighash: a441d067) which is onlyOwner protected.

In his twitter thread, Mudit Gupta suggests that the attacker was using a browser wallet as the calls where made separeterly without a contract and the browser wallet built-in swap was used.

Also, the contract attacked was not verified. The fact that the attacker used only an EOA to perform the attack on a non verified contract suggests that maybe the attacker had insider-knowledge of this vulnerability.

Possible mitigations

  • initialize functions should always be protected so they can be called only once

Diagrams and graphs

Overview

Overview

Entity and class diagram

PlantUML

Sources and references