本次攻擊的核⼼在於利⽤ swap 合約中沒有對池中傳⼊和傳出代幣是否相同作檢查,以此利⽤價格更新機制的缺陷,使得攻擊者傳⼊和傳出代幣相同時,價格被二次計算並覆蓋,導致代幣價格不斷被推⾼,並以此代幣換出池中的其他代幣來獲利。
By:九九@慢霧安全團隊
2021 年11 ⽉ 30 ⽇,據慢霧區消息,DeFi 平台MonoX Finance 遭遇攻擊,本次攻擊中約合1820 萬美元的WETH 和1050 萬美元的MATIC 被盜,其他被盜Token 包括WBTC、LINK、GHST、DUCK、MIM 和IMX,損失共計約3100 萬美元。慢霧安全團隊第⼀時間介⼊分析,並將簡要分析結果分享如下。
攻擊核心
本次攻擊的核⼼在於利⽤ swap 合約中沒有對池中傳⼊和傳出代幣是否相同作檢查,以此利⽤價格更新機制的缺陷,使得攻擊者傳⼊和傳出代幣相同時,價格被二次計算並覆蓋,導致代幣價格不斷被推⾼,並以此代幣換出池中的其他代幣來獲利。
相關信息
MonoX 是⼀種新的DeFi 協議,使⽤單⼀代幣設計⽤於流動性池。這是通過將存⼊的代幣與vCASH 穩定幣組合成⼀個虛擬交易對來實現的。其中的單⼀代幣流動性池的第⼀個應⽤是⾃動做市商系統- Monoswap,它在2021 年10 ⽉時推出。
攻擊者地址1:
0xecbe385f78041895c311070f344b55bfaa953258
攻擊者地址2:
0x8f6a86f3ab015f4d03ddb13abb02710e6d7ab31b
攻擊合約1:
0xf079d7911c13369e7fd85607970036d2883afcfd
攻擊合約2:
0x119914de3ae03256fd58b66cd6b8c6a12c70cfb2
攻擊交易1:
https://etherscan.io/tx/0x9f14d093a2349de08f02fc0fb018dadb449351d0cdb7d0738ff69cc6fef5f299
攻擊交易2:
https://polygonscan.com/tx/0x5a03b9c03eedcb9ec6e70c6841eaa4976a732d050a6218969e39483bb3004d5d
攻擊細節
1、首先攻擊者調用Monoswap.swapExactTokenForToken:0.1 個WETH 換出79.986094311542621010 個MONO。
2、接著攻擊者利用漏洞移除池子中其他用戶的流動性,並為添加攻擊合約的流動性以此來獲取最大的利益。
這裡移除流動性處的漏洞在Monoswap.sol 中的471-510 行,移除池中流動性時通過removeLiquidity 函數調用_removeLiquidityHelper 函數,而這兩個函數都未做調用者和傳入的to 參數的身份驗證,所以可直接移除任意用戶在池中的流動性。
分析
- 移除0x7b9aa6 的流動性,把1670.7572297649224 個MONO 和6.862171986812230290 個vCASH 轉出給0x7b9aa6;
- 移除cowrie.eth 的流動性,把152.9745213857155 個MONO 和0.628300423692773565 個vCASH 轉出給cowrie.eth;
- 移除0xab5167 的流動性,把99940.7413658327 個MONO 和410.478879590637971405 個vCASH 轉出給0xab5167;
為攻擊合約1 在MONO 代幣流動池創建流動性。
分析
3、緊接著攻擊者調⽤ 55 次Monoswap.swapExactTokenForToken 以此來不斷堆⾼ MONO 的價格。
分析
這裡攻擊的核心是在Monoswap.sol 中的swapExactTokenForToken 函數,攻擊者傳入MONO 代幣使得tokenIn 和tokenOut 是相同的代幣。
分析
跟到swapIn 函數中:
分析
可以發現在swapIn 函數中,調用了函數getAmountOut 來計算價格。接著跟到getAmountOut 函數中發現是利用了_getNewPrice 函數來計算tokenInPrice 和tokenOutPrice。
分析
分析
跟到_getNewprice 函數中,發現當計算tokenInPrice 時候傳入的txType 參數為TxType.SELL,此時:
分析
分析
當計算tokenOutPrice 時候傳入的txType 參數為TxType.BUY,此時:
分析
如果傳入和傳出為同一種代幣時,價格計算式中的四個變量都相同,所以很容易得出tokenOutPrice 會比tokenInPrice 要大。
由於tokenIn 和tokenOut 是同一個token,swapIn 函數在計算完價格後會再次調用_updateTokenInfo 函數,使得tokenOutPrice 的更新會覆蓋tokenInPrice 的更新,所以導致這個token 的價格上漲。
分析
分析
4、最後攻擊者調用swapTokenForExactToken 函數用MONO 來換出池子中的其他代幣。
分析
swapTokenForExactToken 函數中調用了swapOut 函數,而swapOut 函數中計算價格是調用的getAmountIn 函數。
分析
在該函數中由於tokenInPoolPrice 是取的MONO 代幣在池中的價格,而此價格在之前已被推高,導致tokenInPrice 變大,計算最後的amountIn 變小,用更少的MONO 換出了原來相同數量的WETH、WBTC、MONO、USDC、USDT、 DUCK、MIM、IMX 等池子中的代幣。
分析
5、攻擊者最終把攻擊獲利轉入地址
0x8f6a86f3ab015f4d03ddb13abb02710e6d7ab31b。
以上為以太坊主鏈上的攻擊分析,此外,攻擊者除了在以太坊主鏈上進行攻擊外,還在Polygon 上進行了同樣的攻擊,攻擊手法與以太坊主鏈上相同,此處不做過多重複的分析。
據慢霧AML 統計,MonoX Finance 最終損失約3400 萬美元,包括約2.1K 個WETH、1.9M 個WMATIC、36.1 個WBTC、143.4K 個MONO、8.2M 個USDC、 9.1M 個USDT、1.2K 個LINK、3.1K 個GHST、5.1M 個DUCK、4.1K 個MIM 以及274.9 個IMX。
總結
本次攻擊是利用了swap 合約裡沒有對池中傳入和傳出代幣作檢查,從而利用價格更新機制的問題,由於在swap 合約中會對池中傳入和傳出的代幣的價格調用同一個函數_upTokenInfo 來進行更新,而當傳入和傳出的代幣為同一種代幣時,第二次調用_upTokenInfo 函數時,通過價格計算後的更高的tokenOutPrice 會覆蓋掉價格更低的tokenInPrice,以此來不斷推高池中該代幣的價格,最後可以換出池中其他的所有代幣來獲利離場。
展開全文打開碳鏈價值APP 查看更多精彩資訊