原文作者:九九,慢霧安全團隊
2022 年6 月27 日,據慢霧區消息,XCarnival 項目被曝出嚴重漏洞遭黑客攻擊並盜走3,087 個ETH(約380 萬美元)。 XCarnival 是一個ETH 鏈上的NFT 借貸項目,目前項目團隊正在修復漏洞並承諾會對受影響的用戶提供解決方案。慢霧安全團隊第一時間介入分析,並將結果分享如下:
相關信息
核心合約地址
P2Controller:
0x34ca24ddcdaf00105a3bf10ba5aae67953178b85
XNFT:
0x39360AC1239a0b98Cb8076d4135d0F72B7fd9909
xToken:
0x5417da20aC8157Dd5c07230Cfc2b226fDCFc5663
攻擊者EOA 地址
0xb7cbb4d43f1e08327a90b32a8417688c9d0b800a
攻擊合約地址
0xf70F691D30ce23786cfb3a1522CFD76D159AcA8d
0x234e4B5FeC50646D1D4868331F29368fa9286238
0x7B5A2F7cd1cc4eEf1a75d473e1210509C55265d8
0xc45876C90530cF0EE936c93FDc8991534F8A6962
漏洞核心點分析
1.攻擊者通過XNFT 合約中的pledgeAndBorrow 函數來進行抵押NFT 並藉出xToken。
在pledgeInternal 函數中轉入NFT 並生成訂單:
2. 接著調用withdrawNFT 函數提取出質押的NFT,其中首先判斷該訂單是否被清算狀態,如果不是則判斷該訂單的狀態是否為NFT 還未被提取且借款金額為0(無負債),如果通過即可提取抵押的NFT。
3. 以上為攻擊前生成訂單的準備操作,接著攻擊者開始利用生成的訂單直接調用xToken 合約中的borrow 函數進行借款。
在borrowInternal 函數中,會外部調用controller 合約中的borrowAllowed 函數來判斷是否可以藉款。
可以看到在borrowAllowed 函數會調用orderAllowed 函數進行訂單相關信息的判斷,但是在這兩個函數中均沒有進行_order.isWithdraw 狀態的判斷。因此攻擊者可以利用之前生成的訂單(訂單裡的抵押的NFT 已經被提走)來調用XToken 的borrow 函數來借款,而因為抵押的NFT 在之前已經被提出,故攻擊者可以不用還款來實現獲利。
攻擊交易分析
此處僅展示其中一筆攻擊交易的細節,其餘攻擊交易的手法均一致,不再贅述。
攻擊前準備——生成訂單的交易:
0x61a6a8936afab47a3f2750e1ea40ac63430a01dd4f53a933e1c25e737dd32b2f
1. 首先攻擊者將NFT 轉入攻擊合約並進行授權,接著調用xNFT 合約中的pledgeAndBorrow 函數在進行抵押NFT 生成訂單並藉款的操作,此處需要注意一點是該函數可以控制傳入的xToken,攻擊者傳入了自己構造的xToken 合約地址,並且讓借款數量為0,目的是為了滿足後續能成功提出NFT 時的不被清算且負債為0 的條件。
2. 攻擊者緊接著調用withdrawNFT 函數來進行提取抵押的NFT:
正式攻擊交易:
0x51cbfd46f21afb44da4fa971f220bd28a14530e1d5da5009cfbdfee012e57e35
攻擊者調用xToken 合約的borrow 函數,傳入之前生成的訂單的orderID,重複了該操作22 次(orderID: 45 – 66),而因為NFT 在準備階段已經提走,估計無需還款以此來獲利。
總結
本次漏洞的核心在於借款的時候,沒有進行訂單中NFT 是否被提走的狀態的判斷,導致攻擊者可以在把NFT 提走之後再利用之前生成的訂單來借款而無需還款,以此來獲利。針對此類漏洞,慢霧安全團隊建議在進行借款操作時應做好訂單狀態中是否已經提走抵押品的判斷,避免再次出現此類問題。