Back to Blog

Mirror Protocol 如何被攻擊

Code Auditing
May 31, 2022
4 min read

Mirror Protocol 被 @FatMan 舉報遭到攻擊。這篇部落格有關於此事的詳細報導。 在這篇短文中,我們將透過攻擊交易來詳細說明此事件是如何發生的。

免責聲明:本文基於公開的交易紀錄以及我們對 Mirror 協議與 Terra 生態系統的理解。如果內容有任何不準確之處,請告知我們。歡迎對此部落格提出任何意見。

1 攻擊

1.1 準備階段

交易用於準備攻擊。

第 1 步: 在此交易中,攻擊者首先發送了 100,000 USTC 到鎖定合約(lock contract)。這對於開啟倉位並非必要,但對於此次攻擊至關重要。

第 2 步: 隨後,攻擊者透過存入 10 USTC 作為抵押品,並將 collateral_ratio 設定為 2.5,開啟了一個倉位。

這裡指定了 short_params,以便鑄造合約(mint contract)自動出售所鑄造的 mAsset(即 mETH),並將所得的 USTC 添加到該倉位的鎖定金額中。

第 2.1 步: 我們來逐步分析該交易。首先,將調用 open_position 函數來開啟一個 ID 為 43186 的空頭倉位。

第 2.2 步: 由於添加了可選的 short_params,合約將首先鑄造 0.001208 mETH(基於當前的 ETH 價格),然後透過在 mETH-UST Pair 中進行兌換來賣出它。

第 2.3 步:0.001208 mETH 將被兌換成 4.06582 USTC,扣除相關費用(如稅費)後,兌換所得的 USTC 將發送到鎖定合約。這是因為開啟的倉位只能在一段時間後才能解鎖。

第 2.4 步: 接著將調用 lock_position_funds_hook。在此函數中,position_locked_amount 是透過查詢 current_balance 並與 locked_funds 進行比較來計算的。

然而,正如我們在第 1 步中所見,由於 100,000 USTC 已被直接轉移到鎖定合約中,計算出的 locked_amount 將約為 100,004 USTC,而不是 4 USTC。

第 2.5 步: 最後,將調用 increase_short_token 來記錄 sLP 代幣。

至此,攻擊者透過將 100,000 USTC 直接發送到鎖定合約,並存入 10 USTC 作為抵押品,成功開啟了一個倉位。該倉位的鎖定金額約為 100,004 USTC,且可在一段時間後解鎖。攻擊者透過發送 1,000100,000 不等的 USTC,重複開啟了許多此類倉位。

1.2 攻擊

Mirror Protocol 沒有檢查倉位 ID 是否重複。在這種情況下,攻擊者可以提供多個重複的倉位 ID,從而反覆解鎖同一個倉位中的鎖定金額。

交易即為攻擊交易。例如,對於倉位 ID 43186,攻擊者重複了 437 次。

由於原始合約程式碼沒有檢查重複項,大約 43.7M437 * 0.1M)USTC 已被解鎖(在單次函數調用中)。

請注意,其他倉位也透過相同的機制被解鎖了。

2. 漏洞修復

該漏洞已在此 Commit 中修復。

具體來說,unlockable_positions 是一個包含待解鎖倉位 ID 的向量(vector)。在原始程式碼中,沒有檢查 unlockable_positions 中是否存在重複 ID。修復後的程式碼增加了對倉位 ID 重複性的檢查。

3. 結論

正如 @FatMan 和其他社群成員所指出的,這個 BUG 存在了幾個月並已在外部遭到利用。我們認為,對於已經在外部被利用的漏洞進行靜默修復並非良好的安全實踐。此外,我們也認為高知名度的 DeFi 專案應部署一些守門機制,以主動監控其應用程式的狀態,並在發生異常情況時發出警報。

Best Security Auditor for Web3

Validate design, code, and business logic before launch. Aligned with the highest industry security standards.

BlockSec Audit