发现
今天看了一下Venus项目的逻辑和代码,发现其存在一个较严重的漏洞,这个漏洞可能导致资金池被盗。
Venus的代码是fork自Compound的,经分析,此漏洞在Compound和Cream中也存在。
利用过程
- 攻击者可以在资金池没有资金(刚创建,或者被取空时),注入一个最小单位的份额。
- 攻击者向资金池注入一定量的资金,导致资金池的净值极大。
- 由于资金池净值极大,普通的做市资金算得得份额都为0,因此后面做市,只有资金进入,但是份额为0,攻击者一致占有全部份额。
- 攻击者赎回份额,盗走所有资金。
攻击原理
1. 在exchangeRateStoredInternal()函数中,通过当前资金池资产(包括余额,借出资产,并扣除已归还资产)除以总份额来计算兑换率,这个兑换率可以简单理解为资金池的净值。
2. 在资金池刚创建,或者被取空时,注入一个最小单位的份额,然后直接向资金池转入一定量的资金,根据上述净值算法,这会导致资金池的净值极大。
3. 后面存入的资金,都是通过转入资金数量除以净值得到的,由于上一步的操作,会导致通常数量的资金所得的份额整除后为0,也就是后面做市只会转入资金,但是得到的份额数量为0!资金池只有攻击者一个人的份额。
4. 攻击者赎回份额,由于资金池只有攻击者一个人的份额,因此所有转入的资金都会被攻击者取走。
以下是在rinkeby上模拟攻击的相关交易
- 攻击者先正常存入资金,获得份额
https://rinkeby.etherscan.io/tx/0x5d09b73dec9268d33e3cb4d2e4451351080c09195e9b1170577d64d00ad6099b - 攻击者赎回份额,仅留下一个最小单位的份额
https://rinkeby.etherscan.io/tx/0x986f13ca84ec3b25f56debf4d9e4e972c26fe36cad2ed91029146881c9a79b58 - 攻击者直接向资金池转入大量资金,等待其他人做市
https://rinkeby.etherscan.io/tx/0xd72b1f8b1cd755929569e4695569753a71f67ba94fbbdfe06f03fe7fe8325706 - 有人做市,但是获得的份额为0
https://rinkeby.etherscan.io/tx/0xbd1374915ea13f4634213dde557876c266bd800a8f96a4bbc0072333876efb74 - 攻击者赎回份额,盗走所有资金
https://rinkeby.etherscan.io/tx/0xf0c6b689cc89614fb27b21c483763a804b8efa3c19c4ecca89f20075a6e8a28a
漏洞特性
根据上面的过程可知,此漏洞可以被利用的条件较苛刻,通常难以被利用。但是,有两种方法可以提高攻击的可能性。
方法一
- 攻击者监听comptroller的MarketListed事件。
- 当通过MarketListed发现新的资金池创建时,立即向资金池注入资金,实行攻击。
方法二
- 攻击者选一个较小的资金池,注入一定的份额。
- 攻击者向资金池注入大量资金,导致净值变大。
- 之前有份额的人发现净值变大,并且单位资金的利率在降低,于是,纷纷赎回份额,资金池份额降低。
- 资金池份额降低,攻击者循环执行2,3步骤,继续向资金池注入资金,导资金池净值快速上升,最终达到超大净值,后面进入的普通资金无法得到份额。
- 攻击者按照空资金池的攻击方式,盗走后来者的资金。
总结
如果这样考虑,则这个漏洞被利用的可能性就提高了很多。这种利用小份额进行的攻击,在uniswap中已经给出了一个解决方案,就是在第一次做市时往0地址转入一个小份额锁死,从而可以有效阻止这种攻击手段。