Babylon协议安全性研究与状态边界漏洞解析

本文分享了针对比特币质押协议Babylon的安全性研究成果,深入分析了在时间边界和状态转换过程中出现的四类典型漏洞,包括委托状态处理不当、节点惩罚机制规避以及协同质目账目错误。文章总结了从历史漏洞补丁中寻找新攻击向量的经验,并强调了在复杂分布式系统中验证状态机边界行为的重要性。

本文介绍了我们对 Babylon 的安全性研究。Babylon 是目前最大的 BTC 质押 DeFi 协议。我们将解释 Babylon 的工作原理、我们遇到的一类反复出现的安全问题、发现这些问题的方法,以及对未来工作的思考。

免责声明: 本研究于 2025 年作为内部计划独立进行,不应被视为正式的安全审计。研究结果已报告给 Babylon Labs,并已得到确认和处理。这项限时研究的目的是与社区分享额外的补充知识。

作者:Qiuhao Li

项目背景

Babylon 是一个原生比特币质押协议,旨在通过共享安全架构将比特币的安全性扩展到其他网络。在这种模型中,BTC 可以被质押以帮助保护其他区块链,同时保持可恢复性并支持较快的解质押,并对可证明的协议违规行为进行可配置的削减(Slashing)。

截至撰写本文时,Babylon 的总锁定价值(TVL)约为 30 亿美元,是目前最大的 BTC 质押协议。Babylon 在安全性方面进行了持续投入,包括多次第三方审计和公开安全竞赛。

Babylon 工作原理

Babylon 是一个分层系统,协调比特币侧的质押交易与 Cosmos SDK 链(Babylon Genesis)。Babylon Genesis 作为控制平面,负责质押激活、投票权、最终性、检查点和奖励。

架构图

比特币侧质押

BTC 质押使用 Taproot 输出,提交到一个包含时间锁质押、按需解质押和削减路径的脚本树。交易有效性受 Babylon Genesis 参数和比特币确认深度的约束。合规性取决于契约委员会(Covenant Committee)的阈值签名,以及在最终性提供者(Finality Provider)违规时可执行的预签名削减交易

Babylon Genesis 链

Babylon Genesis 是一条 Cosmos 链,通过自定义模块实现协议逻辑:

  • Epoching (x/epoching):将链划分为周期(Epoch),并将验证者集的更改延迟到周期边界。
  • Checkpointing (x/checkpointing):收集验证者签名并聚合为用于比特币检查点的多重签名。
  • BTC Staking (x/btcstaking):验证/激活 BTC 委托,跟踪质押参数,并维护活跃的最终性提供者集和投票权。
  • Finality (x/finality):验证最终性提供者的投票并基于投票权敲定区块。

链下组件

Babylon 依赖链下组件在比特币和 Babylon 之间移动数据。Vigilante 套件 监控比特币和 Babylon 并中继关键信息。其他组件包括质押守护进程、最终性提供者软件、密钥管理和契约模拟器。

典型质押流程

  1. 选择最终性提供者并准备 Babylon 账户。
  2. 从 Babylon Genesis 获取当前的 BTC 质押参数。
  3. 根据质押脚本格式构造比特币交易。
  4. 在 Babylon Genesis 上提交注册交易(此时无包含证明)。
  5. 契约侧在 Babylon 上提交验证签名。
  6. 广播比特币质押交易并等待确认。
  7. 链下观察者提交比特币包含证明,委托变为活跃状态并开始贡献投票权。

研究计划

我们将研究结构化为针对不可信数据流的分层手动审查:

  • 层级:执行层(自定义模块)、部分共识层(ABCI++)和链下组件。
  • 不可信输入与边界:用户提供的质押数据、验证者提供的投票/提案以及跨链消息。

我们通过阅读代码、分析历史审计报告、查看 GitHub 上的修复 PR 和安全公告来建立上下文,并针对已知漏洞模式检查是否存在新的边缘案例。

研究发现

1. 委托状态处理不当导致投票权持久化

Babylon 的 x/btcstakingx/finality 模块通过“状态更新事件”协调投票权。问题在于 BTCDelegation.GetStatus 仅因缺少契约法定人数就返回 PENDING 状态,即使比特币高度已显示该委托即将过期。

这导致契约签名验证可以继续进行,并最终在同一笔质押已发生 EXPIRED(过期)事件后,又追加了一个 ACTIVE(活跃)事件。由于投票权更新流程不会再看到后续的过期事件,最终性提供者即使在 BTC 质押过期后仍能保留投票权,削弱了共识安全假设。

流程图

2. 最终性提供者可通过切换状态绕过入狱机制

Babylon 要求活跃的最终性提供者(FP)参与投票,否则会在错过过多投票时将其“入狱”(Jailing)。在 HandleFinalityProviderLiveness 中,入狱条件的评估相对于 StartHeight 进行,而 StartHeight 会在 FP 变为活跃时刷新。因此,FP 可以通过在滑动窗口边界附近短暂退出再重新进入活跃集,不断重置窗口,从而在不参与投票的情况下避免被入狱。

绕过机制

3. 周期中削减验证者导致的联合质押核算错误

Babylon 的联合质押逻辑使用质押Hook(Hooks)来跟踪影响奖励的 ActiveBaby 聚合值。当验证者被标记为已削减(Slashed)时,AfterDelegationModified Hook停止更新 ActiveBaby,但 BeforeDelegationRemoved Hook仍会根据预削减比例减去 Token 金额。

这种不一致会导致减去的质押额超过了本周期内计入 ActiveBaby 的数额,从而降低奖励并导致追踪器验证失败,造成解质押相关的交易失败并冻结资金。

4. 区块提案验证中的未检查类型断言导致崩溃

在每个周期开始时,Babylon 期望区块提案中的第一笔交易是特殊的“注入检查点交易”。在周期边界的 ProcessProposal 路径中,解码器执行了盲目的 Go 类型断言。恶意提案者可以放置一个类型错误的单消息交易,在验证过程中触发运行时恐慌(Panic),导致验证者崩溃。

为什么这些问题容易被忽视

在这些发现中,出现了两个反复出现的模式:

  • 时间边界:问题出现在特定的时间点(周期的首个区块、活跃度滑动窗口阈值、质押过期截止点)。
  • 集中的状态变化:问题需要系统在特定时间窗口内按特定顺序观察到状态转换。

边界条件和紧密耦合的状态转换在实现和审查过程中很容易被忽略。通过显式枚举状态机并测试这些边界周围的对抗性序列,通常能最好地发现这些问题。

发现问题的过程

除了手动审查,我们还借鉴了先前的漏洞和修复方案,寻找类似模式或将其演变为新的攻击场景。

案例 1:从修复 PR 中发现新绕过路径

对于 FP 入狱绕过问题,我们从阅读 PR #584 开始,该 PR 修复了一个由 FP 状态反复切换触发的活跃度问题。随后我们审查了相关代码在滑动窗口边界的边缘案例,从而发现了新的绕过漏洞。

PR 截图

2. 从安全公告中发现类似崩溃风险

针对未检查类型断言问题,我们首先阅读了关于 BLS 投票扩展触发 Panic 的公告,然后利用 AI 协助验证其他可能的攻击方法,搜索类似的导致链停滞的故障,最终在注入检查点解码路径中发现了该漏洞。

3. 从审计报告中发现相关新漏洞

在链下组件方面,我们在阅读先前的审计报告时发现了一个分页漏洞。报告指出 Vigilante 在获取质押交易时,页面索引按 batchSize 而非 1 递增,导致交易被跳过。

审计报告截图

基于此,我们检查了相关的分页逻辑,发现了两个导致拒绝服务(DoS)的新问题:

  • RPC 服务器静默地将 per_page 限制为 100,导致终止逻辑因“返回数 < 请求数”而提前退出。
  • 单笔交易可能发出多个事件,导致哈希数量与返回交易数不一致,触发页面验证错误。

总结与未来展望

本文介绍了一些具有共同模式的安全发现:在时间边界打破不变性的状态转换。在未来对类似系统的审计中,显式建模状态机并验证对抗性顺序下的边界行为至关重要。

我们的研究覆盖了 Babylon Genesis 链和链下组件,但尚未涉及比特币侧的质押脚本,这对于质押、解质押和削减机制至关重要,可能存在进一步的研究机会。

最后,AI 助手在导航和假设验证方面很有帮助,但在处理跨模块的复杂攻击流时仍有局限。

致谢

感谢 Babylon Labs 在披露过程中的专业表现,他们迅速处理了报告并发布了修复程序。同时感谢 Jonas Merhej、Loukas Papachristoforou、Jainil Vora 和 Ionut-Viorel Gingu 对初稿提供的反馈。

  • 原文链接: x.com/openzeppelin/statu...
  • 登链社区 AI 助手,为大家转译优秀英文文章,如有翻译不通的地方,还请包涵~
点赞 0
收藏 0
分享
本文参与登链社区写作激励计划 ,好文好收益,欢迎正在阅读的你也加入。

0 条评论

请先 登录 后评论
OpenZeppelin
OpenZeppelin
江湖只有他的大名,没有他的介绍。