IBC协议中的ICA活跃通道替换漏洞与升级攻击分析

本文详细分析了Cosmos IBC协议中ICA活跃通道的安全漏洞,攻击者可在通道升级或握手过程中通过竞态条件替换活跃通道,导致交易反序列化失败和功能中断。报告包含完整的PoC实现和修复方案。

报告 #2917368 - 升级期间替换ICA活跃通道及更多细节

影响摘要

存在两个潜在问题:

  1. 活跃通道在通道确认(channel ack)期间在控制器上设置。这是一个“先检查后执行”的操作,且是原子性的。但GetOpenActiveChannel仅在通道开放时返回通道,在刷新(flushing)状态时不返回。

  2. 活跃通道在通道开放确认(channel open confirm)期间在主机上设置,但检查通道是否存在的操作在try阶段完成。虽然包含FLUSH*状态,但不是原子性的。

重现步骤

我们在源链上监控新初始化的通道,遍历返回的通道并对匹配的通道执行攻击。当一切就绪后提交ICA创建(参见视频),此处负责执行受害者部分。我使用当前版本,因为版本会在升级过程中改变。主要思路是使新通道与合法通道不同。

攻击分为两个步骤:

  1. 准备工作:由于主机上的“先检查后执行”操作不是原子性的,在控制器上的ICA通道初始化和主机上的ICA通道开放确认之间存在机会窗口。在此窗口期间,我们在控制器上使用ICA端口和连接执行通道初始化(chan init),在主机上执行通道尝试(chan try)。

  2. 等待受害者通道开始升级:脚本将发起新编码的升级提案,但我们的通道将使用旧编码。编码用于在主机上反序列化交易。

提案通过后,攻击获取新的升级序列并执行完整的通道更新,同时完成恶意通道的握手。

合法通道:channel-1,我的通道:channel-2

我同时运行中继器(relayer),因为需要ICA通道像在真实环境中那样完成。但中继器也会拾取我的通道。在合法通道开放后停止它,但在握手期间打印以下消息:

1
error Error sending messages {"path_name": "demo", "src_chain_id": "ibc-1", "dst_chain_id": "ibc-0", "src_client_id": "07-tendermint-0", "dst_client_id": "07-tendermint-0", "error": "rpc error: code = Unknown desc = rpc error: code = Unknown desc = failed to execute message; message index: 1: channel open ack callback failed for port ID: icacontroller-cosmos1zr776t6fpjtyx8vqfhn0ene3jzm5q7nc2674d0, channel ID: channel-2: existing active channel channel-1 for portID icacontroller-cosmos1zr776t6fpjtyx8vqfhn0ene3jzm5q7nc2674d0: active channel already set for this owner"

这是正确的。错误正好来自此处。

但一旦升级开始,我完成握手后通过:

1
2
3
channel acked
successfully acked channel on the source chain channel-2 for port icacontroller-cosmos1zr776t6fpjtyx8vqfhn0ene3jzm5q7nc2674d0 and connection connection-0 
{"level":"info","msg":"Successful transaction","chain_id":"ibc-0","gas_used":105368,"fees":"3310stake","fee_payer":"\u001bZf\u0007\u00144u \ufffd\ufffd\ufffdx\ufffdh\ufffd\ufffdT\ufffdM\u0012","height":134,"msg_types":["/ibc.core.channel.v1.MsgChannelOpenAck"],"tx_hash":"1E1968F24B19D38D0C1ABA0212884E6D295796660862F99C249002739548EE40"}

然后它也在主机上通过开放确认。我们为这个ICA设置了一个具有不同设置的新通道作为活跃通道。 (需要安装Go,并确保没有simd运行)

我不得不对ibc-go进行调整以提交升级提案。从wasm轻客户端获取逻辑。我收到一个错误,说提案必须由治理模块签名(这很合理)。所以不确定这是否是一个错误,或者必须设置权限账户。无论如何,请检出我修改的分叉,或者如果可能,将您的账户设置为治理权限。这样您就能够提交升级。并构建ibc-go:make build。记下simd的路径(在build文件夹中)并在此处更改。 (另外请注意,我们的恶意通道不会受到升级的影响,因为它没有开放。)

检出我的中继器ica分支。此攻击只需要demo文件夹。但还需要路径中的rly二进制文件,您可以从官方中继器或我的中继器构建。

检出https://github.com/unknownfeature/ibc-tools/tree/one,切换到分支one,并将附加的main.go放到根目录。

修改main.go中的rootFolder以指向包含脚本的正确文件夹。

转到relayer/examples/demo(rootFolder)并运行./dev-env。等待直到看到此消息: “Run ‘rly start and run active_channel.go, press ENTER after everything is up”

运行main.go,它将打印2行并等待。 之后打开另一个选项卡并启动rly start。我们需要它完成ICA握手。但它也会尝试完成我们在攻击中发起的握手,最初会出错,但一旦我们通过确认,它将尝试继续我们的握手。这将完成与我们相同的事情,只是我的小攻击可能会出错,并且对于演示目的来说看起来不太好。但即使中继器完成它,攻击的结果也是相同的。所以我只是等待它打开合法通道,并在打印"Successfully created new channel {“chain_name”: “ibc-1"后停止它。应该在ibc-1上,这意味着握手结束。

当一切就绪后,在dev-env请求的地方按"ENTER”。查看攻击的输出。这将需要一些时间。我将提案等待期设置为30秒。但我也等待ICA通道20秒。

我还想说,有时我的通道确认比合法通道更快到达源链。这就是我在这里睡眠的原因。但这也是一个有趣的用例。在某些情况下,活跃通道会在握手期间设置为错误的通道。非常机会主义。谁知道它在现实生活中会如何表现。

解决方法

看起来没有

支持材料/参考文献

  • active_channel_upgrade.mov - PoC视频
  • main.go - PoC

影响

该应用程序提供了在升级期间(或有时在握手期间)用恶意通道替换已建立的活跃通道的机会。我们无法更改ICA地址,无法更改连接。唯一可以更改的是编码。这可以防止主机链反序列化ICA交易。因此需要另一次升级才能使其工作。此外,考虑到没有查询方法来查看活跃通道,还需要一些调查。因此需要一些时间来弄清楚并使其再次工作。此外,我们可以预先设置不止一个而是多个通道。并为每次升级使用每个通道。

附件

2个附件:

  • F3901259: active_channel_upgrade.mov
  • F3901282: main.go

时间线

  • 2024年12月30日 20:32 UTC:unknown_feature向Cosmos提交报告
  • 2024年12月30日 20:33 UTC:unknown_feature更新漏洞信息
  • 2024年12月30日 20:35 UTC:unknown_feature更新漏洞信息
  • 2024年12月30日 21:15 UTC:amulet_mizmo将状态更改为"已分类"
  • 2024年12月30日 21:31 UTC:unknown_feature发表评论
  • 2025年1月2日 20:45 UTC:unknown_feature发表评论并附加更新后的PoC
  • 2025年1月5日 07:48 UTC:amulet_mizmo发表评论
  • 2025年1月5日 14:06 UTC:unknown_feature发表评论
  • 2025年5月20日 14:35 UTC:Cosmos向unknown_feature发放奖金
  • 2025年5月20日 14:55 UTC:arrb Cosmos员工关闭报告并将状态更改为"已解决"
  • 2025年5月21日 06:28 UTC:arrb Cosmos员工将严重性更新为低
  • 2025年5月29日 00:30 UTC:unknown_feature对严重性评级提出质疑
  • 2025年5月30日 14:33 UTC:unknown_feature请求HackerOne支持调解
  • 2025年5月31日 12:45 UTC:unknown_feature请求披露此报告
  • 2025年6月30日 12:46 UTC:报告被披露

报告详情

  • 报告时间:2024年12月30日 20:14 UTC
  • 报告者:unknown_feature
  • 报告对象:Cosmos
  • 状态:已解决
  • 严重性:低 (0.1 ~ 3.9)
  • 披露时间:2025年6月30日 12:46 UTC
  • 弱点类型:业务逻辑错误
  • CVE ID:无
  • 奖金:隐藏
comments powered by Disqus
使用 Hugo 构建
主题 StackJimmy 设计