DeFiVulnLabs靶场全系列详解(四十七)逻辑错误-合约锁定处理错误导致可多次提款

admin 2025年6月7日00:18:05评论0 views字数 3446阅读11分29秒阅读模式

01

前言

此内容仅作为展示Solidity常见错误的概念证明。它严格用于教育目的,不应被解释为鼓励或认可任何形式的非法活动或实际的黑客攻击企图。所提供的信息仅供参考和学习,基于此内容采取的任何行动均由个人全权负责。使用这些信息应遵守适用的法律、法规和道德标准。

DeFiVulnLabs一共有47个48个漏洞实验,包括各种经典的合约漏洞和一些少见的可能造成安全问题的不安全代码,本系列将逐一解析每个漏洞,包括官方的解释和自己的理解。

    本篇是这个系列的最后倒数第二篇文章,且看且珍惜。

    发现新增了一个漏洞Transient Storage Misuse

02

逻辑错误-合约锁定处理错误导致可多次提款

漏洞解析:

该漏洞是非常典型的逻辑错误问题,单纯是因为开发者脑子一糊涂没注意想当然的情况下所产生的。攻击者可以通过来漏洞来进行多次提款。

代码地址:

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

代码解析:

合约本身是一个存在漏洞的银行,然后存在一个CreateLocker函数和unlockToken

函数,然后在unlockToken里存在漏洞,导致可以多次提款。

// SPDX-License-Identifier: MITpragma solidity ^0.8.20;import"@openzeppelin/contracts/token/ERC20/IERC20.sol";//一个存在漏洞的银行系统合约contract VulnerableBank {    struct Locker {        bool hasLockedTokens;        uint256 amount;        uint256 lockTime;        address tokenAddress;    }//嵌套字典//{address:{id:Locker}}    mapping(address => mapping(uint256 => Locker)) private _unlockToken;    uint256 private _nextLockerId = 1;//创建锁定functioncreateLocker(        address tokenAddress,        uint256 amount,        uint256 lockTimepublic{//存入代币必须大于0require(amount > 0"Amount must be greater than 0");//解锁的时间大于当前区块时间require(lockTime > block.timestamp"Lock time must be in the future");//发送者上toeknAddress的地址必须大于amountrequire(            IERC20(tokenAddress).balanceOf(msg.sender) >= amount,"Insufficient token balance"        );//调用transferFrom将代币转移到银行合约中        IERC20(tokenAddress).transferFrom(msg.senderaddress(this), amount);// 然后创建锁定时间,主要是hasLockedTokens=True        Locker storage locker = _unlockToken[msg.sender][_nextLockerId];        locker.hasLockedTokens = true;        locker.amount = amount;        locker.lockTime = lockTime;        locker.tokenAddress = tokenAddress;        _nextLockerId++; //给这笔存款添加一个id    }//解锁代币并转账functionunlockToken(uint256 lockerId) public{//获取lockid下的Locker        Locker storage locker = _unlockToken[msg.sender][lockerId];// 获取存放代币的值        uint256 amount = locker.amount;//判断是否 hasLockedTokens=True  ,也就是Bank里是否还存在没解锁的tokenrequire(locker.hasLockedTokens"No locked tokens");// 如果当前区块时间大于解锁的时间,代币则置零if (block.timestamp > locker.lockTime) {            locker.amount = 0;        }//然后转账//这里乍一看没问题,但是实际上上面如果当前区块时间小于解锁的时间,代币就不置零//那么也就意味着locker.amount不会为0,我们无限调用unlockToken即可        IERC20(locker.tokenAddress).transfer(msg.sender, amount);    }}

合约部署,如果出现问题,可能是如下原因所导致的

DeFiVulnLabs靶场全系列详解(四十七)逻辑错误-合约锁定处理错误导致可多次提款

两个函数的调用createLocker主要存放Token,Token数量,以及锁定时间,在remix不大好复现,原因是需要输入一个TokenAddress,但是这个值不好确定。

DeFiVulnLabs靶场全系列详解(四十七)逻辑错误-合约锁定处理错误导致可多次提款
DeFiVulnLabs靶场全系列详解(四十七)逻辑错误-合约锁定处理错误导致可多次提款

03

foundry复现

可以在foundry里进行复现,以下是漏洞利用时的截图,
1、可以看到一开始铸造了20W的代币,给alice和银行VulnerableBank分别转了1W和10W,因此代币合约里剩余9W
    此时  Alice  1W   银行合约10W。
DeFiVulnLabs靶场全系列详解(四十七)逻辑错误-合约锁定处理错误导致可多次提款
2、Alice 给银行转入1W代币进行锁仓1天,此时VulnerableBank银行存放11W代币。
DeFiVulnLabs靶场全系列详解(四十七)逻辑错误-合约锁定处理错误导致可多次提款
3、Alice利用漏洞调用了 VulnerableBank 合约的 unlockToken 函数,解锁代币。如果当前时间小于锁仓时间,那么amount就不会置为0,并且通用触发transfer。
     unlockToken 函数没有在每次调用时将 locker.amount 置零,Alice 可以无限次调用 unlockToken 函数,每次都会转移代币。

    Alice 利用这个漏洞,将 VulnerableBank 合约中的 110,000 个代币全部提取出来

DeFiVulnLabs靶场全系列详解(四十七)逻辑错误-合约锁定处理错误导致可多次提款
04
如何修复该问题
    看看修复方式,可以看到仅仅是增加了require(block.timestamp > locker.lockTime, "Tokens are still locked"); 这一行代码判断了时间。
    也就是如果锁仓时间没有到,那么就直接抛出异常,而不是像之前的一样时间没到还会继续执行transfer。
contract FixedeBank { ....functioncreateLocker(.....    }function unlockToken(uint256 lockerId) public {        Locker storage locker = _unlockToken[msg.sender][lockerId];require(locker.hasLockedTokens"No locked tokens");require(block.timestamp > locker.lockTime"Tokens are still locked");// Save the amount to a local variable        uint256 amount = locker.amount;//         locker.hasLockedTokens = false;        locker.amount = 0;// Transfer tokens to the locker owner        IERC20(locker.tokenAddress).transfer(msg.sender, amount);    }}
05
感谢关注
个人语雀账号:https://www.yuque.com/iceqaq

原文始发于微信公众号(Ice ThirdSpace):DeFiVulnLabs靶场全系列详解(四十七)逻辑错误-合约锁定处理错误导致可多次提款

免责声明:文章中涉及的程序(方法)可能带有攻击性,仅供安全研究与教学之用,读者将其信息做其他用途,由读者承担全部法律及连带责任,本站不承担任何法律及连带责任;如有问题可邮件联系(建议使用企业邮箱或有效邮箱,避免邮件被拦截,联系方式见首页),望知悉。
  • 左青龙
  • 微信扫一扫
  • weinxin
  • 右白虎
  • 微信扫一扫
  • weinxin
admin
  • 本文由 发表于 2025年6月7日00:18:05
  • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                   DeFiVulnLabs靶场全系列详解(四十七)逻辑错误-合约锁定处理错误导致可多次提款https://cn-sec.com/archives/4139955.html
                  免责声明:文章中涉及的程序(方法)可能带有攻击性,仅供安全研究与教学之用,读者将其信息做其他用途,由读者承担全部法律及连带责任,本站不承担任何法律及连带责任;如有问题可邮件联系(建议使用企业邮箱或有效邮箱,避免邮件被拦截,联系方式见首页),望知悉.

发表评论

匿名网友 填写信息