只读型复入防护(Read-only re-entrancy guards)

The Euler Labs team recently deployed a preventative update to the Euler smart contracts that protects contracts integrating with Euler against a class of manipulation attacks. As far as we know, no users were ever exploited by this issue, but it is quite an interesting attack vector and very likely applies to other projects as well.

Euler Labs 团队最近为 Euler 智能合约部署了一个预防性更新,用来保护与 Euler 集成的合约免受一类操纵攻击。据我们所知,还没有用户被这个问题所利用/受害,但它是一个非常有趣的攻击媒介,也很可能也适用于其他项目。

背景 (Background)

Like many other DeFi systems, Euler created a wrapper asset around deposited tokens. For example, eDAI is a wrapper for DAI. Since this is an interest-earning asset, each unit is redeemable for a growing amount of DAI. At any given point in time, the amount of DAI a user can receive for a unit of eDAI is given by the “exchange rate”. This value is computed by dividing the pool’s assets (balance plus outstanding borrows) by the total outstanding eToken balances. Protocols that integrate with Euler may use the exchange rate to compute the underlying value of an eToken deposit by calling convertBalanceToUnderlying() on an eToken.

与许多其他 DeFi 系统一样,Euler 围绕存入的代币创建了一个封装资产。例如,eDAI 是 DAI 的封装器。由于这是一种生息资产,因此每个单位都可以赎回越来越多的 DAI。在任何给定的时间点,用户可以从一个单位的 eDAI 获得的 DAI 数量由“汇率”给出。该值是通过将池的资产(余额加上未偿还的借款)除以未偿还的 e代币(eToken) 余额总数来计算的。与 Euler 集成的协议可以通过在 e代币(eToken) 上调用convertBalanceToUnderlying(),使用汇率来计算 eToken 存款的标的价值。

On July 25th, Sherlock notified the Euler Labs team about a bug bounty submission they received for their staking system, which uses Euler. It was a sophisticated attack that relied on the interactions between three separate protocols: Euler, Sherlock’s staking system, and the 1inch DEX aggregator.

7 月 25 日,Sherlock 通知了 Euler Labs 团队,他们收到了其使用 Euler 质押系统提交的漏洞赏金。这是一种复杂的攻击,依赖于三个独立协议之间的交互:Euler、Sherlock 的质押系统和 1inch DEX 聚合器。

The bug bounty detailed that the swap module allowed a user to exchange one eToken for another using either Uniswap or 1inch. However, with 1inch, the swap data was treated as a black box by the Euler contracts, and the 1inch router allowed the invocation of arbitrary contracts (including attacker created ones). Fortunately, the Euler system used a reentrancy guard that prevented re-entering into Euler at that time.

漏洞赏金详细说明了交换模块允许用户使用 Uniswap 或 1inch 将一个 eToken 换成另一个。然而,对于 1inch,交易所数据被 Euler 合约视为黑盒,并且 1inch 路由器允许调用任意合约(包括攻击者创建的合约)。幸运的是,当时Euler系统使用了一个复入防护,阻止了其重新进入Euler。

Unfortunately, during the 1inch execution, after a swap was performed the funds would have been moved into the Euler contract but have not yet been credited to the total balances, and in fact cannot have been because it did not know the precise amount that would be returned from 1inch. This meant that at this point calling convertBalanceToUnderlying() would return an incorrect value. An attacker could have invoked a victim contract, such as Sherlock’s staking contract, and it would have used an incorrect exchange rate for its computations.

不幸的是,在 1inch执行期间,执行一笔交换(swap)后,资金被转移到 Euler 合约中,但尚未记入总余额,当然事实上也不可能(计入余额),因为合约其实不知道从 1inch 返回的确切金。这意味着此时调用 convertBalanceToUnderlying() 将返回不正确的值。攻击者可能会调用受害者合约,例如 Sherlock 的质押合约,并且会使用不正确的汇率进行计算。

Another way of describing this is that Swaps were not atomic operations in Euler: They consisted of underlying token transfers, followed by updates to EToken balances. Critically, due to the 1inch router’s flexibility, an attacker could have run code in between those two operations.

另一种描述方式是交换不是Euler中的原子操作:它们包括底层代币转移,然后是对 e代币(eToken) 余额的更新。至关重要的是,由于 1inch 路由器的灵活性,攻击者可以在这两个操作之间运行代码。

解决之道 (Mitigation)

The Euler Labs team together with Sherlock discussed several ways of fixing this issue. Simply removing 1inch swapping support altogether was considered, but this is undesirable because Euler users can often receive better prices and execution from 1inch. Additionally, there may be other opportunities for attackers to run arbitrary code at times when Euler’s internal data was in an inconsistent state, so this was not a comprehensive solution.

Euler Labs 团队与 Sherlock 一起讨论了解决此问题的几种方法。我们考虑过简单地完全删除 对 1inch 交换的支持,但这是不可取的,因为Euler用户通常可以从 1inch 获得更好的价格和执行。此外,当 Euler 的内部数据处于不一致状态时,攻击者可能还有其他机会运行任意代码,因此这不是一个全面的解决方案。

Improving the atomicity of the swapping operation, or sanitising the 1inch “black box” swap data prior to a swap were other options, but these were 4 and still not comprehensive fixes.

提高交换操作的原子性,或在交换之前清理 1inch “黑盒”的交换数据,是另一个选择,但这也非长久之计,依然不是全面的修复。

The option selected was to add what we are calling a read-only re-entrancy guard. This works by having convertBalanceToUnderlying() (and all other methods that use the internal loadAssetCacheRO utility) verify that the re-entrancy guard has not been locked. If it has, then an error is thrown. Typical integrations will propagate this error and revert, preventing an attacker from taking advantage of inconsistent exchange rates.

选择的选项是添加我们所谓的只读型复入防护。通过使用convertBalanceToUnderlying()(以及所有使用内部loadAssetCacheRO 用例程序的其他方法)验证复入防护没有被锁定来生效。如果有,则抛出错误。典型的集成将传播此错误并随后恢复,防止攻击者利用不一致的汇率。

On Aug 4th, this fix was deployed, which transparently fixed the issue for all existing and future Euler integrations.

8 月 4 日,此修复程序 被部署,它透明地修复了所有现有和未来 Euler 集成的问题。

While this was technically a breaking change, existing integrations were analysed and future users were considered before determining that this restriction would not cause any significant issues for legitimate users. Instead, this provided a comprehensive solution to the attack identified in Sherlock’s bug bounty, as well as any future cases where users are able to execute arbitrary code during the execution of an Euler operation.

虽然这在技术上是一项重大更改,但在确定此限制不会对合法用户造成任何重大问题之前,我们分析了现有集成并考虑了未来用户。这也为 Sherlock 的漏洞赏金中确定的攻击—未来用户能够在执行Euler运算期间执行任意代码—提供了一个全面的解决方案。

鸣谢 (Thanks)

Euler Labs would like to thank the Sherlock team, who brought this issue to attention and collaborated on designing and deploying the mitigation described above.

Euler Labs 要感谢 Sherlock 团队,他们提请注意此问题并合作设计和部署上述解决方案。

The Labs team would also like to thank the teams behind the various other Euler integrations for acting promptly and professionally to ensure no users’ funds were at risk.

Labs 团队还要感谢其他各 Euler 集成背后的团队,他们迅速而专业地采取行动,确保没有用户的资金处于危险之中。

关于Euler (About Euler)

Euler is a capital-efficient permissionless lending protocol that helps users to earn interest on their crypto assets or hedge against volatile markets without the need for a trusted third-party. Euler features a number of innovations not seen before in DeFi, including permissionless lending markets, reactive interest rates, protected collateral, MEV-resistant liquidations, multi-collateral stability pools, sub-accounts, risk-adjusted loans and much more. For more information, visit euler.finance.

Euler 是一种资本效率高的无许可借贷协议,可帮助用户从其加密资产中赚取利息或对冲波动的市场,而无需受信第三方。 Euler 具有许多在 DeFi 中前所未有的创新,包括无许可的借贷市场、回应性利率、受保护的抵押品、抗 MEV 清算、多抵押品稳定池、子账户、风险调整贷款等等。有关更多信息,请访问 euler.finance

加入社区 (Join the Community)

Follow us Twitter. Join our Discord. Keep in touch on Telegram (communityannouncements). Check out our website. Connect with us on LinkedIn.

关注我们 Twitter。加入我们的 Discord。在 Telegram 上保持联系(communityannouncements)。查看我们的网站。在 LinkedIn 上与我们联系。

赞赏