Bankroll Network DeFi项目遭受攻击,攻击者共获利230K USD.漏洞在于 Bankroll 的代码中,没有做输入限制,导致攻击者可以使购买方为项目方本身。
<!--StartFragment-->
近期,我们监控到一起针对 BNB Smart Chain 的链上攻击事件,
https\://bscscan.com/tx/0xd4c7c11c46f81b6bf98284e4921a5b9f0ff97b4c71ebade206cb10507e4503b0
被攻击的项目为 Bankroll Network 的DeFi项目
<!--EndFragment-->
<!--StartFragment-->
首先,攻击者通过 pancakeSwap 利用 flash 借了 16,000 WBNB ,
<!--EndFragment-->
<!--StartFragment-->
随后,调用 Bankroll 的 buyfor 函数,将闪电贷获得的 16000 WBNB 购买了 Bankroll 的 share ,类似于质押。
<!--EndFragment-->
<!--StartFragment-->
接着,攻击者大量调用 buyfor 函数,使 Bankroll 自己的合约购买 Bankroll 的 share。
<!--EndFragment-->
<!--StartFragment-->
我们看一下 buyfor 函数的定义,如下图:
<!--EndFragment-->
<!--StartFragment-->
首先,函数从 _customerAddress 将 token 转入当前合约,其中 token 为 WBNB 。随后,调用purchaseTokens 购买 share ,最后调用 distribute 函数。
我们看一下该函数的定义:
<!--EndFragment-->
<!--StartFragment-->
在该函数中,会更新 profitPerShare_ ,该值为拥有一个 share 的利润。然后,通过 sell 函数将最开始利用 buyfor 转入 WBNB 获取的所有 share 卖出,再通过 Withdraw提取所有的 WBNB 。
我们看一下 sell 函数的定义:
<!--EndFragment-->
<!--StartFragment-->
可以看到, payoutsTo[_customerAddress] 和 profitPerShare_ 的关系为, profitPerShare_越大, payoutsTo[_customerAddress] 越小,且 payoutsTo_[_customerAddress] 为负数。
接下来我们再看一下 withdraw 函数的定义:
<!--EndFragment-->
<!--StartFragment-->
可以看出,提取的金额来源于 myDividends 函数,我们继续跟踪;
<!--EndFragment-->
<!--StartFragment-->
由上述分析,我们可以得出结论,只要 profitPerShare_ 越大,相同 share 下可以提取的 WBNB就越多。那么,由于攻击者一开始通过 buyfor获得了一定数量的 share ,攻击者只需要操纵 profitPerShare_ ,将其数值拉高即可提空合约中的 Token 。再回到最初分析 buyfor 函数得到的结论,只要调用 buyfor 函数购买 share 即可拉高profitPerShare_ 。但是 buyfor 函数没有限制 _customerAddress 不能为该合约本身,所以,攻击者通过将 _customerAddress 传入 Bankroll 的合约地址,即可完成不用转入 WBNB 来拉高profitPerShare_ ,最终完成攻击。攻击者从 Bankroll 合约中获得 16,412 WBNB ,还掉闪电贷的本金和利息 16,008 WBNB ,获利403 WBNB 约合 230k USD 。
<!--EndFragment-->
<!--StartFragment-->
本次漏洞在于 Bankroll 的代码中,没有做输入限制,导致攻击者可以使购买方为项目方本身。使得每一个单位的 share 被大幅拉升,从而使攻击者将 Bankroll 的所有资产已 share 的利润方式提取。建议项目方在合约上线前,针对智能合约进行充分的审计和交叉审计,避免此类安全问题。
<!--EndFragment-->
如果觉得我的文章对您有用,请随意打赏。你的支持将鼓励我继续创作!