漏洞说明
这个漏洞简要概括就是因为,函数权限没有控制好,导致代币价格被操纵。攻击者利用合约中大量已经授权的用户购买代币提升代币价格,从而获利。
漏洞分析
漏洞相关信息
漏洞合约:0xAE975a25646E6eB859615d0A147B909c13D31FEd
攻击交易: 0xdb9a13bc970b97824e082782e838bdff0b76b30d268f1d66aac507f1d43ff4ed
漏洞复现
合约分析
本次漏洞合约是公开的,依照惯例,先分析漏洞合约和漏洞点。
本地漏洞函数是在buyMiner
1 | function buyMiner(address user,uint256 usdt)public returns (bool){ |
address user,对于传入的user地址没有任何的限制,导致可以操作已经approve给当前合约的用户可以操作user使用自己的usdt购买
ULME代币1
2
3IERC20(_usdt_token).transferFrom(user,address(this),usdt);
....
IUniswapV2Router01(_roter).swapExactTokensForTokens(usdt,1000000,token,k,block.timestamp+60);
结合这两个漏洞点,就可以操作所有approve给当前合约的用户购买ULME的代币,进而提高ULME代币的价格。
攻击分析
调用栈分析
基于 0xdb9a13bc970b97824e082782e838bdff0b76b30d268f1d66aac507f1d43ff4ed 分析调用过程:
步骤一:闪电贷
通过DODO闪电贷,贷出大量的BUSD
步骤二:买入ULME代币
通过调用栈,可以看到攻击者将1000000个BUSD兑换为LUME代币
步骤三:调用buyMiner

可以看到攻击者传入了用户(0x4a005e5e40ce2b827c873ca37af77e6873e37203)和对应的授权BUSD数量(153067360139278283909712)购买ULME代币。
说明攻击者是提前收集了所有的授权了当前合约的用户已经可用的BUSD的数量。
步骤四:重复步骤三
不断利用已经授权了合约的用户购买LUME贷币,提高代币价格。
步骤五:卖出ULME代币

因为前期,攻击者大量调用buyMiner方法,通过已经授权的用户购买LUME贷币,导致LUME贷币价格升高,此时攻击者在步骤二中买入的ULME代币,即可获得高额利润,完成攻击。
代币转移分析
调用栈分析,偏向于细节,通过代币转移可以简要地看出攻击过程。
首先基于
基于 0xdb9a13bc970b97824e082782e838bdff0b76b30d268f1d66aac507f1d43ff4ed 分析代币转移过程:
步骤一:闪电贷
首先攻击者通过闪电贷获取了大量的BUSD
步骤二:获得ULME代币
通过swap操作,获得ULME的代币
步骤三:操作用户购买ULME代币
通过调用buyMiner方法,操作已经approve的用户购买ULME代币
步骤四:重复步骤三
操作其他的用户购买ULME代币
步骤五:卖出ULME代币
前面操作了大量的用户买入ULME代币,此时ULME代币价格升高,攻击者称此机会卖出ULME代币获利
步骤六:归还闪电贷
漏洞复现
基于 0xdb9a13bc970b97824e082782e838bdff0b76b30d268f1d66aac507f1d43ff4ed 复现
因为整个过程中,攻击者通过闪电贷攻击了大量的用户,但是我们为了演示方便,仅仅只是展示攻击一个受害者即可。
1 | emit log_named_decimal_uint("[Callback] Attacker USDT Balance at start", USDT.balanceOf(address(this)), USDT.decimals()); |
复现过程中的调用栈如下所示:
步骤一:闪电贷
我们在实际调用中,实际使用了两次闪电贷,总结获得了559044363987467735364956/10**18 USDT,没有ULME代币
步骤二:买入ULME代币
攻击者将闪电贷获得USDT通过pancake全部购买成为了ULME代币
购买结束之后,攻击者没有任何的USDT,拥有3665184427622820661280425/10**18 个 ULME代币
步骤三:实施攻击
调用漏洞合约的buyMiner()方法,让受害者(0x4A005e5E40Ce2B827C873cA37af77e6873e37203)用其所有的USDT,去购买ULME代币。
步骤四:攻击者卖出ULME
因为在步骤三中,调用了buyMiner()方法,当前ULME代币的价格就会升高。
攻击者卖出在步骤二中购买的ULME,获得USDT。因为当前ULME比买入的时候价格要高,所以卖出ULME代币时可以获得更多的USDT。
总结
总体来说,是一个比较明显简单的漏洞,,没有很复杂的逻辑。漏洞的合约存在几个问题:
- 对合约中的函数中的权限控制存在问题,任何用户都可以调用
buyMiner()方法 buyMiner()方法中可以操作已经授权过的任何用户
可以说,buyMiner()就类似于一个后门了。
对于用户来说,最近出现了攻击者攻击合约,操作合约中已经授权的用户,导致用户的资金损失。所以对于我们个人来说,不要轻易对合约授权,授权的金额需要按需授权。对于已经不在使用的合约,直接取消授权。