昨天晚間 19 時 50 分,DeFi 協議 Akropolis 遭到了駭客攻擊。本次攻擊的原因如下:1)合約沒有對用戶存儲的 Token 進行白名單校驗 2)關鍵的 deposit 函數沒有對重入攻擊的保護。最終駭客總共發起 17 次重入攻擊並獲得了總共 2,030,841.0177 個 DAI 資產。
(前情提要:DeFi協議「Akropolis」遭閃電貸攻擊!駭客抽走200萬美元DAI,現暫停穩定幣資金池)
區塊鏈安全公司 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 正在對該地址做全方位監控,並對其資金流向做進一步的鎖定分析和追踪,以便協助項目方挽回被盜資產。
📍相關報導📍
DeFi協議「Akropolis」遭閃電貸攻擊!駭客抽走200萬美元DAI,現暫停穩定幣資金池
閃電貸策略:那攻擊者能取走 MakerDAO 的「7 億美元」DeFi 資產抵押品嗎?
無懼 7.5 億駭客案風波!Vitalik 捍衛以太坊 DeFi 領域:勿就單一事件評判「整體安全性」
讓動區 Telegram 新聞頻道再次強大!!立即加入獲得第一手區塊鏈、加密貨幣新聞報導。
LINE 與 Messenger 不定期為大家服務