Web3 安全警示丨Restaking 大熱背後的風險:Prisma Finance 攻擊事件分析

2024-04-03 17:04:29

2024 年 3 月 28 日,Prisma Finance 遭遇攻擊,目前累計虧損約 1100 萬美元。攻擊發生後,Prisma Finance 緊急暫停了項目,並告知用戶趕緊取消委托授權(https://twitter.com/PrismaFi/status/1773371030129524957)。

攻擊簡述

Prisma Finance 是一個非托管、去中心化的,以抵押以太坊 LST(流動性質押代幣)鑄造穩定幣的項目。比如用戶可以通過抵押 wstETH 來鑄造 mkUSD,這個過程可以創建一個 trove,trove 可以理解為是一個記錄指定 borrower 的抵押借貸情況的寶庫,這個寶庫有一個 trove manager,用來管理寶庫的抵押物以及借貸幣(鑄造的穩定幣)。

本次的漏洞合約是 MigrateTroveZap 合約,該合約的主要功能是將用戶的抵押物從一個 trove manager 遷移到另一個 trove manager。因此創建 trove 的 borrower 就可能會授權 MigrateTroveZap 合約對其 trove 進行操作。然而 MigrateTroveZap 合約中的「 onFlashloan 」函數缺乏輸入驗證,從而允許攻擊者通過 MigrateTroveZap 合約操作其他 borrower 的 trove,將其他 borrower 的 trove 中的抵押品數量變少,但是債務不變,從而盜取其他 borrower 的抵押品。

攻擊中涉及的關鍵地址

本次攻擊涉及到多筆交易,我們僅以下面這比交易為例來對攻擊進行分析。

攻擊交易:https://etherscan.io/tx/0xe15fa959627871845f2f5bbfbd7529e6d2aff20ab14ece743f11641700bd7188

攻擊 EOA:

0x7e39e3b3ff7adef2613d5cc49558eab74b9a4202

攻擊者(合約):

0xd996073019c74b2fb94ead236e32032405bc027c

受害者(Prisma Finance TroveManager):

0x1cc79f3f47bfc060b6f761fcd1afc6d399a968b6

漏洞合約(Prisma Finance MigrateTroveZap):

0xcc7218100da61441905e0c327749972e3cbee9ee

一個被利用的 borrower,簡稱 BorrowerA:

0xcbfdffd7a2819a47fcd07dfa8bcb8a5deacc9ea8

穩定幣 mkUSD:

0x4591dbff62656e7859afe5e45f6f47d3669fbb28

質押物 wstETH:

0x7f39c581f595b53c5cb19bd0b3f8da6c935e2ca0

BorrowerOperations 合約:

0x72c590349535ad52e6953744cb2a36b409542719

攻擊流程分析

1. 攻擊准備

攻擊者觀測 borrower 借貸情況,尋找抵押率較高的 borrower,在這比攻擊交易中,找到的 borrower 為 BorrowerA。

攻擊者獲取 BorrowerA 在 TroveManager 中的 collateralToken(wstETH)和 debtToken(mkUSD)的數量,分別為「 824,599,953,913,164,625,273 」、「 598,174,188,906,400,741,697,930 」,在攻擊者發起攻擊時,wstETH 的價格大概為 $4155,大概估計一下抵押率為 570%,遠遠超過了最小抵押率 MCR 110%。這給後續攻擊創造了條件。

2. 攻擊實施

攻擊實施階段主要是攻擊者通過 mkUSD 的閃電貸服務,調用到漏洞合約 MigrateTroveZap 的「 onFlashLoan 」函數,「 onFlashLoan 」函數可以對攻擊者指定的 borrower 的 trove 進行置換,所謂置換即是先關閉這個 trove,再給 borrower 开啓一個新的 trove。這個功能本來是用來將抵押物遷移到不同的 trove manager。然而這個功能存在漏洞,一是它沒有校驗新开的 trove 是否和之前的 trove 具有同樣數量的抵押物,二是通過 mkUSD 的閃電貸服務,攻擊者可以操控別人的 trove。具體的攻擊步驟如下:

1、利用 mkUSD 的閃電貸服務調用到漏洞合約 MigrateTroveZap 的「 onFlashLoan 」函數,並在此時傳入上述觀測好的受害者 BorrowerA 的地址以及准備新开的 trove 的抵押品數量。攻擊者調用 mkUSD 的「 flashLoan 」函數進行閃電貸,借出 mkUSD 給 MigrateTroveZap(MigrateTroveZap 合約用來自動將同樣的抵押物遷移到不同的 trove manager),並在「 data 」參數中指定了後續操作需要用到的 BorrowerA 的地址、TroveManager 的地址、創建 trove 時抵押的 wstETH 的數量,具體傳入的參數如下所示:

mkUSD.flashLoan:

在「 flashLoan 」函數中,首先會給 MigrateTroveZap 鑄造「 598,174,188,906,400,741,697,930 」這么多 mkUSD,然後調用 MigrateTroveZap 的回調函數「 onFlashLoan 」,問題就出在了這個回調函數中。

2、在 MigrateTroveZap 的「 onFlashLoan 」函數中對 BorrowerA 的 trove 進行更換,之所以 MigrateTroveZap 能操作 BorrowerA 的 trove,是因為 BorrowerA 對 MigrateTroveZap 進行了委托授權。原本 BorrowerA 的 trove 抵押率比較高,但是抵押率比較高的 trove 被關閉掉,取而代之的是一個債務一樣,但是抵押率更低的 trove,這個操作能夠成功是因為更換 trove 時並沒有校驗新舊 trove 的抵押物數量是否一致,最終多余的抵押品數量會被留在 MigrateTroveZap 中。

詳細過程如下:

在 MigrateTroveZap 的「 onFlashLoan 」函數中,會將指定 account 的抵押物從 troveManagerFrom 遷移到 troveManagerTo,在本次調用中,從攻擊者傳入的「 data 」參數中解析出來,這兩個參數均指定為了 TroveManager 的地址。

MigrateTroveZap.onFlashLoan:

攻擊者指定的 account 是 BorrowerA,因此首先會調用 BorrowerOperations 的「 closeTrove 」函數將 BorrowerA 的 trove 關閉掉,關閉之前會通過 modifier「 callerOrDelegated 」檢查 BorrowerA 是否授權調用發起者(在這裏是 MigrateTroveZap)代理它進行關閉 trove 的操作。由於 BorrowerA 確實授權了 MigrateTroveZap,因此判斷通過,並且此時並不處於 recovery mode,因此 BorrowerOperations 最終調用 TroveManager 的「 closeTrove 」函數關閉 trove,在這個過程中,將 BorrowerA 的抵押品 wstETH(數量為「 824,599,953,913,164,625,273 」)轉給 MigrateTroveZap。隨後 burn 掉 MigrateTroveZap 的 mkUSD,數量為「 597,974,188,906,400,741,697,930 」。

BorrowerOperations.closeTrove:

緊接着 BorrowerOperations 的「 openTrove 」函數被調用,此時傳入的參數「 _collateralAmount 」為攻擊者在「 data 」參數中指定的「 192,125,967,324,963,177,654 」,而「 _debtAmount 」為攻擊者向 mkUSD 合約閃電貸的數量加上閃電貸的手續費,數值為「 598,712,545,676,416,502,365,458 」。經過計算,現在並不處於 recovery mode,因此最終用來計算抵押率的 debt 的數量「 compositeDebt 」為「 _debtAmount 」+ debt borrowing 費 + debt gas 補償,具體數值為「 598,912,545,682,977,901,520,496 」,根據「 _collateralAmount 」、「 _debtAmount 」和價格計算出來的 ICR(Individual Collateral Rate) 約為 133%,大於 MCR( 最小抵押率 )110%,符合創建 trove 的條件。隨後 MigrateTroveZap 給 TroveManager 轉移「 _collateralAmount 」數量的 wstETH,MigrateTroveZap 拿到給其鑄造的「 _debtAmount 」數量的 mkUSD。這番操作相當於攻擊者利用 MigrateTroveZap 合約,將 BorrowerA 本來有很多抵押品的 trove,換成了抵押品較少的 trove,而攻擊者想要盜取的,正是這一部分抵押品差額。

BorrowerOperations.openTrove:

3、回調結束以後,回到 mkUSD 的 flashLoan 函數。此時 MigrateTroveZap 持有的 mkUSD 的數量正好比需要償還的 mkUSD 的數量多一些,通過 burn 掉 MigrateTroveZap 的 mkUSD 成功償還了閃電貸的債務。至此,MigrateTroveZap 相當於額外獲得了約 632 個 wstETH。接下來攻擊者就开始想辦法把這 632 個 wstETH 給套到自己手上了。

3. 收割贓款

收割贓款的步驟主要是攻擊者將#攻擊實施#步驟中盜取的留在 MigrateTroveZap 合約中的 wstETH 提取出來。攻擊者依然是利用 MigrateTroveZap 合約的漏洞。這一次攻擊者先自己开了一個抵押率較低的 trove,然後通過 mkUSD 的閃電貸服務進入到漏洞合約 MigrateTroveZap 的「 onFlashLoan 」函數,對自己的 trove 進行更換。

相較於#攻擊實施#階段對 BorrowerA 的 trove 的更換,不同之處在於,攻擊者對自己 trove 的更換,是要從低抵押率的 trove 更換為高抵押率的 trove,而用到的抵押物正是 MigrateTroveZap 中多出來的 wstETH。之所以能用到 MigrateTroveZap 的 wstETH,是因為攻擊者也授權 MigrateTroveZap 對其 trove 進行管理,那么在更換 trove 時,抵押物都是在 TroveManager 和 MigrateTroveZap 之間流轉。所以在开一個新的 trove 時,如果用到的抵押物數量增多,就會直接扣除 MigrateTroveZap 中的抵押品數量。

最終攻擊者的 trove 在更換之後擁有了更多的抵押物,攻擊者就可以自己發起關閉 trove 的調用,將抵押物提取出來,從而將盜取的抵押物收入囊中。

詳細過程如下:

1、攻擊者從 Balancer 中閃電貸出 1 個 wstETH,從而調用到攻擊者的「 receiveFlashLoan 」函數。

2、在「 receiveFlashLoan 」函數中,攻擊者首先授權 BorrowerOperations 使用其 wstETH,然後再授予 MigrateTroveZap 代理權。

3、接着攻擊者調用 BorrowerOperations 的「 openTrove 」函數給自己創建一個 trove,使用閃電貸出的 1 個 wstETH 進行抵押,借 2000 個 mkUSD,此時的抵押率大約為 188%。這是攻擊者為了後續操作做的一個准備。傳入的參數詳細信息如下:

4、攻擊者再次調用 mkUSD 合約的 flashLoan 函數進行閃電貸,這一次是借 2000 個 mkUSD 給 MigrateTroveZap,跟#攻擊實施#階段類似,給 MigrateTroveZap 鑄造了 2000 個 mkUSD,並觸發了 MigrateTroveZap 的回調函數「 onFlashLoan 」。這一次攻擊者傳入的「 data 」參數如下,攻擊者指定的想要遷移的 trove 是攻擊者上一步創建的 trove。

5、在函數「 onFlashLoan 」裏,同樣先執行「 closeTrove 」函數,TroveManager 將 1 個 wstETH 轉給 MigrateTroveZap,然後 burn 掉 MigrateTroveZap 約 2000 個 mkUSD。隨後執行「 openTrove 」函數,這一次攻擊者指定的「 _collateralAmount 」值為「 633,473,986,588,201,447,619 」,幾乎是 MigrateTroveZap 中所有的 wstETH,當然其中包括了在#攻擊實施#階段套取的約 632 個 wstETH。此時「 _debtAmount 」具體值為「 2,001,800,000,000,000,000,000 」。抵押率大概為 1195%。trove 創建成功,MigrateTroveZap 將約 633 個 wstETH 轉給 TroveManager,並給 MigrateTroveZap 鑄造了約 2001 個 mkUSD。

6、回調結束以後,回到 mkUSD 的 flashLoan 函數。MigrateTroveZap 償還閃電貸債務,持有的 mkUSD 被 burn 掉。

7、到這一步,攻擊者自己創建的 trove 依然存在,不同的是,經過前面幾步在 mkUSD 中的閃電貸,攻擊者將自己的 trove 中抵押品的數量提升到了約 633 個 wstETH。

8、攻擊者調用 BorrowerOperations 的「 closeTrove 」函數,關閉 trove,從 TroveManager 處拿到約 633 個 wstETH,並 burn 掉相應的 mkUSD 債務。

9、攻擊者償還在 Balancer 中借出的 1 個 wstETH。

至此,收割贓款結束,攻擊者獲利約 632 個 wstETH。

資金流追蹤

本次攻擊共涉及到三個 EOA,如下:

  • Exploiter 1: 0x7E39E3B3ff7ADef2613d5Cc49558EAB74B9a4202

  • Exploiter 2: 0x7Fe83f45e0f53651b3ED9650d2a2C67D8855e385

  • Exploiter 3: 0x7C9FC6E2B908e858F30c5c71a20273315Efd5cf8

Exploiter 2 和 Exploiter 3 共獲利約 200 個 ETH,而另外的約 3200 個 ETH 則是被聲稱是白帽的 Exploiter 1 獲取 (https://etherscan.io/tx/0xc2825fd6dd05e8ec9f271d63efdebd06e78296afc0813c65788790567916d209)。目前 Prisma Finance 項目方仍在與聲稱是白帽的 Exploiter 1 溝通資金退還事宜。

Exploiter 1 向項目方开出了以下條件:

  1. Prisma 團隊需要進行一次在线新聞發布會;

  2. 團隊所有成員都必須現場露面和出示身份證明;

  3. 向 Prisma 的所有用戶、投資方和 Exploiter 1 表示道歉和感謝;

  4. 具體介紹本次事故裏面的問題所在:智能合約審計方是誰,以及 Prisma 將來提高安全性的計劃;

  5. Prisma 需要承認 Exploiter 1 在這起事件中沒有任何責任,Exploiter 1 純粹是在幫助 Prisma 修復問題;

  6. Prisma 需要在 12 小時內修改事後總結中所有具有指控性的措辭。

通過 ZAN 的 KYT 服務,我們可以看到,Exploiter 1 將資金轉到了三個不同的地址上,最終這些資金一部分流入了 Tornado Cash 中。詳細資金流轉情況請查看鏈接:https://zan.top/kyt/controller/transaction?entity=0x7e39e3b3ff7adef2613d5cc49558eab74b9a4202&ecosystem=ethereum

轉入 Tornado Cash 資金流動情況

Exploiter 2 的資金流轉情況:https://zan.top/kyt/controller/transaction?entity=0x7fe83f45e0f53651b3ed9650d2a2c67d8855e385&ecosystem=ethereum

Exploiter 3 的資金流轉情況:https://zan.top/kyt/controller/transaction/?entity=0x7C9FC6E2B908e858F30c5c71a20273315Efd5cf8&ecosystem=ethereum

安全建議

通過分析本次攻擊事件,我們有如下建議:

  1. 「 委托授權要慎重 」。一是項目方需要仔細衡量項目中是否需要委托授權的邏輯,如果需要,那么一定要對相應操作進行嚴格的權限校驗以及輸入校驗,防止攻擊者利用該授權,傳入不合法的參數,篡改項目中關鍵變量。二是委托授權應該有時間限制,長期的授權,容易被用戶忽略,卻被攻擊者利用。

  2. 「 項目設置暫停機制 」。建議項目方在設計項目邏輯時,建立完善的暫停機制,以應對突發的意外事件,及時止損。

本文由 ZAN Team 的 Cara 撰寫,作者個人 X 账號@Cara6289。

鄭重聲明:本文版權歸原作者所有,轉載文章僅為傳播信息之目的,不構成任何投資建議,如有侵權行為,請第一時間聯絡我們修改或刪除,多謝。

推薦文章

btc日內再次下跌 短线應當如何處理?

盡管以太坊現貨ETF獲批是個好消息,但市場反應卻不如預期。在消息公布後,以太坊價格出現了小幅下跌,...

加密蓮
122 3個月前

7月23日、BTC(合約)ETH(合約)行情分析及操作策略

昨日收益還是不錯的,日內給出的現價空單分別止盈我們目標點位,恭喜跟上的朋友喫肉。時間一晃到月底了,...

倪老師
121 3個月前

幣圈院士:血與淚的教訓!交易者為何總是撞死在同一棵樹上?

幣圈院士談。交易市場中的幾種“死法” 在幣圈市場鱗次櫛比的海洋,風起雲湧,時常讓人感到驚手不及。在...

幣圈院士
128 3個月前

7月23:Mt. Gox 比特幣錢包在市場緊縮的情況下轉移了價值 28.2 億美元的 BTC

7月23:Mt. Gox 比特幣錢包在市場緊縮的情況下轉移了價值 28.2 億美元的 BTC一個引...

168超神
120 3個月前

悅盈:比特幣68000的空完美落地反彈繼續看跌 以太坊破前高看回撤

一個人的自律中,藏着無限的可能性,你自律的程度,決定着你人生的高度。 人生沒有近路可走,但你走的每...

我是周悅盈
101 3個月前

btc完美盈利 晚間波動較大注意

昨日btc空單完美給到,最大化走出一千七百點空間~ btc: 日內开盤下跌繼續測試66000一线,...

加密蓮
112 3個月前