autorenew
Solana PDA 冒充:一次遗漏的校验如何导致了发射台代币被盗

Solana PDA 冒充:一次遗漏的校验如何导致了发射台代币被盗

在 Solana 开发这个高速交易与创新 DeFi 工具并存的快节奏世界里,代码中的一个微小疏忽就可能打开通往重大利用的大门。这样的事情正是在三月对 MetaDAO 发射台审计中发生的——一个涉及 Program Derived Addresses (PDA) 的细微漏洞,可能让攻击者抽走新铸造的代币。作为 Solana 安全公司 Accretion “Advent of Bugs”(漏洞降临)系列的一部分,这个第 1 天的披露把 PDA 冒充的问题摆在了台面上,提醒每一个区块链开发者务必再次核查他们的签名者验证逻辑。

如果你正深耕 Solana 智能合约,或者只是尝试在像这样的发射台上参与 meme 代币发行,继续往下看。我们会拆解出问题所在,逐步演示攻击流程,并分享关键教训以保护你的项目安全。无需博士学位——只要清晰、直接的见解,帮助你增强防御。

场景设定:发射台对 PDA 的信任

MetaDAO 的发射台旨在让代币发行流程平滑且去中心化,就像我们在 Solana 上看到爆火的 meme 币掉落一样。在初始化一次新发射时,程序会创建一个名为 launch_signer 的特殊账户。这不仅仅是任意账户——它是从发射的主键和固定种子("launch_signer")派生出的 PDA。PDA 是 Solana 用来创建没有私钥的“签名者”账户的方法,使用确定性种子确保它们仅受程序逻辑控制。

想法很简单:launch_signer PDA 作为新代币的铸币权(mint authority)。它对向指定账户铸造初始代币进行签名,从而启动发射。为此,程序使用 Solana 的 invoke_signed 函数,让程序能够通过提供的种子“代表”PDA进行签名。

但问题就出在这里。指令并没有明确验证所提供的 launch_signer 账户是否“确实匹配”期望的 PDA 地址。相反,代码信任将种子传入 invoke_signed 会处理一切。剧透一下:并没有。

漏洞揭露:冒充签名者

Accretion 的审计员发现了这一漏洞:程序将 launch_signer 标记为未校验账户(UncheckedAccount),意味着对其地址没有内建验证。这允许任意 Solana 账户被传入——前提是它在交易中作为顶层签名者且与铸币的 authority 匹配。

这为何重要?在 Solana 中,当你使用与种子不匹配的 invoke_signed 时,如果该账户已经对外层交易进行了签名,函数并不会失败。种子被忽略,攻击者的密钥对的真实签名接管了签名流程。砰——冒充成功。

这不是某个边缘的理论风险,而是直接通往代币铸造的后门。

攻击实战:在发射前窃取代币

想象你是个盯上热门 meme 代币发射的攻击者。以下是利用方法,按步骤说明:

  1. 准备陷阱:创建一个新的 mint 账户,并将你自己的密钥对(称作 K)设置为 mint authority。然后,创建一个由 K 拥有的代币账户来接收赃款。

  2. 触发初始化:调用 InitializeLaunch 指令,传入 K 作为 launch_signer。确保 K 对顶层交易进行签名——这很容易,因为你控制 K。

  3. 铸造后门供给:程序欢然将代币铸到你 K 拥有的账户,以为它是通过 PDA 种子在签名。但实际上——是你的密钥对的签名在完成关键工作,而种子被置之不理。

  4. 掩盖痕迹:为避免触发警报,将大部分被盗代币转回,或将铸币权限交还给真实的 PDA,然后让发射按计划继续。你已经拿到非法分配,而项目方认为一切正常。

在 meme 代币的世界里,发射可能在数小时内推动数百万的资金,这种攻击可能在社区还未察觉前就抢走一大份额。这类隐蔽利用能把“飞向月球”变成“飞入攻击者的钱包”。

(如需查看标注出缺失校验的代码片段,请参见下方推文线程中的注释 Rust 代码。)

标注的 Solana Rust 代码,展示 PDA 派生和 launch_signer 中缺失的校验

为什么会发生:关于 Solana 签名细节的快速入门

如果你对 PDA 不熟,简单把它们想象成由程序控制的“幽灵签名者”。它们由种子(比如 ["launch_signer", launch.key()])和 find_program_address 派生,确保只有程序能在 CPI(跨程序调用)中通过种子进行“签名”。

但 Solana 的灵活性是把双刃剑。invoke_signed 依赖种子来将 PDA 的地址从 ed25519 曲线中“抬升”出来,以便程序化签名。没有显式的地址校验(例如 require_keys_eq!(launch_signer.key(), expected_pda)),攻击者就能换上他们自己的签名者。该线程的第二张图展示了完整的指令流程,包括那个未被校验的 mint。

用于代币铸造的 Solana 指令代码,包含未校验的 launch_signer PDA

这是经典的“信任但要验证”——用代码的话,就是始终进行验证。

给 Solana 开发者和 Meme 代币构建者的教训

Accretion 的修复?很简单:添加一条校验,确保传入的 launch_signer 与派生出的 PDA 相匹配。这样就没有冒充的空间了。

对所有在 Solana 上构建的人——尤其是在 meme 代币和发射台这片“狂野西部”——更广泛的要点:

  • 始终验证 PDA:使用 invoke_signed 时,计算期望的 PDA 并断言它等于提供的账户。这既便宜又万无一失。
  • 在可能的时候避免使用 UncheckedAccount:UncheckedAccount 提供了灵活性,但要与对签名者的显式校验配合使用。
  • 早审计、频繁审计:正如线程所指出的,这个漏洞在初次审查时被漏过。像 Accretion 这样的公司能发现这些宝石——在下次发射前考虑请人审计。
  • 测试边界情况:使用 Solana 的 solana-program-test 等工具模拟攻击,以捕捉签名者不匹配的问题。

在由炒作推动价值往往快于代码审查的 meme 代币生态里,这些漏洞可以决定项目成败。MetaDAO 在审计后修补了这个问题,但类似故事会让社区保持警惕。

总结:安全是积累的,漏洞不必如此

“Advent of Bugs” 系列开了个好头,提醒我们 Solana 的速度不能成为马虎安全的借口。向 @r0bre 和 Accretion 团队致敬——他们的分享对追求安全、可扩展发射的开发者来说是金矿。

你在酝酿 Solana 项目吗?在评论里说说你的看法:有没有遇到过 PDA 的坑?你的常用修复是什么?如果你在 Meme Insider 审计 meme 代币,联系我们获取最新的安全发射资讯。

保持警惕——因为在区块链世界里,一个未校验的签名者就能引发千百个利用。

你可能感兴趣