時間:2021-12-24|瀏覽:349
鏈必應(yīng)-區(qū)塊鏈安全態(tài)勢感知平臺輿情監(jiān)測顯示,自動做市商協(xié)議MonoX遭閃電貸攻擊,獲利約3100萬美元。關(guān)于本次攻擊,成都鏈安技術(shù)團隊第一時間進行了事件分析。
事件概覽
攻擊發(fā)生之后,MonoX在官方推特確認(rèn)其合約遭到攻擊,團隊正在調(diào)查并將盡最大努力追回被盜資金。
MonoX使用單邊代幣池模型,其使用vCASH穩(wěn)定幣與AMM提供的代幣創(chuàng)建虛擬的交易對。簡單來說,MonoX創(chuàng)建的是代幣-vCASH交易對,添加流動性時,只需要添加代幣,進行任意代幣兌換時,兌換路徑為:代幣A -> vCASH -> 代幣B,而不需要像Uniswap一樣經(jīng)過多個交易對:代幣A -> Pair1-> Pair2-> Pair3-> Token B。
事件具體分析
攻擊者使用相同的地址
對以太坊以及MATIC上的MonoX發(fā)起了攻擊,在兩個平臺進行攻擊所部署的合約一致。攻擊交易為:
移除Monoswap所有的流動性。這里利用了Monoswap合約中的任意地址流動性移除漏洞。
漏洞1:
Monoswap合約中未檢測流動性的所有者to是否為msg.sender。_removeLiquidity函數(shù)中,如圖2所示,第443行,獲取調(diào)用者(攻擊合約)最后一次添加流動性的時間戳,返回結(jié)果是0,因此第445行的檢測通過。第446行,topLPHolderOf如果不是調(diào)用者(攻擊合約)地址,第447行的檢測通過。此后移除流動性相關(guān)代碼中,再無msg.sender相關(guān)的操作。
添加極少數(shù)量的MONO到Monoswap中,這一步是為了后面快速提升MONO的價格做準(zhǔn)備。
利用Monoswap合約中的代幣兌換價格覆寫漏洞,反復(fù)進行同種代幣的兌換,拉升MONO的價格。第3步攻擊者將Monoswap合約中MONO的儲量控制到了一個極小的值,目的就是更快的以極低的MONO數(shù)量來拉升MONO的價格。
漏洞2:
Monoswap合約的代幣兌換過程為:檢查兌換參數(shù)是否正常,然后計算應(yīng)輸入輸出代幣的數(shù)量以及代幣兌換后的價格,最后執(zhí)行兌換操作并將新的代幣價格寫入賬本。以上邏輯在不同種代幣兌換的時候會正常運行。但是在同種代幣兌換時,將出現(xiàn)兩處問題:
(1) 在_getNewPrice函數(shù)計算應(yīng)輸入輸出代幣數(shù)量時,未考慮到兌換過程中交易池代幣儲量的變更,同種代幣是基于相同的初始價格進行兌換后價格的計算。
(2)在最后一步更新代幣過程中,未考慮到同種代幣進行兌換時,兌出代幣的價格更新操作(圖6 第841行)會覆蓋兌入代幣更新的操作(圖6 第830行)。該漏洞導(dǎo)致MONO代幣兌換MONO代幣時,MONO的價格異常增長。此外不止攻擊者使用的swapExactTokenForToken函數(shù)存在該問題,swapTokenForExactToken函數(shù)也存在該問題。
現(xiàn)在看看攻擊者是如何利用漏洞2進行攻擊的:
然后攻擊者反復(fù)進行MONO->MONO的兌換,一共進行了55次兌換,如下圖所示:
對其中一筆兌換交易進行分析,每次兌換的數(shù)量是交易池中MONO的總量減去1,這是能夠最大提升MONO價格的兌換數(shù)量(使圖8 _getNewPrice第527行,分母為1)。另外由于交易池中MONO的總量較低(第3步的操作),攻擊者已經(jīng)通過第1步保證了有足夠的余額進行兌換操作。
截止至兌換結(jié)束時,MONO的價格已經(jīng)被拉升至843,741,636,512.366 vCASH/MONO。攻擊合約中剩余51.92049285389317 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,而不是閃電貸攻擊。