來源:CertiK
上周,由CertiK團隊發布的《Cosmos生態安全指南》在Web3媒體Meta Era首發,並得到衆多媒體轉發,獲得了Web3社區的廣泛關注。
作爲全球最大,最爲知名的區塊鏈生態之一,Cosmos專注於提升區塊鏈互操作性,實現不同區塊鏈之間的高效互通。包括Celestia、dYdX v4在內的一系列頭部項目都基於Cosmos SDK和IBC協議進行搭建。
隨着Cosmos开發組件受到更多开發者青睞,Cosmos生態的安全問題也勢必會帶來更廣泛的影響。例如,此前Cosmos SDK的Dragonfruit漏洞就影響了多個主流公鏈的正常運行。由於Cosmos生態系統基礎組件的分散性,开發者需要根據不同的功能需求使用或者擴展不同的組件,導致Cosmos生態中的安全問題也存在分散、多樣的特點。一份幫助开發者結構性了解Cosmos生態安全現狀與應對方案的研究,也就顯得十分必要。
CertiK團隊獨家發布的《Cosmos生態安全指南》通過讀者友好的分類細致剖析了Cosmos生態不同組件的安全場景。此報告不僅包括Cosmos生態以往重大安全漏洞的分析,還將一些常見的安全漏洞根據起因,效果,代碼位置等分類,最大程度地爲Cosmos生態开發者提供安全指引,並爲安全審計人員提供學習和審計Cosmos安全問題的索引資料。
一直以來,CertiK團隊都在通過持續的研究和挖掘,協助提升Cosmos與整個Web3的生態安全。我們將定期爲大家帶來各類項目安全報告和技術研究,歡迎持續關注!如有任何疑問,可隨時與我們取得聯系。
以下是《Cosmos生態安全指南》全文。
《Cosmos 生態安全指南》
概況
Cosmos是一款开源、开放、高度可擴展的區塊鏈跨鏈網絡,也是全球最爲知名的區塊鏈生態之一。Cosmos是一個由CometBFT(原Tendermint團隊)推出的支持跨鏈交互的異構網絡,由多條獨立、並行的區塊鏈組成去中心化網絡,其愿景是打破信息的孤島效應,實現不同區塊鏈之間的互操作性。在當前多鏈時代,實現跨鏈交互已經成爲區塊鏈行業的迫切需求。
Cosmos提供了一種高效的跨鏈模式,特別適用於專注特定垂直領域的公鏈。通過提供模塊化的區塊鏈基礎設施,Cosmos爲各應用开發者提供了便利,使其能夠選擇並使用符合其需求的公鏈。
Cosmos生態系統中的應用程序和協議採用IBC(區塊鏈間通信協議)進行連接,實現了各個獨立區塊鏈之間的跨鏈交互,使資產和數據能夠自由流通。Cosmos的愿景是建立一個區塊鏈互聯網,爲大量自主、易於开發的區塊鏈提供擴展和交互的可能性。
長期以來,CertiK對Cosmos生態環境保持了充分的關注和研究。我們在Cosmos生態安全問題上積累了充足的經驗,在本研究報告中,將介紹我們對Cosmos生態系統安全的探索和研究成果,主要將重點集中在Cosmos SDK安全、IBC協議安全、CometBFT安全和CosmWasm安全四個方向,討論的對象目標會從Cosmos基礎組件延伸到Cosmos基礎鏈或應用鏈,通過對類似問題的分析和擴展,以自下而上的方式向讀者展現Cosmos生態中關於鏈自身涉及到的安全要點。
由於Cosmos生態的復雜多樣性,存在的安全問題也具備多樣性的特徵,因此這份研究報告並沒有將所有的安全漏洞類型都涵蓋其中,僅探討更具有典型特徵且對Cosmos生態鏈存在更大危害性的漏洞。如果想要了解更多關於其他安全問題的詳情,歡迎聯系CertiK安全工程師交流探討。
背景
CometBFT:跨鏈可擴展性的基石
CometBFT是一項創新的共識算法,包括底層共識引擎(CometBFT Core)和通用應用程序區塊鏈接口(ABCI)兩個主要組件。其共識算法採用了PBFT+Bonded PoS混合共識,確保節點同步記錄交易。作爲Interchain可擴展性的核心組成部分,CometBFT通過驗證者共識,維護Interchain生態系統的安全性、去中心化和完整性。
Cosmos SDK:模塊化和新功能
Cosmos SDK是一個幫助开發者加速开發進程的工具包,提供了模塊化和可插拔的特性,利用Cosmos SDK,开發者可以基於CometBFT共識算法構建自己的區塊鏈或功能組件,實現便捷开發並縮短开發周期。目前已在許多區塊鏈項目中得到採用,如Cronos、Kava和最近推出的dYdX V4。未來的發展計劃將專注於模塊化和引入新功能,使开發人員能夠創建更復雜、模塊化的應用程序,培育更廣泛、更強大的生態系統。
IBC協議:增強互操作性和可擴展性
IBC協議(區塊鏈間通信協議)能夠在區塊鏈之間實現安全、去中心化且無需許可的數據傳輸。由於Cosmos是由多條獨立並行的區塊鏈組成的去中心化網絡且利用中繼技術實現不同區塊鏈之間的跨鏈,因此IBC可以說是整個項目最核心的部分。Interchain基金會目前重點關注兩個主題:可擴展性和可用性。通過提高IBC的可擴展性和互操作性,Cosmos將進一步增強其生態系統的容量,從而實現區塊鏈、應用程序和智能合約之間的無縫交互。
CosmWasm:解鎖去中心化、無許可部署
CosmWasm(Cosmos WebAssembly)是一個基於WebAssembly的智能合約框架,專爲Cosmos生態系統設計。它使开發人員能夠在沒有許可要求的情況下部署去中心化應用程序,同時還允許區塊鏈开發人員將其產品开發周期與區塊鏈开發分开,從而降低驗證器升級的成本。除此之外它還具有模塊化架構,Cosmos SDK集成,跨鏈通信等特性。
截止目前,Cosmos SDK,IBC協議相對成熟,且在目前的Cosmos生態系統中使用最爲廣泛。
從鏈开發者的角度考慮,目前Cosmos上的生態鏈所需要大部分自定義化的功能都可以依賴Cosmos SDK來完成,而爲了實現跨鏈操作過程中一些特殊操作或是出於優化性能等目的,鏈开發者會對各自IBC模塊實現定制化,除此之外,也有少部分的鏈會對CometBFT Core等底層引擎做修改定制化,因篇幅限制暫時不在本研究報告中展开,本研究報告將重點剖析Cosmos SDK和IBC協議這兩者的技術要點和安全問題。
Cosmos SDK安全指南
Cosmos SDK是一個強大而靈活的框架,用於構建區塊鏈應用程序和去中心化協議。它由Interchain基金會开發,是Cosmos網絡的核心組件,Cosmos網絡是互連區塊鏈的去中心化網絡。
Cosmos SDK旨在簡化自定義區塊鏈應用程序的开發,並實現不同區塊鏈之間的無縫互操作性。Cosmos SDK主要有以下特點:模塊化架構、可定制性、基於CometBFT、實現IBC對應接口、开發者友好。Cosmos SDK通過利用CometBFT Core底層共識引擎確保強大的安全性,保護網絡免受惡意攻擊,爲用戶的資產和數據提供保護。此外,其模塊化性使用戶能夠輕松設計定制模塊。盡管有這些優點,但當开發人員使用Cosmos SDK實現自己的應用程序時,仍然可能存在安全漏洞。
從安全審計角度來講,我們需要對審計目標做到面面俱到,充分考慮到各個角度的安全隱患問題,但從安全研究角度來講,我們更需要去關注能夠造成重大影響的安全漏洞,在更短的時間內盡可能的避免最大安全隱患,爲集成服務方提供更有效的幫助。從這個角度考慮,對一些危險程度高、影響範圍大的漏洞做出分類,並分析出其漏洞模型是非常必要且有價值的事情。
在貫穿整個Cosmos生態的ABCI接口中,我們重點關注BeginBlock、EndBlock、CheckTx、DeliverTx這四個接口,前兩者直接涉及到單個區塊的執行邏輯,而後兩者涉及到對sdk.Msg(Cosmos生態中傳輸消息的基礎數據結構)的具體處理。
由於Cosmos生態上各種應用鏈的實現邏輯都可按照類似Cosmos SDK裏的模塊和樣例,因此在分析理解下文的安全漏洞時,需要對Cosmos SDK的模塊運行流程有個基本概念。
在Cosmos生態裏,交易最初在用戶代理中被創建,然後會被籤名並廣播到區塊鏈內的節點。節點利用CheckTx方法來驗證各種交易細節,如籤名、發件人的余額、交易序列和提供的燃料等。如果交易通過驗證,它將被添加到內存池,等待被包含在一個區塊中。另外,如果交易未通過驗證,將向用戶發送錯誤消息,導致交易被拒絕。在區塊執行期間,會對交易進行進一步檢查,這是通過DeliverTx方法完成的,以確保一致性和確定性。
在Cosmos SDK中,交易的生命周期可以簡要描述爲如下流程:
1.交易創建:交易是在客戶端使用各種工具、CLI或在前端創建的。
2.添加到內存池:交易被添加到內存池,其中節點發送一個ABCI消息-CheckTx到應用層,以檢查有效性並接收結果abci.ResponseCheckTx。在CheckTx中,交易從字節格式解碼爲Tx格式,然後在Tx的每個sdk.Msg上調用ValidateBasic()進行初步的無狀態有效性檢查。如果應用程序存在對應的anteHandler,則會先執行它的內部邏輯,然後調用runTx函數,最終會調用到RunMsgs()函數來處理sdk.Msg的具體內容。如果CheckTx成功,消息將添加至本地內存池作爲下一個區塊的候選,並將通過P2P廣播到對等Peer節點。
3. 包含在一個提議區塊中:每一輪开始時,提議者創建一個包含最新交易的區塊,最後由全節點負責共識的驗證者,同意接受該區塊或者投票一個空區塊。
4. 狀態更改:DeliverTx被調用來迭代區塊中的交易,類似於CheckTx,但它在Deliver模式下調用runTx,並執行狀態的變更。MsgServiceRouter被調用來路由交易中的不同消息到不同的模塊,然後執行Msg Server中的每個相應消息。之後,在執行消息後運行檢查,如果有任何失敗,將還原狀態。在執行過程中,使用Gas計量器來跟蹤使用了多少燃料(gas)。如果發生任何燃料錯誤(例如,燃料不足),則與執行失敗後的後果相同,狀態更改將被還原。
5. 提交區塊:當節點接收到足夠的驗證者投票時,它就會提交一個新的區塊以添加到區塊鏈中,並最終確定應用層中的狀態轉換。
Cosmos生態上的交易生命周期圖
以下是Cosmos SDK的具體執行邏輯,在分析下文漏洞觸發路徑時可以方便查閱理解:
Cosmos SDK重點ABCI的具體執行邏輯
常見漏洞分類
在了解漏洞分類之前,我們需要對漏洞危險程度有一個基本劃分,這樣有助於更好地識別出危險性大的安全漏洞,盡可能規避潛在的安全風險。
從危險程度和影響範圍考慮,我們主要關注Critical和Major評級的安全漏洞,它們通常可以造成以下風險:
1. 鏈停止運行
2. 資金損失
3. 影響系統狀態或正常運行
而這些危險的起因往往是以下幾種類型的安全漏洞:
1. 拒絕服務
2. 錯誤的狀態設置
3. 驗證缺失或者不合理
4. 唯一性問題
5. 共識算法問題
6. 實現上的邏輯漏洞
7. 語言特性問題
漏洞分析
由於Cosmos生態模塊化的特殊性,各類鏈條實現上存在大量模塊間相互使用,模塊內相互調用的案例,因此存在漏洞觸發路徑與漏洞觸發位置變量的可控路徑不一致的情況,我們在分析漏洞具體觸發原因時不應只關注觸發路徑,還應該關注漏洞關鍵變量的可控路徑,這樣才能幫我們更好地劃分定義漏洞模型。
鏈停止運行
鏈停止運行的罪魁禍首大多情況下是單個區塊執行過程中產生的問題,但在Cosmos的歷史發展過程中也出現過共識安全漏洞而導致鏈不得不主動停止來修復的情況,因此這裏把影響共識類型的安全漏洞也放到導致鏈停止運行效果裏來討論,我們會分別來講這兩類問題。
第一類情況常見的是拒絕服務類型的漏洞,其具體原因主要是不當的崩潰處理與循環邊界可被用戶影響的遍歷操作。此類漏洞往往會使得鏈暫停運行,或者減緩其運行速度等。
前文中有提到Cosmos SDK和CometBFT作爲Cosmos生態中關鍵的基礎設施,它們不僅被Cosmos中的基礎鏈使用,各類的應用鏈也都基於其架構實現各自邏輯,因此它們都會遵從CometBFT的ABCI接口規則,其攻擊面重點也是在其ABCI接口上,而能夠造成的Chain halt的安全漏洞大多是可以直接影響到區塊代碼執行的問題,因此其發生的路徑基本都可溯源到BeginBlock和EndBlock兩個接口。
第二類情況是屬於影響到共識的漏洞,通常和各類鏈的實現相關,目前已知的常見於一些邏輯處理驗證,時間校准和隨機性問題。此類漏洞從本質上會影響到區塊鏈的去中心化原則,直觀上看可能並沒有太大影響,但假如經過有心者惡意設計,那么依然會產生較大的安全風險。
第一類情況
案例一:SuperNova項目
漏洞背景:鑄幣分發操作中缺乏地址驗證,從而導致操作失敗,資金流失。在鑄幣模塊中,每次token鑄造都取決於抵押金額。然而,如果池不存在或者合約地址輸入錯誤,鑄幣模塊可能會發生意外情況,導致區塊鏈停止運行。在獎勵池模塊中,池合約地址沒有經過驗證。如果分發操作失敗,鏈將直接停止運行。
漏洞位置:https://github.com/Carina-labs/nova/blob/932b23ea391d4c89525c648e4103a3d6ee4531d5/x/mint/keeper/keeper.go#L175
漏洞代碼片段:
漏洞觸發路徑:
BeginBlocker (/x/mint/keeper/abci.go) Keeper.DistributeMintedCoin Keeper.distributeLPIncentivePools PoolIncentiveKeeper.GetAllIncentivePool (/x/mint/keeper/keeper.go)
漏洞補丁:
https://github.com/Carina-labs/nova/commit/538abc771dea68e33fd656031cbcf2b8fe006be0
補丁位於poolincentive的消息處理模塊(x/poolincentive/types/msgs.go),而非mint模塊。
對處理MsgCreateCandidatePool(即創建pool)時的消息做了地址校驗,是想從根源上杜絕錯誤地址的可能。
案例二:Cosmos Interchain Security項目
項目地址:https://github.com/cosmos/interchain-security
漏洞背景:驗證者可以通過在同一個區塊中提交多個AssignConsumerKey消息來減緩提供鏈的速度。在x/ccv/provider/keeper/key_assignment.go中定義的AssignConsumerKey函數使驗證者能夠爲經批准的消費鏈分配不同的consumerKey。爲了執行此操作,consumerAddrsToPrune AddressList會增加一個元素。由於在x/ccv/provider/keeper/relay.go中的EndBlocker中會遍歷這個AddressList,攻擊者可以利用它來減慢提供鏈的速度。爲執行這種攻擊,惡意行爲者可以創建具有多個AssignConsumerKey消息的交易,並向提供鏈發送這些交易。consumerAddrsToPrune AddressList的基數將與發送的AssignConsumerKey消息相同。因此,EndBlocker的執行將花費比預期更多的時間和資源,導致提供鏈運行速度減緩,甚至停止。
漏洞位置:https://github.com/cosmos/interchain-security/blob/6a856d183cd6fc6f24e856e0080989ab53752102/x/ccv/provider/keeper/key_assignment.go#L378
漏洞代碼片段:
漏洞觸發路徑:
msgServer.AssignConsumerKey Keeper.AssignConsumerKeyAppModule.EndBlock EndBlockCIS HandleLeadingVSCMaturedPackets HandleVSCMaturedPacket PruneKeyAssignments
案例三:Quicksilver項目-Airdrop模塊
漏洞背景:BeginBlocker和EndBlocker是模塊开發人員可以在其模塊中實現的可選方法。它們分別在每個區塊的开始和結束時觸發。在BeginBlock和EndBlock方法中使用崩潰來處理錯誤可能會導致鏈在出現錯誤時停止。EndBlocker清算未完成的空投時未考慮模塊是否有足夠的代幣從而觸發崩潰的可能,導致鏈停止運行。
漏洞位置:https://github.com/quicksilver-zone/quicksilver/blob/b4aefa899e024d60f4047e2f2f403d67701b030e/x/airdrop/keeper/abci.go#L15
漏洞代碼片段:
漏洞觸發路徑:
AppModule.EndBlock Keeper.EndBlocker Keeper.EndZoneDrop
漏洞補丁:https://github.com/quicksilver-zone/quicksilver/blob/20dc658480b1af1cb323b4ab4a8e5925ee79a0ed/x/airdrop/keeper/abci.go#L16
直接去掉了panic的處理代碼,換成了記錄錯誤日志。
案例四:Cosmos Interchain Security項目
項目地址:https://github.com/cosmos/interchain-security
漏洞背景:攻擊者可以通過向提供鏈的獎勵地址發送多個代幣來可以實現拒絕服務攻擊。
在消費鏈的EndBlocker執行流程中,在x/ccv/consumer/keeper/distribution.go中定義的SendRewardsToProvider函數獲取tstProviderAddr中所有代幣的余額,並將它們發送到提供鏈。爲了實現這一點,它必須遍歷獎勵地址中找到的所有代幣,並逐個通過IBC發送到提供鏈。由於任何人都可以向獎勵地址發送代幣,攻擊者可以創建並發送大量不同denom的代幣,例如使用具有token工廠模塊的鏈,來發起拒絕服務攻擊。因此,EndBlocker的執行將花費比預期更多的時間和資源,導致消費鏈運行速度減緩,甚至停止。
漏洞位置:https://github.com/cosmos/interchain-security/blob/6a856d183cd6fc6f24e856e0080989ab53752102/x/ccv/consumer/keeper/distribution.go#L103
漏洞代碼片段:
漏洞觸發路徑:
AppModule.EndBlock EndBlock EndBlockRD SendRewardsToProvider
第二類情況
這一類共識問題可能並不能帶來直觀的嚴重危害,但是從整個區塊鏈本質原則和體系考慮,亦或是從具體的場景去看這些漏洞的話,它們帶來的影響和危害並不見得比其他常規漏洞危害小,除此之外,這類漏洞也有存在着共同點。
案例一
漏洞背景:Cosmos SDK Security Advisory Jackfruit
Cosmos SDK的x/authz模塊中ValidateBasic方法的非確定性行爲容易導致共識停止。x/authz模塊的MsgGrant消息結構包含一個Grant字段,其中包括用戶定義的授權所授予的到期時間。在Grant結構的ValidateBasic()驗證處理中,比較其時間信息與節點本地的時間信息而不是區塊時間信息,由於本地時間是非確定性的,各個節點的時間戳可能存在差異,因此會導致共識問題。
漏洞公告:
https://forum.cosmos.network/t/cosmos-sdk-security-advisory-jackfruit/5319
https://forum.cosmos.network/t/cosmos-sdk-vulnerability-retrospective-security-advisory-jackfruit-october-12-2021/5349
https://github.com/cosmos/cosmos-sdk/security/advisories/GHSA-2p6r-37p9-89p2
漏洞代碼片段:
漏洞補丁:
https://github.com/cosmos/cosmos-sdk/compare/v0.44.1...v0.44.2
像關於時間戳這樣的問題不僅會出現在Cosmos SDK這樣的基礎組件中,在各類應用鏈中也曾出現過類似的漏洞。
案例二
漏洞背景:SuperNova,nova項目
項目地址:https://github.com/Carina-labs/nova/tree/v0.6.3
使用time.Now()返回操作系統的時間戳。本地時間是主觀的,因此是非確定性的。由於各個節點的時間戳可能存在小的差異,因此鏈可能無法達成共識。在ICAControl模塊中,交易發送函數使用time.Now()來獲取時間戳。
漏洞位置:https://github.com/Carina-labs/nova/blob/932b23ea391d4c89525c648e4103a3d6ee4531d5/x/icacontrol/keeper/send_msgs.go#L14
漏洞代碼片段:
漏洞補丁:
將使用本地時間戳改爲了使用區塊時間。
timeoutTimestamp := time.Now().Add(time.Minute * 10).UnixNano() _, err = k.IcaControllerKeeper.SendTx(ctx, chanCap, connectionId, portID, packetData, uint64(timeoutTimestamp))timeoutTimestamp := uint64(ctx.BlockTime().UnixNano() + 10*time.Minute.Nanoseconds()) _, err = k.IcaControllerKeeper.SendTx(ctx, chanCap, connectionId, portID, packetData, uint64(timeoutTimestamp))
案例三
漏洞背景:BandChain項目的預言機模塊
項目地址:https://github.com/bandprotocol/bandchain/
代碼庫中的注釋表明,預言機模塊必須在質押之前執行,以便實現違反預言機協議者的懲罰措施。代碼中出現的順序是:在SetOrderEndBlockers函數中,質押模塊在預言機模塊之前運行。如果質押模塊在預言機模塊之前執行,那么基於預言機模塊中完成的驗證來懲罰驗證者質押等操作將是不可能實現的。
漏洞位置:https://github.com/LeastAuthority/bandchain/blob/master/chain/app/app.go#L221-L225
漏洞代碼片段:
可以看到漏洞具體實現和漏洞注釋完全是反過來的,預言機模塊應該排在質押模塊之前。
案例四
漏洞背景:Sei Cosmos項目的accesscontrol模塊
項目地址:https://github.com/sei-protocol/sei-cosmos
在Cosmos各類代碼庫的多個實例中,go map iteration都有使用go語言的map類型,並對其進行了迭代。由於go語言的map的迭代是非確定性的,這將導致節點達到不同的狀態,這可能會導致共識問題,從而導致鏈停止運行。比較合適的處理方法是將映射鍵排序到一個切片中,並迭代排序後的鍵。此類問題比較普遍,屬於是語言特性在運用上引入的問題。
在x/accesscontrol/keeper/keeper.go的BuildDependencyDag的實現中,節點迭代anteDepSet。由於Go中映射迭代的非確定性行爲,ValidateAccessOp可能會出現兩種不同類型的錯誤,這可能會導致共識失敗。
漏洞位置:https://github.com/sei-protocol/sei-cosmos/blob/afe957cab74dd05c213d082d50cae02dd4cb6b73/x/accesscontrol/keeper/keeper.go#L314C9-L314C9
漏洞代碼片段:
根據這些案例可以發現,對於使得鏈被動停止運行的漏洞危害性往往最大,其漏洞起因的邏輯關系都可追溯到直接影響區塊鏈中單個區塊運行的執行流程。而像一些共識安全漏洞,往往是鏈主動停止運行去修復,其漏洞起因的邏輯關系都可追溯到影響區塊鏈整體的運行流程和狀態。與我們接下來討論的造成資金損失類型的漏洞關注點不同,資金損失類型的漏洞通常不會去根據其問題出現的邏輯路徑來判斷其具體危險影響程度,而是更關注其資金的擁有者、資金量的大小、影響資金的範圍以及影響資金的方式等。
資金損失
資金損失類問題常見於對sdk.Msg和IBC消息的邏輯處理中,當然在能夠造成鏈停止運行的原因中也存在有部分漏洞可以造成鏈資金損失的效果,具體影響還得看具體漏洞,這裏着重討論前者。此外由於IBC是Cosmos生態中非常重要的一環,因此難免會涉及到IBC的部分漏洞,具體關於IBC的攻擊面與相對應的漏洞我們放到下一章節去探討。
資金損失常見於gas消耗、資金被鎖無法取出、資金傳輸過程中丟失、計算邏輯錯誤導致資金損失和資金存儲ID未保證唯一性等邏輯情況。
這裏我們以SuperNova項目爲例,分析下和它相關的三個漏洞。
漏洞背景:SuperNova項目
項目地址:https://github.com/Carina-labs/nova
如果區域(zone)的小數位數高於18,資金可能會被鎖定。在該項目代碼中,區域的小數位數沒有上限,可以超過18位。在ClaimSnMesssage中,當用戶希望索取他們的份額代幣時,使用了ClaimShareToken。然而,如果區域的小數位數高於18,那么轉換將失敗,無法從系統中提取資產。因此通過控制區域小數位數,可以直接觸發交易崩潰失敗。
漏洞位置:https://github.com/Carina-labs/nova/blob/v0.6.3/x/gal/keeper/claim.go#L167
漏洞代碼片段:
漏洞觸發路徑:
msgServer.ClaimSnAsset Keeper.ClaimShareToken Keeper.ConvertWAssetToSnAssetDecimal precisionMultiplier
漏洞背景:SuperNova項目
項目地址:https://github.com/Carina-labs/nova/
區域的唯一性未經驗證。在已注冊的區域上,使用區域ID來檢查基礎代幣(BaseDenom)的唯一性,每個區域的BaseDenom應該是唯一的,如果基礎代幣的值設置錯誤,將導致資金損失。該項目在RegisterZone中設置基礎代幣之前,並未確保BaseDenom在所有主區域中都是唯一的,否則會存在用戶向另一含有同名BaseDenom的惡意zone存儲資金的可能性,從而造成資金損失。
漏洞位置:https://github.com/Carina-labs/nova/blob/v0.6.3/x/icacontrol/keeper/msg_server.go#L99
漏洞代碼片段:
漏洞補丁:多了DenomDuplicateCheck檢查
除此之外上文鏈停止運行第一種情況中的案例一,是由於崩潰導致鑄幣失敗,也是資金損失的一種形式。
漏洞背景:Supernova項目
項目地址:https://github.com/Carina-labs/nova/
缺少狀態更新。在IcaWithdraw()方法中,如果交易失敗,版本狀態沒有修改,會導致WithdrawRecord無法訪問,對應的資金也無法提取。更通俗的理解就是state設置在SendTx前,失敗後未修改state,導致該資金回撤失敗並且下次無法再次回撤。
漏洞位置:https://github.com/Carina-labs/nova/blob/932b23ea391d4c89525c648e4103a3d6ee4531d5/x/gal/keeper/msg_server.go#L356
漏洞代碼片段:
根據這部分的案例可以發現,與資金相關的操作主要實現邏輯,還是取決於對各類消息的處理,當然也存在如第一類情況的案例一在BeginBlock執行流程中涉及到的鑄幣操作,當這些操作失敗時也會導致資金損失。整體來說,我們將審計重點放在涉及資金操作的代碼模塊就可以大幅提高發現此類漏洞的可能性。
影響系統狀態或正常運行
此類問題範圍比較寬泛,剛才討論的前兩者危害其實也可以認爲是影響系統狀態或正常運行的漏洞類型的子集。除此之外,危險性更大的更多是一些邏輯類型的漏洞,很大程度上,這類漏洞會根據項目的業務邏輯而產生不同的安全風險,但是由於Cosmos SDK組件構造的相似性以及模塊化的特點,在具體代碼實現時候往往會犯下類似的錯誤,這裏給大家列舉下常見的漏洞類型:
sdk.Msg類型中變量校驗不完全
由於各項目基於sdk.Msg實現了各式各樣的派生類型,但是在Cosmos SDK中其實並未對所有已有類型的各個元素做相應的檢測,導致疏漏了一些關鍵的內嵌變量檢測,從而存在一定的安全風險。
案例一:Cosmos SDK Security Advisory Barberry
漏洞背景:MsgCreatePeriodicVestingAccount.ValidateBasic驗證機制缺失對账戶的存活等狀態的判斷。在x/auth中定義的PeriodicVestingAccount,攻擊者可以將受害者的账戶初始化爲惡意歸屬账戶,該账戶允許存款但不允許取款。當用戶將資金存入其账戶時,這些資金將被永久鎖定,並且用戶無法提取。
漏洞補丁:
https://forum.cosmos.network/t/cosmos-sdk-security-advisory-barberry/10825
https://github.com/cosmos/cosmos-sdk/security/advisories/GHSA-j2cr-jc39-wpx5
https://github.com/cosmos/cosmos-sdk/compare/v0.47.3-rc.0...v0.47.3
https://github.com/cosmos/cosmos-sdk/pull/16465
漏洞代碼片段:
除此之外,Cosmos-SDK Security Advisory Elderflower、Cosmos-SDK Security Advisory Jackfruit,其實都是在ValidateBasic環節出現的問題,前者是直接缺失了對ValidateBasic的調用,後者則是在消息內部關於時間戳變量校驗出現的問題。而在應用鏈,此類的問題更是常見,像ethermint,pstake-native,quicksilver等項目在處理消息的驗證措施上都出現過類似的安全漏洞。
除了驗證類型,在sdk.Msg的處理邏輯中,也會遇到如涉及到大量gas消耗的循環操作,不合理的崩潰處理等,由於針對消息的處理鏈上具備相應的recovery機制,因此它們的危險程度相對於鏈停止運行會低一些,但依然可以影響到系統的正常運行或是導致鏈上資金的損失。
常見類型漏洞
除去根據項目業務特有的安全漏洞,還存在一些比較常見的漏洞模型,比如資金損失案例三,就是一個在發送消息前改變狀態的操作,這類漏洞和智能合約中的漏洞很相似,在傳輸資金之前先改變了自身的狀態,往往會帶來如重入或者遺留的錯誤狀態等問題,像這種狀態設置和消息傳輸緊密結合的場景在區塊鏈中其實十分常見,很多造成重大危險的漏洞都是源於此類問題。除此之外,還有一些計算上的安全漏洞類似於除零漏洞、gas消耗繞過、使用有漏洞的版本等,這類漏洞都會影響到系統狀態或系統正常運行。
唯一性問題
由於區塊鏈上涉及到大量的查找讀取存儲操作,因此在某些功能實現中,命名的唯一性非常重要。例如前文資金損失案例二,就是唯一性問題,除此之外一些代表key等重要因素的string或者byte數組類型的變量,有時候它們的前綴組成也會存在一定的風險,比如是否存在"/"作爲每次命名的結尾等,稍有不慎就可能會導致命名被僞造成另一種含義的字符串,從而導致一系列如資金損失、共識出錯等問題。
語言特性問題
這類問題更加寬泛一些,但是比較有特徵可循,因此較爲容易被發現,比如golang的map迭代問題、rust中的一些panic機制問題等,建議在使用對應語言前,將這些語言特性本身可能會導致對應風險的點列舉出來,在使用或者審計時單獨關注即可最大程度上避免此類錯誤。
小結
根據我們對Cosmos生態底層安全問題的探索,其實不難發現,此類問題不僅適用於Cosmos生態,有很多漏洞模型同樣可以運用在其他的生態鏈中,以下是有關研究Cosmos生態系統安全問題的一些建議和總結:
關注基礎設施漏洞:CometBFT和Cosmos SDK的核心組件也可能存在漏洞,因此需要對這些組件進行定期更新和維護,以確保安全性。
及時審查第三方庫:Cosmos开發者通常使用第三方庫來擴展其應用程序的功能。然而,這些庫可能包含潛在的漏洞,因此需要審查和更新這些庫以降低風險。
注意惡意節點攻擊:在Cosmos生態系統中,共識節點是網絡的關鍵組成部分。節點的拜佔庭容錯算法可能會受到攻擊,因此需要確保節點的安全性以防止不良行爲。
注意物理安全:對於運行Cosmos節點的硬件和服務器,需要採取物理安全措施以防止未經授權的訪問和潛在的攻擊。
必要的代碼審查:由於Cosmos SDK和CometBFT生態系統的开放性,开發者和審查員應該對核心代碼以及在自定義模塊中編寫的代碼進行審查,以識別和糾正潛在的安全問題。
留意生態系統工具:Cosmos生態系統包括許多工具和應用程序,這些工具也需要進行安全審查和定期更新,以確保其安全性。
IBC協議安全指南
本模塊將重點探討IBC協議(The Inter-Blockchain Communication protocol)方面相關的安全問題。IBC協議是Cosmos中極其重要的一環,它的作用是架起各鏈之間的交互橋梁,假如說其他各類跨鏈橋是爲一些較爲獨立的問題提供解決方案,那么IBC協議可以說是爲鏈之間的交互問題提供了統一的基礎解決方案和底層技術支持。IBC是一種允許異構區塊鏈以可靠、有序和信任最小化的方式傳遞任何數據的協議。
自比特幣問世以來,區塊鏈領域經歷了爆炸性的增長。數不清的新網絡紛紛湧現,它們各自擁有獨特的價值主張、共識機制、意識形態、支持者和存在理由。在引入IBC之前,這些區塊鏈大都處於獨立運作的狀態,就像存在於封閉的容器中,無法相互通信,然而這種封閉的模式從根本上是不可持續的。
假如將區塊鏈視爲各個人口不斷增長並充滿商業活動的國家,有的區塊鏈擅長農業,而有的在畜牧業方面表現出色,它們自然而然地希望進行互利的貿易和合作,各自發揮自身優勢。毫不誇張地說,IBC开闢了一個充滿無限可能性的新世界,使不同的區塊鏈能夠互操作、傳遞價值、交換資產和服務,並建立連接,而不受今天大型區塊鏈網絡固有的可擴展性問題所限制。
那么IBC是如何滿足這些需求,並起到至關重要的作用呢?根本原因在於IBC是:
1. 無需信任的
2. 可支持異構區塊鏈的
3. 可在應用層進行自定義的
4. 經過檢驗的成熟技術
IBC協議的基礎是輕客戶端(light clients)和中繼器(relayers)。通過IBC進行通信的鏈A和鏈B互相具有對方账本的輕客戶端。鏈A無需信任第三方,只需通過驗證區塊頭就可以對鏈B的狀態達成共識。通過IBC(尤其是模塊)進行交互的鏈彼此間不會直接傳送消息。相反,鏈A將數據包中的一些消息同步至其狀態。隨後,中繼器會對這些數據包進行檢測,並將它們傳送給目標鏈。
總的來說,IBC協議可分爲兩層,分別是IBC TAO和IBC APP。
IBC TAO:定義數據包的傳輸、身份驗證和排序的標准,即基礎設施層。在ICS中,這由核心、客戶端和中繼器類別組成。
IBC APP:定義通過傳輸層傳遞的數據包的應用程序處理程序的標准,這些包括但不限於同質化代幣轉账(ICS-20)、非同質化代幣轉账(ICS-721)和鏈間账戶(ICS-27),並且可以在應用程序類別的ICS中找到。
IBC圖表(來自Cosmos Developer Portal)
IBC協議是Cosmos堅持的區塊鏈互聯網(Internet of Blockchains)愿景的支柱。從這個意義上說,IBC的設計選擇受到了TCP/IP規範的影響。與TCP/IP爲計算機通信制定標准的方式類似,IBC也指定了一組通用抽象,通過將其實現可以允許區塊鏈進行通信。TCP/IP對通過網絡中繼的數據包的內容不設限制,IBC也是如此。此外,與HTTP和SMTP等應用協議在TCP/IP上搭建的方式類似,同質化資產/非同質化資產傳輸或跨鏈智能合約調用等應用實例也將IBC協議作爲基礎層。
目前IBC協議出現的主要問題都是在關於通道傳輸和數據包的處理上,當然也不乏在證明驗證等環節出現過比較大的問題,但那些問題相對較少,本文重點討論IBC協議的常見問題。由於IBC協議的模塊化設計,IBC應用程序开發人員可以無需關注客戶端、連接和證明驗證等底層細節。但他們需要實現IBCModule接口,以及相對應的Keeper處理方法等,因此較多IBC協議相關的問題都出現在IBCModule關於接收和處理數據包的接口(onRecvPacket, OnAcknowledgementPacket, OnTimeoutPacket等)代碼路徑中。
常見漏洞分類
在Cosmos生態中,IBC協議作爲連接樞紐,從漏洞種類上來說IBC協議相關的漏洞更爲豐富,出現漏洞的位置更加復雜,由於IBC協議的相關實現和Cosmos-SDK,CometBFT等模塊結合密切,下文中難免會提到一些Cosmos生態其他模塊的實現。此外,目前IBC主要運用在Cosmos生態系統中,因此其主流使用語言還是Golang,詳情可見ibc-go相關文檔。
由於篇幅限制,這裏不再針對IBC協議中各個環節和組件做細致的分析,只對現有的一些安全漏洞做分類探討,如果想了解更爲細致和全面的分析,歡迎聯系我們CertiK的安全工程師交流探討。
常見漏洞分類:
1.命名漏洞
① 字符串處理漏洞
② 字節碼處理漏洞
2. 傳輸過程漏洞
① 數據包順序漏洞
② 數據包超時漏洞
③ 數據包認證漏洞
④ 其他數據包漏洞
3. 邏輯漏洞
① 狀態更新漏洞
② 投票共識等漏洞
③ 其他邏輯漏洞
4. Gas消耗漏洞
現有的IBC協議,在審計和分析其安全性的流程上和Web2協議的審計流程上具有較多相似性,這次我們將從協議的制定、實現和運用擴展這樣一個完整流程的角度來剖析IBC協議上的部分安全問題和潛在風險。由於協議的制定往往是由少數人員和組織去完成的,對於各類區塊鏈組織來說,更多的工作是圍繞在協議的實現和運用擴展上,因此本文也將重點討論這兩者的安全問題。這是出於對IBC協議安全風險涵蓋範圍廣的考慮,能更好地把協議上不同類型的安全問題劃分到對應的環節和模塊中。
漏洞分析
IBC協議的制定
案例一:ICS-07協議,邏輯漏洞
漏洞背景:解綁期限的錯誤使用
在代碼中存在如下校驗:
if currentTimestamp.Sub(consState.Timestamp) >= clientState.UnbondingPeriod {
根據Tendermint安全模型來看,時間爲t的區塊(標頭)的NextValidators中的驗證器需要在t+TrustingPeriod之前正確運行,在那之後,它們可能會有其他行爲。然而這裏檢查的是UnbondingPeriod,而不是TrustingPeriod,其中UnbondingPeriod>TrustingPeriod。如果consState的期限介於TrustingPeriod和UnbondingPeriod之間,那么將接受該標頭作爲用於驗證構成不當行爲的其中一個衝突標頭的基准。在此期間,consState.NextValidators中的驗證器不再被認爲是值得信任的,敵對的前驗證者可以在不冒任何風險的情況下關閉客戶端。
項目地址:https://github.com/cosmos/ibc/tree/e01da1d1346e578297148c9833ee4412e1b2f254/spec/ics-007-tendermint-client
漏洞位置:https://github.com/cosmos/ibc/tree/e01da1d1346e578297148c9833ee4412e1b2f254/spec/ics-007-tendermint-client#misbehaviour-predicate
https://github.com/cosmos/cosmos-sdk/blob/6344d626db1fbdba5e0f67425703c1584021bf5b/x/ibc/light-clients/07-tendermint/types/misbehaviour_handle.go#L96
漏洞代碼片段:
協議定義函數
代碼實現
IBC協議的實現
IBC協議的實現環節是比較容易出現問題的地方,因爲這個環節起到了承上啓下的作用,既要盡可能的避免協議規範中的歧義問題,又需要爲了協議後續的運用和擴展實現提供更爲基礎便捷的接口。因此這裏將IBC協議實現環節的主要問題再做一個小分類,即:
1. 協議實現中的歧義和不規範問題
2. 協議設定誤差問題
協議實現中的歧義和不規範問題
案例一:ICS-20協議,命名漏洞
漏洞背景:托管地址衝突。GetEscrowAddress()是截斷爲20字節的SHA256(端口ID+通道ID)。這種方法存在三個問題:
1.端口和通道之間沒有域分隔,使用字符串串聯不會分隔端口和通道的域。例如端口/通道組合(“transfer”、“channel”)和(“trans”、“ferchannel”)將給出相同的托管地址,即截斷的SHA256(“transferchannel”)。如果某些具有庫功能的模塊能夠選擇端口和通道ID,則可能會出現漏洞。
2.模塊账戶地址之間的衝突。在SHA-256的前映像中使用任意的字母數字字符串,後映像大小爲160位。這種小後映像和快速的哈希函數的組合使得生日攻擊成爲可能,因爲其安全性僅降至80位。這意味着大約需要2^80次猜測即可找到兩個不同的托管账戶地址之間的碰撞。2018年,在Tendermint的背景下已經進行了詳細的攻擊SHA256截斷的成本分析,證明了從成本的角度來看這種攻擊是可行的,找到碰撞意味着兩個不同的托管账戶映射到同一個账戶地址。這可能導致存在從托管账戶中盜取資金的風險,詳情可查看ICS20 GetEscrowAddress pre-image domain overlaps with public keysT:BUG。
3. 模塊和非模塊账戶地址之間的衝突。公共账戶地址的構造與Ed25519公鑰的20字節SHA-256相同。雖然160位的安全性足以防止對特定公共地址的衝突攻擊,但針對生日攻擊的安全性又只有80位。這種情況類似於一種半生日攻擊模式,其中一個地址由快速SHA-256生成,另一個地址由相對較慢的Ed25519公鑰計算生成。雖然這種情況會更加安全,但它仍然會引發對托管和公共账戶的潛在攻擊。
項目地址:https://github.com/cosmos/ibc/tree/e01da1d1346e578297148c9833ee4412e1b2f254/spec/ics-020-fungible-token-transfer
漏洞位置:https://github.com/cosmos/cosmos-sdk/blob/6cbbe0d4ef90f886dfc356979b89979ddfcd00d8/x/ibc/applications/transfer/types/keys.go#L40-L47
https://github.com/cosmos/cosmos-sdk/blob/6cbbe0d4ef90f886dfc356979b89979ddfcd00d8/x/ibc/applications/transfer/keeper/relay.go
漏洞代碼片段:
協議設定誤差問題
案例一:IBC Security Advisory Dragonberry,傳輸過程漏洞
漏洞背景:IBC在處理應用數據包時會使用一個Packet的結構,根據超時機制,同步和異步的確認機制以及相應的證明驗證流程,數據包會分成兩個執行流程:
1.正常情況:超時內成功
2.超時情況:超時失敗
IBC應用數據包傳輸流程圖
當發生超時情況時,說明此次傳輸失敗,IBC協議便會發起退款流程,同時需要注意的是IBC具有用戶可配置的超時機制。此次的Dragonberry漏洞源自ICS-23(IBC),該漏洞的根本原因在於用戶可以僞造驗證流程中的不存在證明(即未收到數據包的虛假證明),從而繞過安全校驗,僞造出“合理的”IBC超時情況來欺騙IBC協議,導致中繼器發送帶有虛假證明的超時數據包,並可能會升級爲ICS-20雙花問題,其漏洞的具體觸發流程可以看下圖。
Dragonberry漏洞原理流程圖
項目地址:https://github.com/cosmos/ibc-go/tree/00a680cda52690a4ba835bf37f53acc41c01bc7a/modules/core/04-channel
漏洞位置:https://github.com/cosmos/ibc-go/blob/00a680cda52690a4ba835bf37f53acc41c01bc7a/modules/core/04-channel/keeper/timeout.go#L117C28-L117C54
漏洞代碼片段:
案例二:IBC Security Advisory Huckleberry,傳輸過程漏洞
漏洞背景:UnreceivedPackets僅通過查找查詢中包含的每個序列號的相應數據包收據來構建響應。這僅適用於無序通道,因爲有序通道使用的是nextSequenceRecv而不是數據包收據。因此,在有序通道上,通過GetPacketReceipt查詢序列號不會找到其中的收據。
此問題的嚴重程度較輕,因爲ICS-20 FT傳輸的通道大部分是無序的,並且中繼器不依賴這個grpc端點來確定觸發超時數據包。然而,假如目標鏈中有大量數據包,同時配置了用於IBC傳輸的有序通道,且沒有對grpc響應進行分頁,這將產生導致服務節點性能下降甚至崩潰的風險。其具體的觸發流程可以看下圖。
Huckleberry漏洞原理流程圖
項目地址:https://github.com/cosmos/ibc-go/blob/11297aaa61e651c16e6d4147a15be24ce55ba7cc/modules/core/04-channel/
漏洞位置:https://github.com/cosmos/ibc-go/blob/11297aaa61e651c16e6d4147a15be24ce55ba7cc/modules/core/04-channel/keeper/grpc_query.go#L408
漏洞代碼片段:
IBC協議的運用和擴展
案例一:stride airdrop漏洞,邏輯漏洞
漏洞背景:TryUpdateAirdropClaim該函數將IBC數據包的發送者地址轉換爲名爲senderStrideAddress的Stride地址,並從數據包元數據中提取airdropId和新的空投地址newStrideAddress。然後調用UpdateAirdropAddress來更新senderStrideAddress和ClaimRecord。隨着ClaimRecord的更新,newStrideAddress將能夠領取空投。然而這裏更新函數只校驗了sender該請求的地址是否爲空,未對newStrideAddress做校驗,由於ibc允許solo machine 連接實現IBC-enabled的鏈,因此這裏就存在更新任意其他账戶地址作爲空投地址的安全風險。
項目地址:https://github.com/Stride-Labs/stride/tree/3a5c7bfcc3b8c5e7dd870f01bebeb9d949492203/x/autopilot
漏洞位置:https://github.com/Stride-Labs/stride/blob/3a5c7bfcc3b8c5e7dd870f01bebeb9d949492203/x/autopilot/module_ibc.go#L119
https://github.com/Stride-Labs/stride/blob/3a5c7bfcc3b8c5e7dd870f01bebeb9d949492203/x/autopilot/keeper/airdrop.go#L17
漏洞代碼片段:
案例二:neutron ibc模塊漏洞,gas消耗漏洞
漏洞背景:智能合約爲IBC事件的確認/超時支付的費用沒有得到足夠的驗證,惡意智能合約可以利用這一點在OnAcknowledgementPacket和OnTimeoutPacket消息處理期間導致ErrorOutOfGas崩潰。這些崩潰不會通過outOfGasRecovery執行來恢復,這意味着交易不會包含在區塊中,並且會導致IBC中繼器重復提交消息,最終可能會造成中繼器資金流失和網絡廢棄數據包過多的危害。
項目地址:https://github.com/neutron-org/neutron/blob/64868908b21f648ad5e8a9b48179134619544e2a/
漏洞位置:
https://github.com/neutron-org/neutron/blob/64868908b21f648ad5e8a9b48179134619544e2a/x/interchaintxs/keeper/ibc_handlers.go#L62
漏洞代碼片段:
小結
根據上文對IBC協議安全問題的研究分析,其實不難發現,IBC協議的安全問題分布範圍廣,且問題多樣,但主要問題還是出現在IBC協議的實現和運用擴展上。在各大應用鏈逐漸豐富完善自身傳統模塊功能性的同時,爲了貼合自身業務需求,優化運行效果,也在對應的IBC模塊中添加了不同的代碼實現。
除了上文提到IBC環節中的安全問題外,其他一些如IBC中間件的安全問題也在湧現,相信在未來,IBC模塊方面的安全問題會成爲Cosmos生態安全中的重要一環。
總結
在針對Cosmos生態安全的探索與研究過程中,我們經歷了復雜的審計、匯總和分類工作,探討了關於Cosmos生態裏最爲關鍵的Cosmos SDK和IBC協議兩者的安全問題,並通過豐富的實踐經歷,總結出大量通用的審計經驗。
本報告突顯了在面對支持跨鏈交互的異構網絡時所面臨的挑战,由於其組成元件復雜且分散,因此在對這些組件進行安全審計時同樣具有挑战性,我們不僅需要通過已有的安全經驗去排查固有的一些安全風險,還需要不斷面臨新的安全場景,分析新的安全問題。
盡管如此,我們依然相信,通過類似本報告所總結的一些通用場景和安全問題,可以逐步提高異構網絡Cosmos生態整體的安全性。
鄭重聲明:本文版權歸原作者所有,轉載文章僅為傳播信息之目的,不構成任何投資建議,如有侵權行為,請第一時間聯絡我們修改或刪除,多謝。