被黑 6.1 億美金的 Poly Network 事件分析與疑難問答

買賣虛擬貨幣

2021 年 08 月 10 日,據慢霧區訊息,跨鏈互操作協議 Poly Network 遭受駭客攻擊,慢霧安全團隊第一時間介入分析,並將分析結果分享如下。

攻擊背景

Poly Network 是由 Neo、Ontology、Switcheo 基金會共同作為創始成員,分佈科技作為技術提供方共同發起的跨鏈組織。

如下圖,透過官方的介紹我們可以清楚的看出 Poly Network 的架構設計:使用者可以在源鏈上發起跨鏈交易,交易確認後由源鏈 Relayer 將區塊頭資訊同步至 Poly Chain,之後由 Poly Chain 將區塊頭資訊同步至目標鏈 Relayer,目標鏈 Relayer 將驗證資訊轉至目標鏈上,隨後在目標鏈進行區塊頭驗證,並執行使用者預期的交易。

以下是本次攻擊涉及的具體地址:

攻擊核心

1、源鏈未對發起的跨鏈操作的資料進行檢查。

2、目標鏈未對解析出的目標呼叫合約以及呼叫引數進行檢查。

3、EthCrossChainData 合約的 owner 為 EthCrossChainManager。

4、 bytes4(keccak256(abi.encodePacked(_method, "(bytes,bytes,uint64)")))

可以被 hash 碰撞。

攻擊細節

Poly Network 會在各個鏈上部署智慧合約以便進行跨鏈互操作(分析將以在以太坊部署的智慧合約為例),其中 EthCrossChainManager 合約用於驗證 Poly Chain 同步來的區塊頭以確認跨鏈資訊的真實。EthCrossChainData 合約用於儲存跨鏈資料,中繼鏈驗證人 (即 Keeper) 的公鑰也儲存在這個合約中。LockProxy 則用於資產管理。

本次攻擊中,攻擊者分兩步來完成這次攻擊,我們接下來進行詳細分析:

首先攻擊者透過在其他鏈呼叫 crossChain 函式構造資料發起跨鏈交易。

我們切入此函式進行分析:

EthCrossChainManager.crossChain

(https://github.com/polynetwork/eth-contracts/blob/master/contracts/core/cross_chain_manager/logic/EthCrossChainManager.sol#L91)

從上圖我們可以清晰的看出,此函式只是用於幫助使用者構造 makeTxParam 並儲存了構造後的雜湊以便後續驗證,其並未對使用者傳入的跨鏈操作引數進行任何限制,因此攻擊者完全可以透過構造任意想構造的資料而讓 Relayer 毫無防備的將其同步至 Poly Chain,透過 Poly Chain 將其同步至以太坊 Relayer。

隨後在以太坊上的 Relayer 透過呼叫 EthCrossChainManager 合約中

的 verifyHeaderAndExecuteTx 函式提交區塊頭資訊來驗證這筆跨鏈資訊的真實性。

我們切入此函式進行分析:

EthCrossChainManager.verifyHeaderAndExecuteTx

(https://github.com/polynetwork/eth-contracts/blob/master/contracts/core/cross_chain_manager/logic/EthCrossChainManager.sol#L127)

透過上圖程式碼我們可以看出其先對區塊頭進行反序列化,以解出所需要驗證的具體資訊。隨後呼叫 getCurEpochConPubKeyBytes 函式從 EthCrossChainData 合約中獲取 Keeper 公鑰,並透過 deserializeKeepers 函式得到 Keeper 地址。

接下來將透過 ECCUtils.verifySig 驗證簽名是否為 Keeper,從以下程式碼中我們可以發現 verifySig 函式中會切出簽名者的 v r s,並透過 ecrecover 介面獲取簽名者地址,然後呼叫 containMAddresses 函式迴圈比較簽名者是否為 Keeper,只要 Keeper 簽名數量符合要求即可透過檢查,數量要求即為 EthCrossChainManager 合約傳入的 n - ( n - 1) / 3)。

簽名驗證後會透過 ECCUtils.merkleProve 進行默克爾根驗證,只要是正常跨鏈操作即可透過此項檢查。隨後會對交易是否重複傳送進行檢查並儲存已驗證後的資料。這裡只需保證不重複提交即可。

最後,也是最關鍵的一步,其將透過內部呼叫 _executeCrossChainTx 函式執行構造的資料。

從上圖我們可以看出 _executeCrossChainTx 函式未對傳入的 _toContract、_method 等引數進行檢查就直接以 _toContract.call 的方式執行交易。

其中透過鏈上資料我們可以看出 EthCrossChainData 合約的 owner 即為 EthCrossChainManager 合約,而先前我們知道中繼鏈驗證人 (即 Keeper) 的公鑰存在 EthCrossChainData 合約中,且此合約存在 putCurEpochConPubKeyBytes 函式可以直接修改 Keeper 公鑰。

經過以上分析,結果已經很明確了,攻擊者只需在其他鏈透過 crossChain 正常發起跨鏈操作的交易,此交易目的是為了呼叫 EthCrossChainData 合約的 putCurEpochConPubKeyBytes 函式以修改 Keeper 角色。隨後透過正常的跨鏈流程,Keeper 會解析使用者請求的目標合約以及呼叫引數,構造出一個新的交易提交到以太坊上。這本質上也只是一筆正常的跨鏈操作,因此可以直接透過 Keeper 檢查與默克爾根檢查。最後成功執行修改 Keeper 的操作。

但我們注意到 putCurEpochStartHeight 函式定義為

function putCurEpochConPubKeyBytes(bytes calldata curEpochPkBytes) external returns (bool);

而 _executeCrossChainTx 函式執行的定義為

abi.encodePacked(bytes4(keccak256(abi.encodePacked(_method, "(bytes,bytes,uint64)")))

我們可以知道這兩個函式的函式簽名在正常情況下傳入的 _method 為 putCurEpochStartHeight 肯定是完全不同的,因此透過 _toContract.call 理論上是無法呼叫到 putCurEpochStartHeight 函式的。但 _method 是攻擊者可以控制的,其完全可以透過列舉各個字元組合以獲得與呼叫 putCurEpochConPubKeyBytes 函式相同的函式簽名,這要求其只需列舉前 4 個位元組符合即可。我們也可以自己嘗試列舉驗證,如下所示:

可以看出前四個位元組與 putCurEpochConPubKeyBytes 函式是一致的

至此我們就已還原出攻擊者的攻擊細節。

透過解析鏈上資料,我們可以發現攻擊者將 Keeper 替換為了

0xA87fB85A93Ca072Cd4e5F0D4f178Bc831Df8a00B。

最後攻擊者只需使用替換後的 Keeper 地址進行簽名即可透過所有檢查執行呼叫 LockProxy 合約將其管理的資產轉出。

攻擊流程

1、攻擊者在源鏈精心構造一筆修改目標鏈 Keeper 的操作。

2、利用官方 Relayer 正常在目標鏈提交資料並執行替換 Keeper 操作。

3、攻擊者透過替換後的 Keeper 地址對其轉出資產的操作進行簽名提交至 EthCrossChainManager 進行驗證。

4、驗證 Keeper 為攻擊者已替換完的地址透過檢查,執行將資產轉移至攻擊者指定地址。

5、獲利走人。

MistTrack 分析過程

慢霧 AML 團隊分析統計,本次攻擊損失共計超 6.1 億美元!

具體如下:

資金流向分析

慢霧 AML 旗下 MistTrack 反洗錢追蹤系統分析發現,攻擊者初始的資金來源是門羅幣(XMR)。

然後在交易所裡換成了 BNB/ETH/MATIC 等幣種並分別提幣到 3 個地址,不久後在 3 條鏈上發動攻擊。

事件梳理

資金情況(截止到北京時間 08 月 11 日 13:00)

BSC 上:

駭客地址 1,駭客將近 1.2 億美元(包括約 3210 萬枚 BUSD 和約 8760 萬枚 USDC)的流動性新增到 Curve 分叉專案 Ellipsis Finance 中,目前仍在做市無異動。

Polygon上:

資金無異動。

Ethereum 上:

1)駭客地址 3,只有一筆轉出 13.37 ETH 到地址0xf8b5c45c6388c9ee12546061786026aaeaa4b682 的交易;

2)駭客在 Curve 上新增了超 9706 萬美元(包括 67 萬枚 DAI 和 9638 萬枚 USDC)的流動性。後又撤銷流動性將 9638 萬枚 USDC 和 67 萬枚 DAI 換成 9694 萬枚 DAI,這筆資金仍停留在地址 3。目前,3343 萬枚 USDT 已被 Tether 凍結。

疑難問答

注:eccm 為 EthCrossChainManager 合約的簡稱,eccd 為 EthCrossChainData 合約的簡稱。

問:為什麼 keeper 能更換成功,合約程式碼沒有進行鑑權嗎?

答:eccd 合約有進行鑑權,僅允許 owner 呼叫 putCurEpochConPubKeyBytes 更改 keeper,因為 eccd 合約的 owner 是 eccm,所以透過 eccm 可以更改 keeper 的值。

問:為什麼能簽名一筆更換 keeper 的交易?

答:因為跨鏈要執行的資料沒有判斷好 toContract,所以可能原先的 keeper 以為是一筆正常的跨鏈交易就簽名了, 但是他是一筆更換 keeper 的交易。

問:為什麼能繞過程式碼 bytes4(keccak256(abi.encodePacked(_method, "(bytes,bytes,uint64)")))的這個限制,然後執行 putCurEpochConPubKeyBytes(bytes) 函式?

答:函式簽名用的是 keccak-256 進行雜湊,然後取前面的 4bytes,這種情況下是較容易被 hash 碰撞的。

問:駭客更換 keeper 的交易如何被舊的 keepers 簽名?

答:keepers 是一個鏈中繼器(Replayer),會對所有正常使用者的跨鏈請求進行簽名。當使用者在BSC上發起跨鏈交易時,keepers 會解析使用者請求的目標合約以及呼叫引數,構造出一個新的交易提交到以太坊上,並在以太坊上用 eccm 合約呼叫使用者交易裡包含的目標合約。駭客替換 keeper 的交易本質上也是一筆正常的跨鏈交易,只不過呼叫的目標合約是 eccd 合約,呼叫的引數是更換 keeper,所以能被正常簽名。

總結

本次攻擊主要在於 EthCrossChainData 合約的 keeper 可由 EthCrossChainManager 合約進行修改,而 EthCrossChainManager 合約的 verifyHeaderAndExecuteTx 函式又可以透過 _executeCrossChainTx 函式執行使用者傳入的資料。因此攻擊者透過此函式傳入精心構造的資料修改了 EthCrossChainData 合約的 keeper 為攻擊者指定的地址,並非網傳的是由於 keeper 私鑰洩漏導致這一事件的發生。

慢霧 AML 旗下 MistTrack 反洗錢追蹤系統將持續監控被盜資金的轉移,拉黑攻擊者控制的所有錢包地址,提醒交易所、錢包注意加強地址監控,避免相關惡意資金流入平臺。此外,特別感謝虎符 Hoo、Poly Network、火幣 Zlabs、鏈聞、WePiggy、TokenPocket 錢包、Bibox、歐科雲鏈等團隊及許多個人夥伴在合規的前提下及時與慢霧安全團隊同步相關攻擊者資訊,為追蹤攻擊者爭取了寶貴的時間。

目前,在多方努力下,駭客開始陸續歸還資金。

免責聲明:

  1. 本文版權歸原作者所有,僅代表作者本人觀點,不代表鏈報觀點或立場。
  2. 如發現文章、圖片等侵權行爲,侵權責任將由作者本人承擔。
  3. 鏈報僅提供相關項目信息,不構成任何投資建議

推荐阅读