事件背景
Eleven Finance是在币安智能链生态系统中为高APY金库赋能的平台,专注于快速发展为社区平台提供动态和广泛的保险库,为用户提供优化的收益策略。
零时科技监控到消息,北京时间2021年6月23日,Nerve官方推文称Nerve相关的保险库Eleven Finance遭到闪电贷攻击,并表示$NRV资金安全,零时科技安全团队及时对该安全事件进行复盘分析。
事件分析
攻击信息
通过初步追踪分析,攻击者创建了四个攻击合约,进行了五笔攻击交易,共盗取资金价值超460万美元,攻击信息如下:
攻击者钱包地址
https://bscscan.com/address/0xc71e2f581b77de945c8a7a191b0b238c81f11ed6
攻击者合约地址
https://bscscan.com/address/0x8b2979d88be70ba1b0c48691bdcae7909d084401
https://bscscan.com/address/0x01eae4e246dfae08a4ef5c3d8f31d0668686eab3
https://bscscan.com/address/0xc0efd9f475950d71e8c3399d1d1cfc73531fcb8f
https://bscscan.com/address/0x87e950c3b749ee1585c066b78930f7c0cfc465ce
攻击者盗取资金交易
https://bscscan.com/tx/0x6450d8f4db09972853e948bee44f2cb54b9df786dace774106cd28820e906789
https://bscscan.com/tx/0xeaaa8f4d33b1035a790f0d7c4eb6e38db7d6d3b580e0bbc9ba39a9d6b80dd250
https://bscscan.com/tx/0x9c147db3604e130738142171624eef51f1ff3394433aea64a58401531c5ca8c3
https://bscscan.com/tx/0x153eeae811a9acedad4dc76492316d5503a02ad8a324563a50b7118b4f574469
https://bscscan.com/tx/0xcfcee591a1a7010a8bd084b6f03698dde8eb3ac13c8f561ea20c7fc5d1f936dc
ElevenNeverSellVault合约地址
https://bscscan.com/address/0x025E2e9113dC1f6549C83E761d70E647c8CDE187#code
攻击过程
由于攻击者的五笔攻击交易均类似,这里分析攻击者第四个合约中的第一笔交易,该笔交易也是损失资金最多的交易,下面分步解析该笔交易,方便读者更清晰的了解攻击过程。
第一步:攻击者通过PancakePair闪电贷借出242万枚USDT。
第二步:攻击者将闪电贷借出的242万枚USDT全部在稳定币Nerve 3Pool兑换为241万枚3NRV-LP。
第三步:攻击者将241万枚3NRV-LP添加至ElevenNeverSellVault合约后获得241万枚11Pool3 Nerve。
第四步:攻击者取出在 ElevenNeverSellVault合约添加的万枚3NRV-LP(这里需要注意的是,这步是攻击者完成攻击最重要的一步操作,攻击者上一步获得的241万枚11Pool3 Nerve并没有进行销毁)
第五步:攻击者归还第三步获得的241万枚11Pool3 Nerve,得到241万枚3NRV-LP。(这里是正常逻辑,归还11Pool3 Nerve,得到3NRV-LP,但由于第四步凭空取出241万枚3NRV-LP,加上这里数值,共计归还241万枚11Pool3 Nerve,得到482万枚3NRV-LP,也就是双倍3NRV-LP)
第六步:攻击者将得到的482万枚3NRV-LP兑换为483万枚USDT。
第七步:攻击者归还闪电贷借出的242万枚USDT,并将剩余的241万枚USDT转至攻击者钱包。
至此
攻击者通过该笔交易获取241万枚USDT,加上攻击者其余的四笔攻击交易获取的资金,攻击者共计获取了310万枚USDT,30枚BTC,284枚ETH,总价值超过460万美元。
走到这里大家可能会有疑问,看似简单的步骤,为何可以获取大量代币,交易的第四步中为什么取走241万枚3NRV-LP后,没有对取款者质押的241万枚11Pool3 Nerve进行销毁,下面我们从合约中分析凭空取走241万枚3NRV-LP的代码逻辑。
攻击成功的原因
通过以上交易分析可以明确,攻击者将241万枚3NRV-LP添加至ElevenNeverSellVault合约后获得241万枚11Pool3 Nerve,但从ElevenNeverSellVault合约取款时,取了两次241万枚3NRV-LP,这里我们直接分析ElevenNeverSellVault合约取款代码逻辑,如下图:
上图为ElevenNeverSellVault合约中两个取款方法withdraw()和emergencyBurn()。攻击者使用的是紧急提款emergencyBurn方法,1132行代码中,合约逻辑是将调用者地址余额赋值给balan变量,之后1135行中给调用者进行了balan金额的转账,转账的金额也就是调用者在该合约中的所有余额。
问题点在于:调用者在合约中的余额赋值给balan变量,并给调用者进行了转账,但并未对调用者余额balanceOf(msg.sender)数量进行销毁,所以攻击者第一次取走241万枚3NRV-LP代币后,emergencyBurn方法并未销毁攻击者原本的余额,导致攻击者余额并没有减少,之后攻击者又利用本身余额进行了第二次241万枚3NRV-LP取款。
该问题如何避免!上图withdraw方法中已给出答案,1123行代码中,在调用者进行取款时,对调用者取款数量shares随即进行销毁,同样的逻辑也可以应用在emergencyBurn方法,将调用者地址余额赋值给balan变量后,可使用上图burn方法对调用者余额进行销毁,从而避免此类安全问题。
总结
通过此次攻击事件来看,攻击者通过多次闪电贷,并通过emergencyBurn方法中用户余额未更新问题,最终获得了大量代币,目前类似的闪电贷攻击事件居多,为何还会频频发生,对于DeFi项目而言,合约代码的安全,代币价格的相对稳定,旧版本的及时更新都是保证项目安全极其重要的部分,对于合约变量未更新问题,应在合约上线前进行严格审查及测试。对于此类闪电贷攻击事件,零时科技安全团队给出以下建议:
安全建议
·对于合约代码安全,可找多家安全审计公司进行审计。
·对LP价格及获取奖励的铸币代码块,应根据业务逻辑进行严格审核演算,避免出现参数可控制导致大量铸币问题。
·使用可信的并且安全可靠的预言机,如Chainlink去中心化预言机,Alpha homera采用的。
·对敏感性较强的代码,要做到及时更新完善。