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