说明
前面分享了一个有关ATK代币获取奖励的漏洞,本质上还是对于获取奖励机制的方法太过于简单。本篇文章分享的NewFreeDao也是奖励机制存在问题,和ATK的漏洞一样,存在漏洞的合约也是一个闭源合约,但还是被攻击了。
漏洞合约是一个闭源合约,0x8B068E22E9a4A9bcA3C321e0ec428AbF32691D1E
NewFreeDao,是用于奖励的代币
攻击交易,0x1fea385acf7ff046d928d4041db017e1d7ead66727ce7aacb3296b9d485d4a26
漏洞分析
正常交易分析
因为漏洞合约是一个闭源合约,所以我们并不能通过合约分析出漏洞位置和原理,还是通过已有的交易来分析漏洞点。
本次分析的正常的交易是:0x92c72bb1d47ab30abb1cf2ee55137e1001383bfdf9ae4c51f18644425386e2e8
调用漏洞合约的0x6811e3b9方法,就获得了NFD的代币。
分析调用栈信息:0x92c72bb1d47ab30abb1cf2ee55137e1001383bfdf9ae4c51f18644425386e2e8
根据调用栈分析:
- 调用漏洞合约中
0x6811e3b9() - 漏洞合约计算目标账户中的NFD代币余额
- 根据第二步中的计算账户中的NFD的数量发布奖励
根据0x6811e3b9()的说法,我们账户中如果存在大量的NFD代币,那么响应的获取的奖励也就越多。那么我们就可以通过闪电贷完成这样的攻击。
攻击交易分析
攻击合约分析,0x1fea385acf7ff046d928d4041db017e1d7ead66727ce7aacb3296b9d485d4a26
通过分析攻击交易中的Token转移交易,猜测内部的交易过程如下:
- 攻击合约
0xa35ef9fa2f5e0527cb9fbb6f9d3a24cfed948863通过闪电贷最终获得大量的NFD - 攻击合约创建子合约
0x9f49375d30dd556776c14e95fb2502ac7e09a281,并向子合约转账NFD - 漏洞合约合约
0x8B068E22E9a4A9bcA3C321e0ec428AbF32691D1E向子合约0x9f49375d30dd556776c14e95fb2502ac7e09a281转账(估计是获得了代币奖励) - 重复2-3步,不断滴获得代币奖励
通过Tokens Transferred,大致猜测出了攻击合约的调用方法。
通过调用栈分析,0x1fea385acf7ff046d928d4041db017e1d7ead66727ce7aacb3296b9d485d4a26
第一步,通过闪电贷获得WBNB之后,将WBNB通过swap,替换为NewFreeDAO
第二步,攻击合约(0xa35ef9fa2f5e0527cb9fbb6f9d3a24cfed948863)创建子合约(0x9f49375d30dd556776c14e95fb2502ac7e09a281),并向子合约转账NFD

第三步,子合约(0x9f49375d30dd556776c14e95fb2502ac7e09a281调用漏洞合约(0x8b068e22e9a4a9bca3c321e0ec428abf32691d1e)的获取奖励方法0x6811e3b9

最终通过子合约获得的奖励,全部转移到攻击合约(0x8b068e22e9a4a9bca3c321e0ec428abf32691d1e)中。
第四步,子合约自行销毁

第五步,攻击合约(0x8b068e22e9a4a9bca3c321e0ec428abf32691d1e)继续创建子合约重复步骤二、步骤三、步骤四
漏洞复现
既然通过攻击交易0x1fea385acf7ff046d928d4041db017e1d7ead66727ce7aacb3296b9d485d4a26,明白了整个攻击流程。我们模仿这个攻击分步写出Poc。
本次的漏洞复现分成三部分:
第一步
通过DODO闪电贷出250个WBNB,然后在PancakeRouter中变为NFD的token,作为攻击的初始攻击资产。
1 | DVM(dodo).flashLoan(0, 250*1e18, address(this), data); |
第二步
创建子合约,并将资金全部转移到子合约中,这里为了方便演示,仅仅只是循环创建一个子合约。
1 | console.log("Abuse the Reward Contract..."); |
第三步
子合约调用漏洞合约(0x8B068E22E9a4A9bcA3C321e0ec428AbF32691D1E)的0x6811e3b9函数,领取奖励,并将奖励和资产又全部转移到攻击合约中
1 | // 子合约代码 |
第四步
攻击合约继续重复步骤三和步骤四,不断获取奖励。
第五步
归还闪电贷还款。
在实际测试过程中,我为了方便查看分析结果,仅仅只是进行了1次循环攻击,发现整个攻击攻击最终是revert了,循环50次之后攻击,攻击交易就成功了。后面分析攻击失败的原因,是在于循环一次攻击虽然也获得了盈利,但是因为最开始需要将贷出的WBNB换成NFD,最终归还闪电贷时需要将NFD换成WBNB,这个中间存在滑点,所以如果仅仅只是循环攻击一次,那么最终滑点导致的损失可能不足以支付闪电贷而失败了。日志情况如下所示:
1 | # 初始情况是,250 WBNB |
可以看到虽然NFD变多了,但是最后兑换出来的WBNB却变少了,所以只进行一次攻击是不够的。
最终利用forge测试得到的调用栈信息如下所示:
DODO闪电贷
通过PancakeRouter,将WBNB兑换为NFD
创建子合约准备实施攻击
子合约调用abuse()方法获得奖励并将奖励转移到攻击合约中
攻击合约继续循环创建子合约实施攻击获取奖励。
归还闪电贷
以上就是整个攻击过程的分析。
总结
NewFreeDao的漏洞基本上和前面的ATK的漏洞点是一样的。发放奖励的标准是根据账户中的Token的数量,同时也没有限制账户是EOA账户,最终导致了攻击事件。
NewFreeDao和ATK这两个代币是没有漏洞的,漏洞都是出现在奖励发放的合约上,虽然这两个奖励发放合约都是闭源的,但是并不能保证不被攻击,根本的方法还是需要加强对合约的安全性的测试。
参考
https://bscscan.com/tx/0x1fea385acf7ff046d928d4041db017e1d7ead66727ce7aacb3296b9d485d4a26
https://twitter.com/SlowMist_Team/status/1567854876633309186
https://twitter.com/peckshield/status/1567710274244825088