Audios protocol hack analysis
Audius is a fully decentralized music platform. Own the masters & the platform. Audius was hacked Saturday losing about $6 million worth of Ethereum-based AUDIO tokens. The 18.6 million AUDIO tokens were re-sold for 705 ETH ($1.1 million) and funneled through a transaction mixing service.
0x02 Attack information
· Attacker’s address
· Attack Transactions
· Attack Contracts
· Attacked Contracts Governance
0x03 Attack steps
- Attackers deploy attack contracts
- the attacker evaluates whether the current 84 proposal has passed by the evaluateProposalOutcome method (the 84 proposal is initiated by the attacker, but lacks the conditions for the proposal to pass)
- Initiate a new proposal 85 for the transfer of a large amount of funds to 0xbdbb5945f252bc3466a319cdcc3ee8056bf2e569 via the transfer method.
4. call the Staking.initialize initialization method to set the attacker contract address to the administrator address (note: why the attacker can call the initialization method)
5.Call the DelegateManagerV2.initialize initialization method to update the administrator address
6.Call DelegateManager.setServiceProviderFactoryAddress update serviceProviderFactoryAddress
7.Call delegateStake method to delegate a large number of votes to the attacker’s contract address
8. The attacker calls the submitVote method to vote
9. The attacker calls the evaluateProposalOutcome method to evaluate the 85 proposal passed and successfully completed the transfer.
0x04 Core of the attack
Three conditions in the initializer() modifier judgement.
initializing: initially false, also false when the method is finished.
isConstructor()：When initially deploying a contract, the code is still undeployed when the constructor is run, and any check on its code size yields zeros.
initialized: Initialized to true to satisfy the condition, modified to false at the end of method execution, no secondary calls can be made.
Normal calls to initialize contracts, methods modified by initializer can only be called once, here the attacker has made calls in multiple contracts, why is it like that?
Proxy contracts exist on the Audius platform， The Governance contract is called by the proxy contract and the modifiers in the initialisation contract are called by the Governance contract when deployed.
The initialization results in the determination of the governanceAddress address, which exists in the first card slot, and the modifier condition for this initialization, where the boolean value of the variable is also stored in the first card slot, resulting in a storage conflict, after which the initializing variable remains true. initializer() modifier can be called multiple times.
0x05 Source and flow of funds
Attackers took by Tornado.Cash platform on Binance chain
Flow of funds
The attackers have now transferred their profits to the Tornado.Cash platform.
Although multiple storage conflicts are declared in the official openzeppelin proxy model, unexpected storage conflicts can occur when multiple logics are combined together. Audius has now officially added a judgement condition to the initialisation modifier to prevent secondary exploitation, and added storage parameters to the initialisation contract.