Back to Blog

#2:Euler Finance 事件:2023 年最大规模黑客攻击

Code Auditing
February 9, 2024
6 min read

2023年3月13日,我们的系统检测到 Euler Finance 的借贷池遭受了闪电贷攻击,导致 1.97 亿美元的损失。我们第一时间向社区发出警报,并提供了分析以帮助识别根本原因。

本次事件的根本原因在于 donateToReserves() 函数中缺乏偿付能力检查。具体而言,该漏洞合约提供了一种功能,允许用户在不检查头寸是否偿付的情况下将其抵押品捐赠给协议。更糟糕的是,为了处理这些不良头寸,该协议为清算人提供巨额折扣,使其能以更少的负债来清算该头寸。攻击者利用这一功能创建了一个大额头寸并使其陷入资不抵债的状态,随后便能以折扣价购回自己的抵押品从而获利。

背景

Euler Finance 概述

Euler Finance 是以太坊上的一个借贷协议,允许用户存入和借出特定的代币。当借方存入 Euler 的流动性池时,系统会铸造等量的 EToken(计息的 ERC20 代币)并发送给他们。这些 EToken 可用于赎回他们存入的基础资产。

另一方面,借入流动性的借款人会收到 DToken。这些 DToken 符合 ERC20 标准,禁止持有者独立销毁它们。具体来说,它们不能被随意发送给任何人,只能被他人提取,且接收这些代币需要获得批准。在基础资产方面,借款人需支付贷款利息,该利息的一部分用于覆盖协议的坏账。

Euler Finance 的杠杆借贷(也称自我借贷)和软清算机制是帮助我们更好地理解此次攻击原因的两个关键概念。

杠杆借贷

Euler Finance 提供杠杆借贷功能,使用户能够模拟循环借贷策略。简单来说,用户可以存入抵押品并铸造 EToken,这些 EToken 随后可用作进一步借入更多 EToken 的抵押品。合约还会铸造相应数量的 dToken 作为债务代币。用户头寸的健康程度是根据 EToken 和 dToken 的价值计算的。据 Euler Finance 的文档显示,用户最高可获得 19 倍杠杆。杠杆借贷功能在此次事件中起到了关键作用。如果没有该功能的协助,攻击者将无法获利。通过杠杆借贷,攻击者将其实际头寸规模放大到了闪电贷所得初始资金的近 11 倍。

软清算

正如 Euler Finance 的白皮书所述,软清算机制使清算人能够灵活地帮助被清算方偿还债务,而不受 Compound 和 Aave 等协议所采用的固定清算系数的限制。软清算意味着头寸的健康度越低,可供清算的抵押品比例就越高——根据本次事件的数据,在坏账发生时,清算比例最高可达 75%。因此,通过以大幅折扣清算抵押品,攻击者得以偿还闪电贷并锁定利润。

漏洞分析

主要漏洞(即缺乏偿付能力检查)存在于 donateToReserves() 函数中,该函数用于用户将头寸中的 EToken 作为捐赠转移到协议储备金中。对于普通用户而言,执行此类操作通常没有任何激励或动机。事实上,该漏洞在于 donateToReserves() 函数在将 EToken 从用户头寸中转出时,并未进行健康度检查。这使得攻击者可以直接将通过杠杆借贷创建的大额头寸中的 EToken 捐赠出去,导致该头寸的健康度跌破 100%,从而产生坏账。

根据设计,Euler Finance 使用动态平仓因子(close factor)来对头寸进行“软清算”。简而言之,头寸的健康状态越差,该头寸中可被清算的抵押品占比就越高。在坏账情况下,清算比例最高可达头寸内抵押品的 75%(根据实际攻击交易计算得出)。结果,被清算的大量折扣抵押品使攻击者能够偿还闪电贷并赚取利润。

攻击分析

针对不同资产池的攻击交易有多笔:

  • 0xc310a0affe2169d1f6feec1c63dbc7f7c62a887fa48795d327d4d2da2d6b111d (DAI)
  • 0x71a908be0bef6174bccc3d493becdfd28395d8898e355d451cb52f7bac38617 (WBTC)
  • 0x62bd3d31a7b75c098ccf28bc4d4af8c4a191b4b9e451fab4232258079e8b18c4 (wstETH)
  • 0x465a6780145f1efe3ab52f94c006065575712d2003d83d85481f3d110ed13d9 (USDC)
  • 0x3097830e9921e4063d334acb82f6a79374f76f0b1a8f857e89b89bc58df1f311 (stETH)
  • 0x47ac3527d02e6b9631c77fad1cdee7bfa77a8a7bfd4880dccbda5146ace4088f (WETH)

攻击步骤如下(以第一笔攻击交易为例):

  1. 攻击者通过闪电贷从 AAVE 借入 3000 万 DAI。
  2. 攻击者存入 2000 万 DAI 并获得 2000 万 eDAI。
  3. 由于 Euler Finance 提供杠杆借贷功能,攻击者进而铸造了 1.95 亿 eDAI 和 2 亿 dDAI。此时攻击者持有 2.15 亿 eDAI 和 2 亿 dDAI。
  4. 继续上述操作,偿还了 1000 万债务以便能铸造更多 eDAI。此时,攻击者持有 2.15 亿 eDAI 和 1.9 亿 dDAI。
  5. 重复步骤 3,此时攻击者持有 4.1 亿 eDAI 和 3.9 亿 dDAI。
  6. 攻击者调用函数 donateToReserve 捐赠了 1 亿 eDAI。然而在此过程中,攻击者的健康因子并未被检查。在这种情况下,该头寸现在可以被清算(3.1 亿 eDAI 对比 3.9 亿 dDAI),这为获利创造了机会。
  7. 攻击者使用另一个地址合约作为清算人 (0xa0b3...) 清算了该头寸。清算人 (0xa0b3...) 收到了 3.1 亿 eDAI 和 2.59 亿 dDAI。
  8. 攻击者在清算人地址 (0xa0b3...) 下销毁了 3890 万 eDAI 以提取 3890 万 DAI(由于存在偿付能力检查,无法提取更多)。
  9. 攻击者偿还了闪电贷。

关键的攻击步骤 2-7 已在交易链路中标注。

总结

这是 2023 年最大规模的黑客攻击事件。一名 20 岁的阿根廷年轻人 Federico Jaime 窃取了破纪录的 1.97 亿美元资金,他向媒体提供了一个“曲折、有时令人困惑,甚至自相矛盾的叙述”。尽管如此,“所有可追回的资金”后来都被归还到了 Euler Finance 的财库地址中。然而,其中一小部分(约 20 万美元)“在无意中”被发送给了 Lazarus Group——一个据称受美国财政部制裁的、由朝鲜政府支持的犯罪组织。您可以参考这些链接,即 链接1链接2,了解详细且有趣的故事始末。

此次事件的根本原因是缺乏偿付能力检查,这给我们上了一课。事实上,对于借贷协议而言,评估是否应针对任何可能影响用户头寸的流程执行头寸健康度检查至关重要。此外,项目团队应主动监控其借贷协议是否存在大规模清算,并建立有效的预警系统,以便及时感知并应对此类事件。

阅读本系列的其他文章:

Best Security Auditor for Web3

Validate design, code, and business logic before launch. Aligned with the highest industry security standards.

BlockSec Audit