Detailed explanation of Ethereum smart contract vulnerabilities
— On-chain vulnerability recurrencecall and delegatecall
Detailed explanation of Ethereum smart contract vulnerabilities — On-chain vulnerability recurrencecall and delegatecall
Welcome to follow and discuss with us
Author: support@lunaray.co
0x01 Introduction
Let’s briefly introduce call and delegatecall
- call: When calling functions of other contracts, the code is executed in the environment of the called contract, and the value of the built-in variable msg will be modified to the caller after the call.
- delegatecall: When calling functions of other contracts, the code is executed in the environment of the contract that called the function.
delegatecall is tricky to use, and misuse or incorrect understanding can lead to devastating results.
0x02 Notice
- delegatecall saves the context (store, caller, etc…)
- The storage layout of the contract calling delegatecall and the called contract must be the same
0x03 Vulnerability example
The following is an example of a vulnerable contract and attack:
there are the following 5 steps:
- Account A deploys Lib
- Account A uses the Lib address to deploy HackMe
- Account B uses the HackMe address to deploy Attack
- Account B calls Attack.attack()
- Attack is now the owner of HackMe
When the attack function is finally called, if the transaction fee is insufficient, such as:
Then you can try to increase the upper limit of the transaction fee in the transaction confirmation step:
We can see on-chain whether the transaction was successful or not:
https://kovan.etherscan.io/tx/0xbaa58712740181a425852e492dfaac62ab44fd2285c8b342b2f2ea8882fcb72a
what happened?
- Account B calls Attack.attack()
- 2. Attack the function selector that calls HackMe’s fallback function to send pwn()
- HackMe uses delegatecall to forward calls to Lib
- msg.data contains the function selector for pwn()
- This tells Solidity to call the function pwn() in Lib
- The function pwn() updates the owner to msg.sender
- Delegatecall uses HackMe’s context to run Lib’s code
- So HackMe’s store is updated to msg.sender, where msg.sender is the caller of HackMe, in this case Attack
0x04 more complex vulnerabilities
The operation process is exactly the same as before:
0x05 On-chain transaction information:
https://kovan.etherscan.io/tx/0x712863d4a3720ab6617573dfd6a2129ed501533df35e8581c7c2cc2064a3bd8b
so what happened?
Note that state variables are defined differently in Lib and HackMe. This means that calling Lib.doSomething() will change the first state variable inside HackMe, which happens to be the address of lib.
Inside attack() , the first call to doSomething() changes the address where lib is stored in HackMe. The address of lib is now set to Attack. The second call to doSomething() calls Attack.doSomething() , where we change the owner.
0x06 Defense method
Currently, stateless libraries are recommended for this vulnerability.