Uniswap和lendf.Me遭攻击始末:愿DeFi世界里没有ERC777

IP归属:

04月18日上午08:58开始,一 DeFi 平台 Uniswap 被黑客利用重入漏洞实施了攻击。大约24小时后,于04月19日(昨天)上午08:45,又一知名 DeFi 平台 Lendf.Me 被以类似的手段实施了攻击。

攻击的原理是:攻击者通过以太坊上少有 token 使用的 ERC777 的 transferFrom() 回调机制,利用在内部调用_callTokensToSend()回调函数劫持交易 ,并在真正更新余额的 _move() 函数之前进行恶意攻击。

在 Uniswap 的攻击案例中,攻击者利用此漏洞消耗尽 Uniswap ETH-imBTC 池约1,278个 ETH。而在 Lendf.Me 中,攻击者则是利用它来任意增加内部 imBTC 抵押金额,并通过从其他可用的 Lendf.Me 交易中借入10多种资产(总价值约 2,524万美元)。

详细漏洞攻击细节,我们将在文章后面做详细介绍。

Figure 1: ERC777 transferFrom()

罪恶之源:ERC777 标准

我们首先介绍下 ERC777 标准,该标准是通用 ERC20 标准改进后的一个稀有标准,不仅实现了部分功能扩展还保持着 ERC20良好的兼容性,愿景是成为 ERC20标准的有效继承者。

该标准扩展功能提供了“hook”机制, “通过调用“hook”函数来加强智能合约对 Token 转账的通知或控制”。但也正因为此功能的出现给注入代码攻击提供了可能性。

其中最关键的部分是,可以通过注册 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)

Uniswap攻击分析

由于针对 ERC777 的攻击原理在前面已经描述过了,因此我们不再赘述。

就如此恶意交易在 Bloxy中的截图所示(hash:0x9cb1d93d6859883361e8c2f9941f13d6156a1e8daa0ebe801b5d0b5a612723c1),函数的内部调用中又进行一次 tokenToEthSwapInput()调用。这意味着攻击者可以先通过交易操纵汇率,然后再用另一笔 imBTC 以较低价格兑换更多的 ETH。

Figure 5: Uniswap Hack

Lendf.Me攻击分析

在 Uniswap 遭攻击约24小时后,又一 DeFi 平台 Lendf.Me 也遭到了黑客攻击。下面是其中一个攻击交易的截图。如图所示,supply() 函数中调用真实转账函数 transferFrom()时,被 hook 的攻击者合约里嵌入了盗用 Lendf.Me 的 withdraw() 的提币操作。

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

资产流向

攻击者 0x538359 共计从 Lendf.Me 获利 25,236,849.44 美元,其中各个 Token 分布如下:

如上图,攻击者在获利之后,马上将各个 Token 转移至其关联账号 0xa9bf70 之中,之后攻击者数十次 通过 1inch.exchange, ParaSwap 等平台将其中比较抢手的 WETH, PAX, BUSD 等 Token 换成 ETH, DAI, BAT 代币,另外将其中的 TUSD, USDT 代币存入 Aave 借贷平台。至此为止,攻击者及其关联账号的余额如上所示。

修复建议

PeckShield 安全团队在此建议开发者,可以采用 “Checks-Effects-Interactions”方法来防止这类重入攻击。举个例子,Lendf.Me 的supply() 里如果是先更新 token 余额,再调用 doTransferIn() 。这将会让攻击在 withdraw() 之后没有重置余额的可能性。

另一方面, ERC777 标准特性会不可避免地启用 hook 机制,因此我们需要检测并防止所有交易功能产生可以重入的风险。例如,如果 supply()和 withdraw()同时运行时加个互斥锁,那么攻击者就无法在 supply()函数内部执行 withdraw()操作。

最后并不能被忽视的一点是,我们需要认真思考下是否ERC20已经足够满足项目需求,我们真的需要ERC777么?

PS:此次黑客对 Lendf.Me 的攻击对 DeFi 社区来说无疑是一场灾难,在此建议广大 DeFi 开发者务必注意业务存在的系统性风控风险,应尽可能和第三方安全公司合作排查一切潜在的安全风险。更多详情请点击左下角“阅读原文”查看英文原版分析报告。

本文来源:陀螺科技 文章作者:PeckShield
收藏
举报
PeckShield
累计发布内容21篇 累计总热度10万+

陀螺科技现已开放专栏入驻,详情请见入驻指南: https://www.tuoluo.cn/article/detail-27547.html

PeckShield专栏: https://www.tuoluo.cn/columns/author412598/

本文网址: https://www.tuoluo.cn/article/detail-10000576.html

免责声明:
1、本文版权归原作者所有,仅代表作者本人观点,不代表陀螺科技观点或立场。
2、如发现文章、图片等侵权行为,侵权责任将由作者本人承担。

相关文章