主页 > 比特币 > 正文

Aave经历惊魂一刻 这个漏洞差点酿成一场危机

2020-12-17 18:18

注:今日,DeFi安全审计公司Trail of Bits披露了Aave借贷协议此前存在的一个严重漏洞,在发现到该问题后,Aave迅速修复了该漏洞,从而避免了一场危机。

原文来自Trail of Bits:

12月3日,知名DeFi借贷协议Aave部署了V2版本,尽管我们并没有被雇佣来查看其代码,但在次日,我们还是对其进行了简单审查。很快,我们就发现了一个影响Aave V1和V2版本合约的漏洞,并报告了该问题。在将我们的分析发送给Aave的一小时内,他们的团队修复了该漏洞,以减轻潜在影响。如果该漏洞被利用,这一问题将破坏Aave,并影响外部DeFi合约中的资金。

据悉,有5家不同的安全公司审查了Aave代码库,其中有一些使用了形式化验证。然而,这个漏洞并没有被这些公司注意到。这篇文章描述了这一问题,以及“该漏洞是如何逃过检测”等其它的一些经验教训。此外,我们也在开发一种新的Slither检测器,它可以识别这一漏洞,从而为以太坊社区提高安全性。

漏洞

Aave使用了delegatecall代理模式,这一点我们在过去的文章中已经详细讨论过了。简单来看,每个组件被分成了两个合约:(1)包含实现的逻辑合约,(2)包含数据并使用delegatecall与逻辑合约进行交互的代理。在逻辑合约上执行代码时,用户与代理合约进行交互。这是delegatecall代理模式的简化表示:

Aave经历惊魂一刻 这个漏洞差点酿成一场危机

在Aave中,LendingPool(LendingPool.sol)是使用delegatecall代理的可升级组件。

而我们发现的漏洞依赖于这些合约中的两个功能:

  • 可以直接调用逻辑合约的函数,包括初始化函数;

  • 借贷池具有其自己的delegatecall功能;

  • 初始化可升级合约

    这种可升级模式的一个限制是,代理不能依赖逻辑合约的构造函数(Constructor)进行初始化。因此,状态变量和初始设置必须在公共初始化函数中执行。

    在LendingPool中,初始化函数设置提供者地址(_addressesProvider):

    Aave经历惊魂一刻 这个漏洞差点酿成一场危机

    initializer调节器防止多次调用initialize,它要求满足以下条件为true:

    Aave经历惊魂一刻 这个漏洞差点酿成一场危机

    以下:

  • 初始化允许在相同交易中多次调用调节器(因此有多个initialize函数);

  • isConstructor()是代理执行代码所需的;