DeFi協議Akropolis漏洞詳解:駭客復現“經典重入攻擊”擄走203萬DAI

昨天晚間19時50分,DeFi 協議 Akropolis 遭到了駭客攻擊。

區塊鏈安全公司 PeckShield(派盾)安全人員迅速定位到問題在於,Akropolis  專案的 SavingsModule 合約在處理使用者儲存資產時存在某種缺陷,駭客利用此缺陷連續實施了17次重入攻擊,導致其 YCurve 和 sUSD 資金池損失了203萬枚 DAI。 

技術概要:

本次攻擊的原因如下:

1)合約沒有對使用者儲存的 Token 進行白名單校驗
2)關鍵的 deposit 函式沒有對重入攻擊的保護

簡單而言:駭客利用 Akropolis 專案存在的儲存資產校驗缺陷,向合約發起連續多次的重入攻擊,致使 Akropolis 合約在沒有新資產注入的情況下,憑空增發了大量的 pooltokens,進而再利用這些 pooltokens 從 YCurve 和 sUSD 池子中提取 DAI,最終導致專案合約損失了203萬枚 DAI。

攻擊過程詳解:

攻擊流程復現:

我們透過分析駭客實施攻擊的交易雜湊(0xe1f375a47172b5612d96496a4599247049f07c9a7d518929fbe296b0c281e04d)發現,攻擊來自於一個惡意的 ERC20 合約地址(0xe2307837524Db8961C4541f943598654240bd62f)

這個惡意合約實現了一個鉤子函式,使得函式在 transferFrom() (function signature: 0x23b872dd)被呼叫的時候會被執行。

攻擊者先是呼叫 SavingsModule.sol (https://github.com/akropolisio/delphi/blob/release-1.0/contracts/modules/savings/SavingsModule.sol#L217-L277) 中的 deposit() 函式,並將自己編寫的位於 0xe230 開頭的惡意合約作為要儲存的代幣地址傳入。當其惡意代幣的 transferFrom() 函式被呼叫時,其鉤子函式會再次呼叫 deposit() 函式並存入真實的 DAI 資產。

由於 pooltokens 增發的量透過代幣 deposit 前後餘額的差值得出。所以第二次 deposit 的真實的 DAI 資產會被計算兩次用於鑄造 pooltokens。第一次是在惡意合約 0xe230 儲存的時候,第二次是在 DAI 儲存的時候。也就是說,如果第二次儲存的時候存入了 25K DAI, 那麼由於重入攻擊,總的鑄造的 pooltokens 將會是雙倍,也就是 50K DAI 。

以此類推,駭客總共發起 17次重入攻擊並獲得了總共 2,030,841.0177個DAI 資產。

值得注意的是,在攻擊的最開始,攻擊者還使用了 dYdX 的閃貸功能(https://etherscan.io/tx/0xddf8c15880a20efa0f3964207d345ff71fbb9400032b5d33b9346876bd131dc2)。

核心漏洞詳解:

接下來,我們分析下存在漏洞的代幣儲存邏輯。Akropolis 的使用者可以將代幣儲存入Delphi Savings Pools,而資金池會鑄造相應的 pooltokens 給使用者。核心邏輯在SavingsModule::deposit()(1,944行)。

第一步:攻擊者呼叫 deposit() 函式並提供 _tokens 引數。這個函式在進一步呼叫 depositToProtocol(_protocol, _tokens, _dnAmounts) 前後會計算代幣的餘額,並透過代幣餘額的變化來決定將要鑄造的 poolTokens 數目(第1,970行)。而 depositToProtocol() 函式會呼叫目標代幣的 safeTransferFrom()函式來進行代幣的轉賬(第2,004行)。然而 deposit() 函式沒有對重入攻擊進行檢測,也沒有檢查存入的代幣是否為惡意代幣;

第二步:在惡意代幣的 transferFrom() 函式被呼叫的時候,觸發鉤子函式,從而再次呼叫 deposit() 函式;

第三步:因為第二次呼叫 deposit() 函式的時候攻擊者存入了真正的 DAI 代幣使得池子的代幣餘額發生變化,所以攻擊者可以獲得資金池鑄造的 poolTokens;

第四步:當第二次 deposit() 函式呼叫結束的時候,程式碼執行流程將返回第一次儲存代幣呼叫 depositToProtocol() 函式的上下文。這個時候,代幣餘額變化將被再次計算。此時代幣餘額的變化和第二次呼叫 deposit() 函式代幣餘額變化一樣。因此攻擊者可以再次獲得相應數目的 poolTokens。

被盜資產情況:

這次攻擊的被盜資產目前被儲存在錢包[0x9f26](https://etherscan.io/address/0x9f26ae5cd245bfeeb5926d61497550f79d9c6c1c)中。PeckShield 旗下數字資產追蹤平臺 CoinHolmes 正在對該地址做全方位監控,並對其資金流向做進一步的鎖定分析和追蹤,以便協助專案方挽回被盜資產。

免責聲明:

  1. 本文版權歸原作者所有,僅代表作者本人觀點,不代表鏈報觀點或立場。
  2. 如發現文章、圖片等侵權行爲,侵權責任將由作者本人承擔。
  3. 鏈報僅提供相關項目信息,不構成任何投資建議

推荐阅读