慢霧認為,攻擊主要在於EthCrossChainData 合約的keeper 被修改,而非私鑰洩漏導致。目前,黑客已開始陸續歸還資金。
撰文:慢霧安全團隊
2021 年08 月10 日,據慢霧區消息,跨鏈互操作協議Poly Network 遭受黑客攻擊,慢霧安全團隊第一時間介入分析,並將分析結果分享如下。
攻擊背景
Poly Network 是由Neo、Ontology、Switcheo 基金會共同作為創始成員,分佈科技作為技術提供方共同發起的跨鏈組織。
如下圖,通過官方的介紹我們可以清楚的看出Poly Network 的架構設計:用戶可以在源鏈上發起跨鏈交易,交易確認後由源鏈Relayer 將區塊頭信息同步至Poly Chain,之後由Poly Chain 將區塊頭信息同步至目標鏈Relayer,目標鏈Relayer 將驗證信息轉至目標鏈上,隨後在目標鏈進行區塊頭驗證,並執行用戶預期的交易。
以下是本次攻擊涉及的具體地址:
攻擊核心
- 源鏈未對發起的跨鏈操作的數據進行檢查。
- 目標鏈未對解析出的目標調用合約以及調用參數進行檢查。
- EthCrossChainData 合約的owner 為EthCrossChainManager。
- bytes4(keccak256(abi.encodePacked(_method, “(bytes,bytes,uint64)”))) 可以被hash 碰撞。
攻擊細節
Poly Network 會在各個鏈上部署智能合約以便進行跨鏈互操作(分析將以在以太坊部署的智能合約為例),其中EthCrossChainManager 合約用於驗證Poly Chain 同步來的區塊頭以確認跨鏈信息的真實。 EthCrossChainData 合約用於存儲跨鏈數據,中繼鏈驗證人(即Keeper) 的公鑰也存儲在這個合約中。 LockProxy 則用於資產管理。
本次攻擊中,攻擊者分兩步來完成這次攻擊,我們接下來進行詳細分析:
首先攻擊者通過在其他鏈調用crossChain 函數構造數據發起跨鏈交易。
我們切入此函數進行分析 :
EthCrossChainManager.crossChain
從上圖我們可以清晰的看出,此函數只是用於幫助用戶構造makeTxParam 並存儲了構造後的哈希以便後續驗證,其並未對用戶傳入的跨鏈操作參數進行任何限制,因此攻擊者完全可以通過構造任意想構造的數據而讓Relayer 毫無防備的將其同步至Poly Chain,通過Poly Chain 將其同步至以太坊Relayer。
隨後在以太坊上的Relayer 通過調用EthCrossChainManager 合約中
的verifyHeaderAndExecuteTx 函數提交區塊頭信息來驗證這筆跨鏈信息的真實性。
我們切入此函數進行分析:
EthCrossChainManager.verifyHeaderAndExecuteTx
通過上圖代碼我們可以看出其先對區塊頭進行反序列化,以解出所需要驗證的具體信息。隨後調用getCurEpochConPubKeyBytes 函數從EthCrossChainData 合約中獲取Keeper 公鑰,並通過deserializeKeepers 函數得到Keeper 地址。
接下來將通過ECCUtils.verifySig 驗證簽名是否為Keeper,從以下代碼中我們可以發現verifySig 函數中會切出簽名者的vrs,並通過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 合約將其管理的資產轉出。
攻擊流程
-
攻擊者在源鏈精心構造一筆修改目標鏈Keeper 的操作。
-
利用官方Relayer 正常在目標鏈提交數據並執行替換Keeper 操作。
-
攻擊者通過替換後的Keeper 地址對其轉出資產的操作進行簽名提交至EthCrossChainManager 進行驗證。
-
驗證Keeper 為攻擊者已替換完的地址通過檢查,執行將資產轉移至攻擊者指定地址。
-
獲利走人。
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、歐科雲鍊等團隊及許多個人夥伴在合規的前提下及時與慢霧安全團隊同步相關攻擊者信息,為追踪攻擊者爭取了寶貴的時間。
目前,在多方努力下,黑客開始陸續歸還資金。
來源鏈接:mp.weixin.qq.com