Uniswap / Lendf.Me遭受攻击的根本原因和损失分析

从2020年4月18日上午12:58:19 + UTC开始,DeFi平台Uniswap被黑客利用可重入漏洞攻击。大约24小时后,即+ UTC,2020年4月19日上午12:58:43,Lendf.Me发生了类似的黑客攻击。从技术上讲,这两个事件背后的主要逻辑是ERC777与那些DeFi智能合约之间的不兼容性,攻击者可能会滥用这种兼容性来完全劫持正常交易,并执行其他非法操作。

具体而言,在Uniswap被攻击事件中,攻击者利用此漏洞耗尽ETH-imBTC(约有1,278 ETH)的Uniswap流动资金池,而在Lendf.Me被攻击事件中,攻击者利用它来任意增加内部记录攻击者的imBTC抵押金额的一半,以便可以从所有可用的Lendf.Me流动性池中借出10多种资产,资产总值25,236,849.44美元。

同时,还需要注意的是,ERC777本身是社区建立的代币标准,具有适用于各种情况的高级功能。但是,这些高级功能可能与某些DeFi方案不兼容。更糟糕的是,这种不兼容性可能进一步导致不良后果,例如重新进入。我们还注意到,其他代币标准,例如ERC1155也有类似地设计具有回调功能。话虽如此,我们对imBTC ERC777情况的人工审核表明,它确实遵循ERC777标准。

Figure 1: ERC777-Compatible transferFrom()

根本原因分析

如果我们深入研究ERC777源代码,则该漏洞位于内部逻辑中,即当transferFrom()操作的发自地址已注册为实现者,通过标准ERC1820接口时,调用tokensToSend()函数。

为了说明起见,我们在以下代码段中显示了调用tokensToSend()函数时的上下文。特别是,如第1054行所示,ERC1820的getInterfaceImplementer()用于检索已注册的实现程序。这个特定的函数有两个参数from和TOKENS_SENDER_INTERFACE_HASH:第一个参数本质上是攻击者,例如将imBTC提供给Lendf.Me的地址,第二个参数是常量,即keccak256,“ ERC777TokensSender”。稍后,在第1056行中,将调用实现者中定义的tokensToSend()函数,该攻击者允许攻击者通过本质上注入其他恶意代码来执行劫持交易。

Figure 2: ERC777-Compatible tokensToSend() Hijacking

正如2019年4月OpenZeppelin的帖子以及去年7月发布的概念验证漏洞所描述的那样,攻击者可以设置InterfaceImplementer()来使用定义上述tokensToSend()方法的智能合约来设置钩子。

Figure 3: OpenZeppelin’s Exploit Demo (Hook Setup)

在tokensToSend()函数中,攻击者基本上可以执行其他逻辑,例如多次出售同一批代币。

Figure 4: OpenZeppelin’s Exploit Demo (Hook Function)

Uniswap 被攻击

由于Uniswap 被攻击背后的理论已在本文前面进行了描述,因此我们在此不再赘述。相反,我们会检查特定的恶意交易(哈希:0x9cb1d93d6859883361e8c2f9941f13d6156a1e8daa0ebe801b5d0b5a612723c1)。显然,内部还有一个附加的tokenToEthSwapInput()调用。这意味着当操纵转换率以利于攻击者的利益时,攻击者可以用另一批imBTC代币交换ETH。

Figure 5: Uniswap Hack

Lendf.Me被攻击

Lendf.Me被攻击的运作方式略有不同,但性质相同。如果我们检查特定的恶意交易(哈希:0xae7d664bdfcc54220df4f18d339005c6faf6e62c9ca79c56387bc0389274363b),则存款功能,即Lendf.Me中的supply()会通过嵌入额外的withdraw()操作,从而导致增加攻击者的内部记录没有实际存入金额的抵押金额。

Figure 6: Lendf.Me Hack

背后的逻辑是,攻击者首先确实向Lendf.Me提供了一定数量的imBTC,例如289.99999999 imBTC。但是,在第二个supply()中,攻击者只是提供了0.00000001 imBTC,但另外撤回了290 imBTC,通过劫持doTransferIn()内部的IMBTC :: transferFrom()调用-第1583行。结果,从嵌入的withdraw()中的攻击者余额中减去了290个imBTC。但是,当执行返回到supply()时,余额重置为290 imBTC(第1599行)。这就是攻击者操纵Lendf.Me中攻击者的imBTC抵押品金额的内部记录的方式。有了足够大的抵押物,攻击就可以从各种流动性池中借出所有可用的10多种资产,资产总值25,236,849.44美元。

Figure 7: Lendf.Me Hack Details

缓解机制

作为阻止此类重入攻击的常见缓解机制,所谓的Checks-Effects-Interactions设计模式始终有帮助。例如,如果Lendf.Me的supply()在保存用户代币余额的更新后调用doTransferIn(),则攻击者将没有机会由于withdraw()调用而重置余额更新。

另一方面,ERC777的性质不可避免地会启用挂钩机制,因此我们需要防止所有交易功能的重新进入。例如,如果supply()和withdraw()都试图在该函数的开头保持互斥锁,那么错误的参与者就无法在supply()主体内部执行withdraw()。最后但并非最不重要的一点是,我们可能需要重新审视ERC20和ERC777之间的选择,同时注意到选择ERC777的优点是便于保护用户资产,因为用户无需为每次交易操作将所有代币都批准到平台上。

被攻击的损失

Lendf.Me 被攻击对当前的DeFi社区造成了巨大的打击。在下图中,我们汇总了此事件中各种资产的损失金额:

——感谢阅读,全文完——

原文链接:https://medium.com/@peckshield/uniswap-lendf-me-hacks-root-cause-and-loss-analysis-50f3263dcc09

你可能感兴趣的:(Uniswap / Lendf.Me遭受攻击的根本原因和损失分析)