Uniswap和Lendf.Me遭攻击始末:DeFi乐高组合下的“多米诺”式崩塌
- 资讯
- 2023-07-24
糟糕的是,仅仅在24小时后,于04月19日上午08:45,又一知名DeFi平台 Lendf.Me 也被黑客以类似的手段实施了攻击。
PeckShield 安全团队认为这是自年初 bZx 遭攻击之后,又两起黑客利用 DeFi 系统性风控漏洞实施的攻击。一个不容忽视的问题是,DeFi 市场的风险可能不仅仅局限于平台本身,单个平台的模式创新很可能在与其他平台业务接轨时产生漏洞风险。
详细漏洞攻击细节,我们将在文章后面做详细介绍。
Figure 1: ERC777 transferFrom()
该标准扩展的功能之一是提供了“hook”机制,可以使普通地址或合约通过注册一个tokensToSend() hook 函数来控制或拒绝发送 Token。这原本是在 ERC20 基础上加强了对 Token 的风险控制接口,是一次有益的改进。不过由于 DeFi 项目的可组合特性,一个合约在不同产品之间相互调用时,其业务逻辑复杂度也会大大增加,这就给注入代码攻击提供了可能性。
其中最关键的部分是,攻击者可以通过注册 from 的 tokensToSend() 来实行回调。我们从下面的代码片段可以看到,ERC777 标准中可以通过 getInterfaceImplementer()(1,054行)获得攻击者的 tokensToSend() 接口,并在第1,056行调用此函数。而此处正是黑客劫持交易实施攻击的入口。
Figure 2: ERC777-Compatible tokensToSend() Hijacking
如2019年4月OpenZeppelin 发布的帖子以及2019年7月发布的漏洞利用演示中所述,攻击者可以自己定义函数 tokensToSend(),并通过 setInterfaceImplementer() 来设置合约中的 hook 函数。
Figure 3: OpenZeppelin's Exploit Demo (Hook Setup)
之后攻击者就可以像传统 PC 上的 hook 函数一样,在 tokensToSend() 做任何事情。如下图所示,攻击者可以对同一笔交易进行多次交易。
Figure 4: OpenZeppelin's Exploit Demo (Hook Function)
Figure 5: Uniswap Hack
Figure 6: Lendf.Me Hack
在这个交易例子中,攻击者第一次 supply() 时确实向 Lendf.Me 存放了289.99999999个 imBTC,而在第二个 supply() 中,攻击者只存放0.00000001个 imBTC,但由于攻击者注册了 tokensToSend(),所以在执行 doTransferIn() -> IMBTC :: transferFrom()(第1,583行)时,调用了攻击者函数 tokensToSend(),攻击者函数通过调用 Lendf.Me 的 withdraw() 函数把290个 imBTC 直接全部提走。
需要注意的是,正常的业务逻辑应该是项目合约中的 Balance 会减去被攻击者提走的290个 imBTC,然而当 supply() 执行返回时,余额并未被重置,仍然为290 imBTC(第1,599行)。攻击者就是通过控制修改 Lendf.Me 中攻击者的 imBTC 抵押金额,有了足够大的 imBTC 抵押,攻击就可以从各种流动交易对中借出所有可用的10多种资产(资产总值25,236,849.44美元)。
Figure 7: Lendf.Me Hack Details
另一方面, ERC777 标准特性会不可避免地启用 hook 机制,因此我们需要检测并防止所有交易功能产生可以重入的风险。例如,如果 supply() 和 withdraw() 同时运行时加个互斥锁,那么攻击者就无法在 supply() 函数内部执行 withdraw() 操作。
最后并不能被忽视的一点是,我们需要认真思考下 DeFi 业务组合可能存在的系统性风险问题,平台方不仅要确保在产品上线前有过硬的代码审计和漏洞排查,还要在不同产品做业务组合时考虑因各自不同业务逻辑而潜在的系统性风控问题。
可能一个新创新,在原平台一点问题都没有,但组合接入另一个产品后就可能存在业务逻辑缺陷,进而成为黑客攻击整个 DeFi 市场的入口。
本文链接:http://www.bqcjw.com/read/7148.html