本文揭示了在Solana官方stake-pool程序中发现的语义不一致性漏洞,并讨论了漏洞的性质、发现过程及其利用方式。文章详细介绍了带来的风险及安全审计的重要性,强调需要更全面的审计流程。
sec3 团队最近在 solana-program-library 的官方 stake-pool 程序中发现了一个漏洞。该漏洞已在 这个 PR 中修复。感谢 @ joncinque 对我们确认并迅速解决问题的行动。
本文描述了我们发现漏洞和通过渗透测试构建 PoC 的历程。
我们注意到 stake-pool 代码 以前已被多家公司审计。本文强调了需要更加全面和系统化的审计过程(例如,通过 sec3 团队采用的自动化分析和验证工具)。
Solana 的 stake-pool 程序用于将 SOL 进行汇聚并在网络中重新分配 Stakes,以最大化抵抗审查和奖励。
已修复的问题( GitHub 上的 PR)
漏洞在于 stake-pool 的 process_initialize 指令中:
在初始化期间,没有为储备 stake 帐户中的 lamports 发放代币。因此,如果储备帐户在创建时有多余的资金,这笔钱将由 第一个 存款发放的代币进行委托/代表。如果这个存款是由攻击者进行的(例如通过前置操作),储备中的资金将被盗窃。
这个问题是微妙的,因为池的创建者可能错误地将多余的 lamports 放入储备 stake 帐户,并且 这种行为是未定义的。如果初始储备帐户没有钱或第一个存款者是池的创建者,则漏洞不会浮出水面。
重要通知: 由于 stake-pool 程序已被其他 Solana 项目分叉、重用或修改,易受攻击的代码可能已被广泛部署。如果你正在使用 stake-pool,请确保应用 修补程序。
sec3 团队在我们的工具箱中实验了一种新的检查器(早期原型已在 这里 发布)。新的检查器全面查看代码中的每一条路径并检测 语义不一致性问题:
如果两件事经常一起发生,则可能存在隐藏的不变性(在逻辑或语义级别),并且这一不变性的违反(例如其中之一缺失或顺序不同)会触发警告。
在 stake-pool 中,确实存在这样的不变性:每当 reserve_stake 帐户在指令中被使用(读取或写入时), spl_token::instruction (mint_to、transfer 或 burn) 也会在同一指令中使用。
然而,在该补丁之前的 process_initialize 指令中,reserve_stake_account 被使用 (第 637 行),但没有使用 spl_token::instruction. 因此,我们的检查器标志了一个 语义不一致性。
在 process_initialize 中使用 reserve_stake 帐户 的 stake-pool。
基于上述报告的语义不一致性问题,我们开始通过渗透测试构建 PoC(有关渗透测试技术的更多细节,可以在我们之前的博客 第 3 部分:渗透测试 中找到)。
第一步是初始化 stake pool:
在上面中,reserve_stake 帐户被初始化为 100 Sol:
接下来,黑客向 stake pool 存入 1.0 Sol 并领取 990000000 个池代币(这远远超过预期的代币数量):
最后,黑客销毁他们所有的池代币并提取所有资金:
黑客成功地利用了这个漏洞,窃取了 (99090100000–1100000000) lamports = 97.9901 Sol(见上文)。
sec3 由区块链安全和软件验证领域的领先人才创办。
我们很高兴为 Solana 上高影响力的 Dapps 提供审计服务。请访问 sec3.dev 或发送电子邮件至 contact@sec3.dev
- 原文链接: sec3.dev/blog/solana-sta...
- 登链社区 AI 助手,为大家转译优秀英文文章,如有翻译不通的地方,还请包涵~
如果觉得我的文章对您有用,请随意打赏。你的支持将鼓励我继续创作!