2022 年 7 月 2 日
ccryptoo 1 1653041651

Position Exchange 重入漏洞解析 - Amber Group 安全團隊

Amber Group 安全團隊與獨立研究員 Rivaill  3 月上旬發現去中心化加密平台 Position Exchange 合約存在重入漏洞,為此團隊將深入探討此漏洞如何可讓攻擊者為合約建立偽造狀態,並透過零質押 NFT 獲利的手法。
(前情提要:DeFi乾貨 | 深入解析 Dexfolio 的重入漏洞事件 -Amber安全團隊
(背景補充: 全解析 | 不可不知的 3種「Defi重入攻擊」: 基本概念、背後細節、手法 — Amber資安負責人

 

(本文由  Amber Group 安全團隊撰著、提供。)


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

0x00 Position Exchange

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

ccryptoo 1 1653041651 1

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

ccryptoo 1 1653041651 2

ccryptoo 1 1653041652

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

0x01 漏洞

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

ccryptoo 1 1653041652 1

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

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

ccryptoo 1 1653041652 3

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

ccryptoo 1 1653041653

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

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

ccryptoo 1 1653041653 2

ccryptoo 1 1653041654

0x02 漏洞利用

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

ccryptoo 1 1653041654 1

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

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

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

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

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

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

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

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

ccryptoo 1 1653041654 2

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

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

2) 在 NFTReward 合約上竄改狀態;

3) 「歸還」該 NFT

4)收穫獎勵。

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

ccryptoo 1 1653041655

0x03 時間軸和緩解措施

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

完整的時間軸如下圖所示:

2022/03/09 提交

ccryptoo 1 1653041655 12022/03/21 確認

ccryptoo 1 1653041655 2

2022/03/22 修復

https://bscscan.com/tx/0x67875ba082a5a5f7e570ce1f4035dadf0daa0b3cb22e527ac89ef37ce38a4257

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

關於 Amber Group

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

Amber Group官方網站: www.ambergroup.io

WhaleFin官方網站: www.whalefin.com

若有產品相關問題,請聯繫 Amber 客服團隊: [email protected][email protected]

📍