全球區塊鏈監管查詢平台

繁體中文
下載WikiBit

DeFi 乾貨|Position Exchange 重入漏洞解析 - 桑幣筆記Zombit

DeFi 乾貨|Position Exchange 重入漏洞解析 - 桑幣筆記Zombit WikiBit 2022-05-27 11:02

Amber Group 區塊鏈安全團隊和

  Amber Group 區塊鏈安全團隊和獨立研究員 Rivaill 再次發現了一個重入漏洞,並向漏洞懸賞平台 ImmuneFi 提交漏洞報告。由於項目方(Position Exchange)在修復漏洞後就與我們失去聯繫,我們決定在此撰文中公佈詳情。

  0x00 Position Exchange

  去中心化加密平台 Position Exchange 允許用戶使用 POSI 代幣鑄造 NFT,並質押 NFT 以賺取更多的 POSI。 如 HOWTO 文檔中所述,用戶可以鑄造的 NFT 角色共有六種,藉此來獲得隨機的挖礦效率增益。

  舉例來說,用戶支付 50 POSI 鑄造下方這個 Pilot NFT,隨機生成的挖礦效率為 154.06 %,因此他/她獲得 50 x 154.06% = 76.28 POSI 的算力。如果用戶選擇質押該算力,會因此獲得額外的 NFT 礦池獎勵分成。

  為了實現上述的 NFT 質押機制,後端的 NFTReward 智能合約實現了 stake() 和 unstake() 函數,讓用戶轉入/轉出基於 ERC-721 的 NFT。 然而,由於 ERC-721 標準實現中內建的回調機制,NFTReward 的運作邏輯產生了問題,導致攻擊者能夠多次重入該智能合約而獲利。

  0x01 漏洞

  前面提的 unstake () 函數,他的基本功能是將某個 ERC721 代幣取回給調用者。 但是如下圖所示,我們注意到第 283 行中使用的 safeTransferFrom() 函數被嵌入了一個特殊的回調機制,攻擊者可利用此漏洞攔截 unstake() 調用並插入惡意的程式碼。 此外,第 283 行之後有兩行改變狀態的語句(第 285-286 行),這違反了智能合約基本的 Checks-Effects-Interactions 原則。

  具體來說,在 OpenZeppelin 的 ERC721 實現中,在傳輸 ERC721 代幣時,若接收地址是合約時會調用 onERC721Received() 外部函數(第 395 行),這是此漏洞能被利用的關鍵。

  透過這種方式,攻擊者可以藉由任何的外部函數進入 NFTReward 合約竄改相關數據。 如何做到?我們注意到下面兩行是 unstake() 函數調用 safeTransferFrom() 之後唯二更新過狀態的兩個地方:

  如下方的程式碼片段所示,這些狀態是在 stake() 函數中被設置的。

  我們認為這個的設計的初衷是先暫存 gegoId 對應 NFT 的餘額(_stakeBalances[geogoId])和權重(_stakeWeightes[geogoId])。隨後,如果用戶選擇 unstake() 該 NFT,暫存的值將用於更新與該用戶有關的全域變數 _weightBalances 和 _degoBalances(下面的第 276 和 280 行)。

  因此,如果暫存的餘額和權重在用於更新全域狀態之前被竄改,意味著 _weightBalances 和 _degoBalances 可能也會被篡改。此外,我們注意到 _weightBalances 值會被用於計算獎勵,這意味著可以利用被篡改的狀態來獲取額外的獎勵,甚至可能耗盡獎勵池。

  0x02 漏洞利用

  下圖展示了篡改 _weightBalances 的六個步驟:

  •   攻擊者創建一個惡意合約 Exp,並從 Exp 呼叫 stake() 函數。如上圖所示,為了成功做到後續的劫持操作,此惡意合約 Exp 實現了一個外部函數 onERC721Received();

  •   攻擊者從 Exp 合約觸發了 unstake() 函數;

  •   透過 safeTransferFrom(),Exp 合約成功劫持了 unstake() 函數的調用;

  •   從 Exp 合約重新進入 stake() 函數,使其之後能夠調用第二次 unstake() 函數;

  •   當 Exp 合約返回到被劫持的 unstake() 調用時,第四步驟設置的 _stakeWeightes 會被重置設為 0;

  •   攻擊者發出第二個 unstake() 調用並使用歸零的 _stakeWeightes 篡改 _weightBalances 變數。n

  •   透過上述步驟,攻擊者可以只用一個 NFT 持續累積 _weightBalances,並且可以在沒有質押任何 NFT 的情況下,透過 NFTReward 合約中的 harvest() 函數不斷獲取獎勵。

      下方惡意合約的程式碼說明了我們如何模擬攻擊。 在 trigger() 函數中,我們執行了多次 [stake(), unstake(), unstake()] 調用。 每當 unstake() 將 NFT 轉移回惡意合約時,onERC721Received() 函數就會劫持 unstake() 並在 flag 為 true 時發出另一個 stake() 調用,這就是重入攻擊竄改狀態的流程。

      下方的 eth-brownie 截圖證明了我們的猜想。 具體來說,我們:

    •   通過 eth-brownie 的模擬,「借用」了 NFT #1183410;

    •   在 NFTReward 合約上竄改狀態;

    •   「歸還」該 NFT;

    •   收穫獎勵。

    •   最後,我們的駭客在沒有質押任何 NFT 的情況下以 4.93 POSI 獲利出場,這也間接證明了攻擊者可以創建多個合約,為每個合約偽造狀態,並透過來回轉移同一個 NFT 來獲得獎勵。

      0x03 時間軸和緩解措施

        該漏洞於 3 月 9 日通過 ImmuneFi 提交;3 月 21 日,Position Exchange 團隊確認了該問題,並將其評為高危漏洞; 3 月 22 日,我們觀察到一個新的 NFTReward 合約被部署上鏈,此合約加入了 reentrancy guard。 但自那以後,我方仍未能收到 Position Exchange 團隊的任何回覆。

        除了 Position Exchange,我們還聯繫了 Dego FinanceSmarty Pay。兩方都部署了類似的 NFTReward 合約,且其中含有類似的漏洞。Dego Finance 團隊的處理方式是透過將 DEGO 代幣轉移到新代幣。 與此同時,Smarty Pay 團隊升級了他們的 NFTReward 合約,並將所有的用戶狀態遷移到了新版本。 據我們了解,這三個具有漏洞的項目,在我們披露細節之前皆沒有被真的攻擊。

      關於 Amber Group

        成立於 2017 年,業務遍及亞洲及歐美各大主要城市,現為 1,000 多家知名大型機構客戶提供加密金融服務,在 100 多個電子交易所中累計交易總額已超過 1 兆美元,資產管理規模超過 50 億美元,幫助客戶管理各種加密資產的風險,提供靈活化的投資、最大化的回報來優化長期價值。

免責聲明:

本文觀點僅代表作者個人觀點,不構成本平台的投資建議,本平台不對文章信息準確性、完整性和及時性作出任何保證,亦不對因使用或信賴文章信息引發的任何損失承擔責任

  • 通證換算
  • 匯率換算
  • 購匯計算
/
當前匯率
可兌換金額

0.00