乙太坊合併後的重放攻擊:Omni跨鏈橋被攻擊事件分析

一、事件描述

2022年9月18日,乙太坊合併完成後,PoW鏈遭到PoS鏈上交易的重放攻擊,根本原因是橋接器未正確讀取並驗證區塊鏈的chainid。攻擊者首先通過Gnosis鏈的Omni跨鏈橋轉移了200 WETH,然後在PoW鏈上重放了相同的消息,獲得了額外的200 ETHW。

SharkTeam對此事件進行了技術分析,並總結了安全防範手段,希望後續項目可以引以為戒,共築區塊鏈行業的安全防線。

二、事件分析

該事件涉及兩個不同鏈的交易hash以及攻擊者地址,分別如下:

(1)PoS鏈交易hash:0xbddb0cc8bc9949321e1748f03503ed1a20dd618fbf0a51dc5734c975b1f8bdf5

(2)PoW鏈交易hash:0x9c072551861ce384203516f4d705176a2d2e262d5b571d853467425f1a861fb4

(3)攻擊者地址:0x82FaEd2dA812D2E5CCed3C12b3baeB1a522DC677

首先,我們對比發現兩筆交易訪問的合約相同,並且inputdata完全相同,即調用了同一個合約的同一個函數並且參數相同,根據相同的方法簽名ID ; 0x23caab49可知,駭客調用safeExecuteSignaturesWithAutoGasLimit函數。

囙此,攻擊者通過Omni Bridge轉移200WETH,然後在PoW鏈上重放了相同的Inputdata,獲得了額外的200 ETHW。

此時,我們對這裡的重放操作抱有懷疑態度。 因為,乙太坊網絡在硬分叉之前强行執行EIP-155,這就說明ETH PoS鏈上交易不能在PoW鏈上重複交易。 在正常的交易中,我們通過nonce來進行排序交易,避免重複交易。 在跨鏈中,我們會根據chianid進行識別鏈的類型,比如乙太坊主網的chainid是1,ETHW主網的chainid是10001。

對此,我們分析了Omni Bridge相應的源碼。 我們查看一下Omni Bridge驗證chainid的邏輯,發現chainid的來源於unitStorage中存儲的值,而不是通過操作碼CHAINID(0x46)直接讀取的鏈上chainid。

unitStorage是合約EternalStorage中的狀態變數,sourceChainId()函數所在的合約BasicAMB繼承了BasicBridge和VersionableAMB。 其中,BasicBridge陸續繼承了合約EternalStorage。 這裡保存的chainid是預先存儲好的,如果發生區塊鏈的硬分叉而chainid又沒有重新設定或者chainid人為設定有誤,從合約層面上來說,由於不是通過操作碼獲取的chainid,不會正確驗證跨鏈消息的實際chainid。 這樣的漏洞,容易被攻擊者利用。

問題分析總結:主要是Omni使用的solidity版本是0.4.24,採用的是手動存儲和更新chainid的管道,並未通過EIP-1344中規定的CHAINID(0x46)操作碼進行實際chainid獲取。

三、安全建議

引發本次安全事件的原因是在PoW陞級PoS過程中,Omni Bridge對chainid未及時處理。 導致過舊的solidity版本中,存在歷史遺留問題。 建議在後續項目反覆運算中,及時應對新問題,採取必要的程式碼優化措施。 雖然Gnosis鏈上Omni Bridge有每日最大轉移代幣數量限制250個WETH,但是依舊要保持警惕,以防止積少成多,造成更大的損失。