時間:2023-08-11|瀏覽:265
原文來自TrailofBits:
12月3日,知名DeFi借貸協(xié)議Aave部署了V2版本,盡管我們并沒有被雇傭來查看其代碼,但在次日,我們還是對其進(jìn)行了簡單審查。很快,我們就發(fā)現(xiàn)了一個影響AaveV1和V2版本合約的漏洞,并報告了該問題。在將我們的分析發(fā)送給Aave的一小時內(nèi),他們的團(tuán)隊修復(fù)了該漏洞,以減輕潛在影響。如果該漏洞被利用,這一問題將破壞Aave,并影響外部DeFi合約中的資金。
據(jù)悉,有5家不同的安全公司審查了Aave代碼庫,其中有一些使用了形式化驗證。然而,這個漏洞并沒有被這些公司注意到。這篇文章描述了這一問題,以及“該漏洞是如何逃過檢測”等其它的一些經(jīng)驗教訓(xùn)。此外,我們也在開發(fā)一種新的Slither檢測器,它可以識別這一漏洞,從而為以太坊社區(qū)提高安全性。
漏洞 Aave使用了delegatecall代理模式,這一點我們在過去的文章中已經(jīng)詳細(xì)討論過了。簡單來看,每個組件被分成了兩個合約:(1)包含實現(xiàn)的邏輯合約,(2)包含數(shù)據(jù)并使用delegatecall與邏輯合約進(jìn)行交互的代理。在邏輯合約上執(zhí)行代碼時,用戶與代理合約進(jìn)行交互。這是delegatecall代理模式的簡化表示:
在Aave中,LendingPool(LendingPool.sol)是使用delegatecall代理的可升級組件。
而我們發(fā)現(xiàn)的漏洞依賴于這些合約中的兩個功能:
可以直接調(diào)用邏輯合約的函數(shù),包括初始化函數(shù); 借貸池具有其自己的delegatecall功能; 初始化可升級合約 這種可升級模式的一個限制是,代理不能依賴邏輯合約的構(gòu)造函數(shù)(Constructor)進(jìn)行初始化。因此,狀態(tài)變量和初始設(shè)置必須在公共初始化函數(shù)中執(zhí)行。
在LendingPool中,初始化函數(shù)設(shè)置提供者地址(_addressesProvider):
initializer調(diào)節(jié)器防止多次調(diào)用initialize,它要求滿足以下條件為true:
以下: 初始化允許在相同交易中多次調(diào)用調(diào)節(jié)器(因此有多個initialize函數(shù)); isConstructor是代理執(zhí)行代碼所需的; revision>lastInitializedRevision?允許在合約升級時再次調(diào)用初始化函數(shù); 雖然它通過代理,預(yù)期可正常工作,但是(3)也允許任何人直接在邏輯合約上調(diào)用initialize函數(shù)。一旦邏輯合約被部署: revision將為0x2(LendingPool.sol#L56); lastInitializedRevision將為0x0; 而漏洞是:任何人都可以在Lending