CertiK技术分享:《Cosmos 生态安全指南》

  • CertiK
  • 更新于 2024-10-23 12:11
  • 阅读 595

概况Cosmos是一款开源、开放、高度可扩展的区块链跨链网络,也是全球最为知名的区块链生态之一。Cosmos是一个由CometBFT(原Tendermint团队)推出的支持跨链交互的异构网络,由多条独立、并行的区块链组成去中心化网络,其愿景是打破信息的孤岛效应,实现不同区块链之间的互操作性。在当

image.png

概况

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.  提交区块:当节点接收到足够的验证者投票时,它就会提交一个新的区块以添加到区块链中,并最终确定应用层中的状态转换。

image.png 上图为Cosmos生态上的交易生命周期图

以下是Cosmos SDK的具体执行逻辑,在分析下文漏洞触发路径时可以方便查阅理解:

Cosmos SDK重点ABCI的具体执行逻辑

image.png

常见漏洞分类

在了解漏洞分类之前,我们需要对漏洞危险程度有一个基本划分,这样有助于更好地识别出危险性大的安全漏洞,尽可能规避潜在的安全风险。

image.png

从危险程度和影响范围考虑,我们主要关注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

漏洞代码片段:

image.png

image.png

漏洞触发路径:

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

漏洞代码片段:

image.png

image.png

漏洞触发路径:

msgServer.AssignConsumerKey   
        Keeper.AssignConsumerKey
AppModule.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

漏洞代码片段:

image.png

image.png

漏洞触发路径:

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

漏洞代码片段:

image.png

漏洞触发路径:

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

漏洞代码片段:

image.png

漏洞补丁:

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

漏洞代码片段:

image.png

漏洞补丁:

将使用本地时间戳改为了使用区块时间。

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

漏洞代码片段:

image.png

可以看到漏洞具体实现和漏洞注释完全是反过来的,预言机模块应该排在质押模块之前。

  • 案例四

漏洞背景: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

漏洞代码片段:

image.png

根据这些案例可以发现,对于使得链被动停止运行的漏洞危害性往往最大,其漏洞起因的逻辑关系都可追溯到直接影响区块链中单个区块运行的执行流程。而像一些共识安全漏洞,往往是链主动停止运行去修复,其漏洞起因的逻辑关系都可追溯到影响区块链整体的运行流程和状态。与我们接下来讨论的造成资金损失类型的漏洞关注点不同,资金损失类型的漏洞通常不会去根据其问题出现的逻辑路径来判断其具体危险影响程度,而是更关注其资金的拥有者、资金量的大小、影响资金的范围以及影响资金的方式等。

  • 资金损失

资金损失类问题常见于对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

漏洞代码片段: image.png

image.png

漏洞触发路径:

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

漏洞代码片段:

image.png

漏洞补丁:多了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

漏洞代码片段:

image.png

image.png

根据这部分的案例可以发现,与资金相关的操作主要实现逻辑,还是取决于对各类消息的处理,当然也存在如第一类情况的案例一在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

漏洞代码片段:

image.png

除此之外,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中找到。

image.png

上图为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

漏洞代码片段:

image.png

协议定义函数

image.png

代码实现

  • 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

漏洞代码片段:

image.png

  • 协议设定误差问题

  • 案例一:IBC Security Advisory Dragonberry,传输过程漏洞

漏洞背景:IBC在处理应用数据包时会使用一个Packet的结构,根据超时机制,同步和异步的确认机制以及相应的证明验证流程,数据包会分成两个执行流程:

1.正常情况:超时内成功

2.超时情况:超时失败

image.png

上图为IBC应用数据包传输流程图

当发生超时情况时,说明此次传输失败,IBC协议便会发起退款流程,同时需要注意的是IBC具有用户可配置的超时机制。此次的Dragonberry漏洞源自ICS-23(IBC),该漏洞的根本原因在于用户可以伪造验证流程中的不存在证明(即未收到数据包的虚假证明),从而绕过安全校验,伪造出“合理的”IBC超时情况来欺骗IBC协议,导致中继器发送带有虚假证明的超时数据包,并可能会升级为ICS-20双花问题,其漏洞的具体触发流程可以看下图。

image.png

上图为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

漏洞代码片段:

image.png

image.png

  • 案例二:IBC Security Advisory Huckleberry,传输过程漏洞

漏洞背景:UnreceivedPackets仅通过查找查询中包含的每个序列号的相应数据包收据来构建响应。这仅适用于无序通道,因为有序通道使用的是nextSequenceRecv而不是数据包收据。因此,在有序通道上,通过GetPacketReceipt查询序列号不会找到其中的收据。

此问题的严重程度较轻,因为ICS-20 FT传输的通道大部分是无序的,并且中继器不依赖这个grpc端点来确定触发超时数据包。然而,假如目标链中有大量数据包,同时配置了用于IBC传输的有序通道,且没有对grpc响应进行分页,这将产生导致服务节点性能下降甚至崩溃的风险。其具体的触发流程可以看下图。

image.png

 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

漏洞代码片段:

image.png

  • 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

漏洞代码片段:

image.png

image.png

  • 案例二: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

漏洞代码片段:

image.png

image.png

小结

根据上文对IBC协议安全问题的研究分析,其实不难发现,IBC协议的安全问题分布范围广,且问题多样,但主要问题还是出现在IBC协议的实现和运用扩展上。在各大应用链逐渐丰富完善自身传统模块功能性的同时,为了贴合自身业务需求,优化运行效果,也在对应的IBC模块中添加了不同的代码实现。

除了上文提到IBC环节中的安全问题外,其他一些如IBC中间件的安全问题也在涌现,相信在未来,IBC模块方面的安全问题会成为Cosmos生态安全中的重要一环。

总结

在针对Cosmos生态安全的探索与研究过程中,我们经历了复杂的审计、汇总和分类工作,探讨了关于Cosmos生态里最为关键的Cosmos SDK和IBC协议两者的安全问题,并通过丰富的实践经历,总结出大量通用的审计经验。

本报告突显了在面对支持跨链交互的异构网络时所面临的挑战,由于其组成元件复杂且分散,因此在对这些组件进行安全审计时同样具有挑战性,我们不仅需要通过已有的安全经验去排查固有的一些安全风险,还需要不断面临新的安全场景,分析新的安全问题。

尽管如此,我们依然相信,通过类似本报告所总结的一些通用场景和安全问题,可以逐步提高异构网络Cosmos生态整体的安全性。

报告PDF下载:https://indd.adobe.com/view/91035407-4f21-4383-9485-a56394d9f95f

  • 原创
  • 学分: 22
  • 分类: Cosmos
  • 标签:
点赞 0
收藏 0
分享
本文参与登链社区写作激励计划 ,好文好收益,欢迎正在阅读的你也加入。

0 条评论

请先 登录 后评论
CertiK
CertiK
CertiK总部位于纽约,由耶鲁大学和哥伦比亚大学的两位教授创立。作为头部Web3安全机构,CertiK以守护Web3生态的安全为愿景,依托其核心技术和人才优势,为全球150个国家的4682个项目提供审计、安全评级、合规与反洗钱、投资和安全相关服务,致力于最大化客户利益,并持续为社区创造价值。