风险提示:防范以"虚拟货币""区块链"名义进行非法集资的风险。——银保监会等五部门
资讯
发现
搜索
登录
简中
繁中
English
日本語
한국어
ภาษาไทย
Tiếng Việt
BTC
ETH
HTX
SOL
BNB
查看行情
Yearn Finance攻击事件分析
Eocene
特邀专栏作者
2023-04-18 03:52
本文约1055字,阅读全文需要约2分钟
本文将分析Yearn Finance攻击事件的攻击过程以及漏洞产生的原因。

概述

2023 年 4 月 13 日,Yearn Finance 遭到黑客攻击,导致大约损失 1000 万美元。本文将分析攻击过程以及漏洞产生的原因。

攻击分析

这是一笔攻击交易:

https://etherscan.io/tx/0xd55e43c1602b28d4fd4667ee445d570c8f298f5401cf04e62ec329759ecda95d

攻击者从 Balancer 发起了闪电贷,借了 500 万 DAI、 500 万 USDC 和 200 万 USDT

然后在 Curve 上,攻击者将 500 万 DAI 兑换成了 695, 000 USDT,并将 350 万 USDC 兑换成 151 USDT:

攻击者调用 IEarnAPRWithPool 的recommend函数来检查当前的 APR。此时,只有 Aave 的 APR 不等于 0 :

接下来,攻击者将 800, 000 USDT 转移到了攻击合约 0x9fcc1409b56cf235d9cdbbb86b6ad5089fa0eb0f 中。在该合约中,攻击者多次调用了 Aave:Lending Pool V1的repay函数,帮助其他人偿还债务,以使 Aave 的 APR 等于 0 :

攻击者调用了 yUSDT 的deposit函数,抵押了 900, 000 USDT,并获得了 820, 000 yUSDT:

接下来,攻击者调用了 bZx iUSDC 的mint函数,使用 156, 000 USDC 铸造了 152, 000 bZx iUSDC,并将其转移到了 Yearn yUSDT:

攻击者调用 Yearn:yUSDT 的withdraw函数,将 820, 000 yUSDT 兑换成 1, 030, 000 USDT。此时,合约中只剩下攻击者转移的 bZx iUSDC:

接下来攻击者调用 Yearn:yUSDT 的rebalance函数,销毁 bZx iUSDC:

然后攻击者向 yUSDT 合约转移了 1/e 6 个 USDT,并调用了deposit函数,抵押了 10, 000 USDT,获得了 1, 252, 660, 242, 850, 000 yUSDT:

然后在 Curve 上,攻击者将 70, 000 yUSDT 兑换成 5, 990, 000 yDAI,将 4 亿 yUSDT 兑换成 4, 490, 000 yUSDC,将 1, 240, 133, 244, 352, 200 yUSDT 兑换成 1, 360, 000 yTUSD:

然后在 yearn: yDAI 和 yearn: yUSDC 中分别调用 withdraw ,提取 678 万 个 DAI 和 562 w 万个 USDC,并归还闪电贷:

漏洞分析

这次攻击中最关键的一点,是攻击者使用 100, 000 USDT 铸造了 1, 252, 660, 242, 850, 000 个 yUSDT。查看 deposit 函数的实现:

可以看到 share 的数量和变量 pool 相关,pool 越小,share 越大,而 pool 的值由 _calcPoolValueInToken 获得:

攻击者在调用 rebalance 函数 后,合约中只存在了 USDC,但是 _balance() 获取的是 USDT 的余额,USDC 的余额并不计入其中,因此此时的 pool 为 1 (攻击者转入的) :

这里显然是项目方的配置错误,yUSDT 合约中 应当都是 USDT 类的代币,但是其 fulcrum 变量却是 USDC 相关的 bZx IUSDC 代币,因此 yUSDT 中的 USDC 不计入 balance 中:

攻击者为什么能调用 rebalance 函数来 burn 掉 bZx iUSDC 代币呢?查看 rebalance 函数的实现:

可以看到在 _withdrawFulcrum() 中会 存在 redeem 和 burn 操作,因此我们需要让 "newProvider != provider" 成立 ,  其中 recommend() 的实现:

攻击者通过控制 IIEarnManager(apr).recommend(token) 的返回值,使其为都为 0 来操控 newProvider:

如何让其都为 0 呢,该函数的返回值和计算出的各个 DeFi 中的 APR 相关,由于 Compound,bZx,dydx 中没有池子,因此只需要控制 Aave ( Aave: Lending Pool Core V1) 即可:

要使其值返回为 0 ,需要让 apr.calculateInterestRates 函数的第一个返回值为 0 :

即让 currentLiquidityRate 为 0 ,该值和 _totalBorrowsStable_totalBorrowsVariable 相关,当这两个个值都为 0 时,currentLiquidityRate 为 0 :

_totalBorrowsVariable 为 0 ,即 Aave: Lending Pool Core V1 此时没有人存在债务,为了达成这个条件,攻击者将池中所有人的债务进行了 repay

最后,攻击者让 _totalBorrowsVariable 变为 0 ,所以它能够调用 rebalance 函数 burn 掉 bZx iUSDC 代币:

总结

此次 Yearn 攻击事件的根本原因是项目方的配置错误。攻击者通过一系列精妙的手法利用了该漏洞,最终获利大约 1000 万美元。

关于我们

At Eocene Research, we provide the insights of intentions and security behind everything you know or don't know of blockchain, and empower every individual and organization to answer complex questions we hadn't even dreamed of back then.

了解更多: Website | Medium | Twitter

yearn
bZx
Aave
USDT
USDC
AI