02月15日,bZx 團隊在官方電報群上發出公告,稱有駭客對「bZx 借貸協議」進行了漏洞攻擊,且已暫停除了借貸外的其他功能;對於攻擊細節,bZx官方並沒有進行詳細披露。現在,就由據動區專欄作家機構,區塊鏈資安公司《PeckShield》帶您還原這場轟動全球 Defi 社群,十幾秒即套利 35 萬美元(約 1000 萬台幣)的傳奇攻擊事件始末。
PeckShield 安全人員主動跟進bZx 攻擊事件,發現這起事件是針對DeFi 項目間,共享可組合流動性的設計進行攻擊。
特別在有槓桿交易及借貸功能的DeFi 項目裡,該問題會更容易被利用。
延伸閱讀:什麼是「閃電貸 Flash Loan」?十幾秒內從”借貸協議 bZx”狠賺 35 萬美元的 DeFi 策略
延伸閱讀:有哪些值得投資的 Defi 幣?從傳統金融「市盈率PE Ratio」分析:SNX 3倍 MKR 80倍…
漏洞的攻擊細節如下:
此攻擊事件發生在台北時間2020-02-15 09:38:57(區塊高度#9484688),攻擊者的transaction資訊可以在 etherscan 上查到,此攻擊過程可以分為以下五個步驟:
延伸閱讀:幣安(Binance)遭駭的 7,000 顆比特幣去哪了?還原駭客組織攻擊後的「銷贓過程」
延伸閱讀:面對 3.4 億美元的駭客洗劫風險,MakerDAO 開啟社群投票是否延遲「治理安全模塊(GSM)」
第一步:閃貸獲取可用資金
攻擊者通過在部署的合約中調用了dYdX閃貸功能藉入了10,000個ETH,這部分是已知的dYdX的基本借貸功能,我們不做進一步解釋。
當第一步操作過後,如下表中攻擊者資產,此時並沒有收益:
第二步:囤積 WBTC 現貨
通過第一步閃貸獲得ETH後,攻擊者將其中的5,500 ETH存入Compound作為抵押品,貸出112 WBTC。
這也是正常的Compound借貸操作,貸出的WBTC將在第四步中被拋售。
延伸閱讀:ETHFANS 專欄|DeFi 中的流動性和銀行擠兌風險,以 Compound 為例
延伸閱讀:去中心化金融入門|五分鐘看懂借貸機制,什麼是「DeFi 銀行」Compound?
在此步驟操作後,我們可以看到關於攻擊者控制的資產發生了改變,但此時仍然沒有獲益:
第三步:槓桿拉盤 WBTC 價格
利用bZx的槓桿交易功能,做空ETH購入大量WBTC。
具體步驟是:攻擊者存入1,300 ETH並調用bZx槓桿交易功能,即接口mintWithEther(),在內部會繼續調用接口marginTradeFromDeposit()。
接下來,攻擊者將從bZx 5倍槓桿獲得的5,637.62個ETH,通過 KyberSwap兌換成51.345576 WBTC。請注意,此處做空ETH是藉來的5倍。
本次交易導致將WETH / WBTC的兌換率提高到109.8 ,大約是正常兌換率(~38.5 WETH / WBTC)的3倍。
為了完成此交易,KyberSwap 基本上會查詢其儲備金並找到最優惠的匯率,最終只有Uniswap 能提供這樣的流通性,因此這個交易從本質上推動了Uniswap 中WBTC 價格上漲了3倍。
延伸閱讀:以太坊上的「WBTC」代幣,會不會比起「比特幣閃電網路」更蓬勃發展?
延伸閱讀:新手介紹|一文讀懂 Defi 熱門項目「Uniswap」,什麼是以太坊上的「代幣交換協議」
應該注意的是,這步操作在合約內部實現有個安全檢查邏輯,但是實際上在交易之後並沒有驗證鎖倉值。
也就是說,當攻擊發生時,此檢查沒有啟用,我們在後面會有一節詳細介紹此合約中的問題。
在這一步之後,我們注意到關於駭客控制的資產有以下改變。不過,在這一步之後仍然沒有獲利。
第四步:拋售WBTC 現貨
在Uniswap中WBTC價格飆升後(價格為61.4 WETH / WBTC),攻擊者將第二步中通過Compound借的112 WBTC全部賣給Uniswap並返還了相應的WETH。
這次交易攻擊者共計獲得6,871.41個ETH的淨額作為回報,在這一步之後,可以看到攻擊者已經獲得不少利潤。
延伸閱讀:外媒訪談揭露:Vitalik 說服「以太坊基金會」在最高點售出 70,000 ETH 套現近 1 億美元
延伸閱讀:大型資金盤 PlusToken 已轉走近 3 萬顆比特幣,交易紀錄留下一句:「抱歉,我們先閃啦」
第五步:閃貸還款 Flash Loan
攻擊者從拋售的112 WBTC 中獲得的6,871.41 個ETH,將閃貸的10,000個ETH償還給dYdX,從而完成閃貸還款。
在這一步之後,我們重新計算了以下資產詳情。結果顯示,攻擊者通過此次攻擊獲得71 ETH,加上這兩個鎖倉:Compound(+5,500weth/-112WBTC)和bZx(-4,337WETH/+51WBTC)。bZx鎖倉處於違約狀態,Compound的鎖倉是有利可圖的。
顯然,在攻擊之後,攻擊者就開始償還Compoud債務(112BTC)以贖回抵押的5,500個WETH。由於bZx鎖倉已經處於違約狀態,攻擊者也不再感興趣了。
延伸閱讀:幣託推出「債權」認購平台BitoDebt,首期USDT產品利率8.5%並附帶「附買回條款」
延伸閱讀:台灣「借貸投資服務」BinFi 今日上線!重新定義 DeFi 驅動投資,改良現有 DeFi 的新產品
參考1WBTC=38.5WETH(1WETH=0.025BTC)的平均市場價格,若攻擊者以市場價格購入112 WBTC花費約需4,300個ETH。
此112 WBTC用以清償Compond債務並取回抵押品5,500 ETH,則最終攻擊者總共獲利為71 WETH +5,500 WETH -4,300 ETH=1,271 ETH,合計大約$355,880(當前ETH價格$280)。
硬核解析:bZx 可規避風險程式碼邏輯缺陷
通過前面攻擊者在合約中實現的步驟可以看出,問題的核心原因是在第三步調用marginTradeFromDeposit()通過借貸的1,300 ETH,加5倍槓桿來實現做空ETH/WBTC交易的。
於是我們進一步審查合約程式碼,發現這是一個「可避免的套利機會」,但因為程式碼存在的邏輯錯誤造成可用於規避風險的程式碼邏輯沒有生效。
具體程式碼追踪如下:
首先是marginTradeFromDeposit( ) 調用_borrowTokenAndUse( ),此處由於是以存入的資產作槓桿交易,第四個參數為true(第840行)。
在_borrowTokenAndUse( ) 裡,當amountIsADeposit 為true 時,調用_getBorrowAmountAndRate( ) 並且將borrowAmount 存入sentAmounts[1] (第1,348行)。
在1,355 行,sentAmounts[6] 被設置為sentAmounts[1] 並且於第1,370行調用_borrowTokenAndUseFinal( )
經由IBZx interface 進入bZxContract 的takeOrderFromiToken( ) 函數。
bZxContract屬於另一個合約iTokens_loanOpeningFunctions 於是我們我們繼續分析合約程式碼,在函數中發現有一個關鍵的邏輯判斷:
在第148行,bZx事實上嘗試利用oracle合約的shouldLiquidate( )檢查這個槓桿交易的倉位是否健康。然而,因為第一個條件(第146~147行)已經為true,則繼續執行,而忽略了shouldLiquidate()的邏輯判斷。
事實上,在合約BZxOracle 的shouldLiquidate( )中實現了對getCurrentMarginAmount( ) <= loanOrder.maintenanceMarginAmount判斷,如果執行到shouldLiquidate( )就可以有效避免這個攻擊的發生。
如前所述,這是一次很有意思的攻擊,它結合了各種有趣的特性,如貸款、槓桿交易和拉高價格等。之所以可能發生這種攻擊,是因為當前項目共享可組合流動性的設計。
特別是,5倍槓桿交易允許用戶以相對較低的成本借入大量代幣,加上DeFi項目間共享的流動性,導致交易價格更容易被操控。
?相關報導?
最大資金盤 PlusToken 再轉移12,422比特幣(價值38億),恐趁 BTC 飆漲破萬點時銷贓
澳本聰威脅:「我可以關掉比特幣網路」—— 真的做得到嗎?
有哪些值得投資的 Defi 幣?從傳統金融「市盈率PE Ratio」分析:SNX 3倍 MKR 80倍…
《BlockTempo動區動趨》讓「 Telegram 動區大家庭 」再次強大!!~立即加入獲得第一手區塊鏈、加密貨幣新聞報導!