不安分的駭客又“偷襲”?MonoX被攻擊事件全解析

買賣虛擬貨幣


11月30日,鏈必應-區塊鏈安全態勢感知平臺輿情監測顯示,自動做市商協議monox遭閃電貸攻擊,獲利約3100萬美元。關於本次攻擊,成都鏈安技術團隊第一時間進行了事件分析。


#1 事件概覽

攻擊發生之後,monox在官方推特確認其合約遭到攻擊,團隊正在調查並將盡最大努力追回被盜資金。


monox使用單邊代幣池模型,其使用vcash穩定幣與amm提供的代幣建立虛擬的交易對。簡單來說,monox建立的是代幣-vcash交易對,新增流動性時,只需要新增代幣,進行任意代幣兌換時,兌換路徑為:代幣a -> vcash -> 代幣b,而不需要像uniswap一樣經過多個交易對:代幣a -> pair1-> pair2-> pair3-> token b。


#2 事件具體分析

攻擊者使用相同的地址

0xecbe385f78041895c311070f344b55bfaa953258對以太坊以及matic上的monox發起了攻擊,在兩個平臺進行攻擊所部署的合約一致。攻擊交易為:

以太坊:

0x9f14d093a2349de08f02fc0fb018dadb449351d0cdb7d0738ff69cc6fef5f299

matic:

0x5a03b9c03eedcb9ec6e70c6841eaa4976a732d050a6218969e39483bb3004d5d

由於兩個平臺程式碼完全一致,下面的分析將基於以太坊上的攻擊交易進行。

round 1

將 0.1 weth 透過 monoswap中兌換為79.98609431154262101 mono;

圖 1 weth兌換mono

round 2

移除monoswap所有的流動性。這裡利用了monoswap合約中的任意地址流動性移除漏洞。

漏洞1:

monoswap合約中未檢測流動性的所有者to是否為msg.sender。_removeliquidity函式中,如圖2所示,第443行,獲取呼叫者(攻擊合約)最後一次新增流動性的時間戳,返回結果是0,因此第445行的檢測透過。第446行,toplpholderof如果不是呼叫者(攻擊合約)地址,第447行的檢測透過。此後移除流動性相關程式碼中,再無msg.sender相關的操作。

圖 2 _removeliquidity原始碼

圖 3 第一次移除流動性內部呼叫細節

圖 4 移除monoswap中mono池所有的流動性

round 3

新增極少數量的mono到monoswap中,這一步是為了後面快速提升mono的價格做準備。


圖 5 攻擊合約新增流動性

round 4

利用monoswap合約中的代幣兌換價格覆寫漏洞,反覆進行同種代幣的兌換,拉昇mono的價格。第3步攻擊者將monoswap合約中mono的儲量控制到了一個極小的值,目的就是更快的以極低的mono數量來拉昇mono的價格。

漏洞2:

monoswap合約的代幣兌換過程為:檢查兌換引數是否正常,然後計算應輸入輸出代幣的數量以及代幣兌換後的價格,最後執行兌換操作並將新的代幣價格寫入賬本。以上邏輯在不同種代幣兌換的時候會正常執行。但是在同種代幣兌換時,將出現兩處問題:

(1) 在_getnewprice函式計算應輸入輸出代幣數量時,未考慮到兌換過程中交易池代幣儲量的變更,同種代幣是基於相同的初始價格進行兌換後價格的計算。

(2)在最後一步更新代幣過程中,未考慮到同種代幣進行兌換時,兌出代幣的價格更新操作(圖6 第841行)會覆蓋兌入代幣更新的操作(圖6 第830行)。該漏洞導致mono代幣兌換mono代幣時,mono的價格異常增長。此外不止攻擊者使用的swapexacttokenfortoken函式存在該問題,swaptokenforexacttoken函式也存在該問題。

圖 6 swapin函式原始碼

圖 7 兌換過程引數計算


圖 8 兌換後價格計算

圖 9 swapout函式原始碼

現在看看攻擊者是如何利用漏洞2進行攻擊的:

(1)如圖10所示,初始mono的價格為5.218 vcash/mono。

圖 10 初始mono價格

然後攻擊者反覆進行mono->mono的兌換,一共進行了55次兌換,如下圖所示:

圖 11 反覆兌換,拉昇mono價格

對其中一筆兌換交易進行分析,每次兌換的數量是交易池中mono的總量減去1,這是能夠最大提升mono價格的兌換數量(使圖8 _getnewprice第527行,分母為1)。另外由於交易池中mono的總量較低(第3步的操作),攻擊者已經透過第1步保證了有足夠的餘額進行兌換操作。

圖 12 mono兌換細節

截止至兌換結束時,mono的價格已經被拉昇至843,741,636,512.366 vcash/mono。攻擊合約中剩餘51.92049285389317 mono。



圖 13 最終的mono價格

(2)透過uniswap v2的usdc/weth池借入了847.2066974335073 weth。然後攻擊者透過monoswap將0.0709532091008681 mono 兌換為4,029,106.880396 usdc,然後將usdc歸還給usdc/weth池。注意,這裡實際上是攻擊者將從monoswap中兌換的usdc到uniswap v2中兌換為weth,而不是閃電貸攻擊。

(3)攻擊者所有轉出的資產如下:

幣種數量
usdc4,029,106.880396 (兌換為847.2066974335073 weth)
usdt4,525,120.098829 (兌換為949.0325798508261 weth)
weth452.9120530334938
wbtc21.42797145
duck5,155,863.718616853
mim4,125.858256772
imx274.9390440877583


所有被盜資產全部傳送到0x8f6a86f3ab015f4d03ddb13abb02710e6d7ab31b地址。

目前專案方已經和攻擊者進行了溝通,成都鏈安將持續對此事件進行監控。


#3 事件覆盤

這次攻擊事件中,攻擊者利用了合約中的兩個漏洞:(1)任何地址都可以任意移除指定地址的流動性;(2)特殊情況下的價格寫入操作覆蓋問題。

建議專案方在進行合約開發過程中做好許可權的檢查;在開發以及測試過程中將特殊情況納入考慮,例如同種代幣轉賬。


免責聲明:

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

推荐阅读

;