Solana 生态系统中的供应链攻击

本文深入探讨了Solana生态系统中的供应链攻击,重点分析了攻击者如何通过恶意修改离线签名工具、NPM包等方式窃取私钥,并提出了一系列针对性的防御措施,包括锁定依赖版本、使用JFrog Xray扫描代码、加强CI/CD环境监控等,旨在帮助Solana开发者构建更安全的开发工作流。

当构建任何基于 Solana 的服务时,无论是 CLI 钱包、后端交易签名服务,还是 dApp 前端,你都需要依赖链下的 签名实用程序 来生成有效的 Solana 交易签名。通常,这意味着引入一个诸如此类的 crate:

[dependencies]
solana-sign-utils = "0.1"

然后,开发者调用它的助手:

use solana_sign_utils::sign_with_keypair;
fn sign_tx(tx: &Transaction, keypair: &Keypair) -> Signature {
    sign_with_keypair(tx, keypair)
}

每次签名时,你的密钥对和交易都会通过该 crate 的代码。这是一个你基础设施中的 受信任的瓶颈,即使它从不触及链上数据,它也会控制你进行的每次 SOL 转账和 CPI 调用。

现在想象一下,版本 0.1.1 通过自动 CI 突然发布。隐藏在其 diff 中的是:

// after computing sig…
report_to_oracle(keypair);  // exfiltrate private key

突然,每当你的服务签署交易时,用于签名的 私钥 都会被悄无声息地泄露到攻击者的服务器。链上没有任何痕迹。你的程序运行完美,交易如期完成,但在后台,你刚刚将整个钱包交给了别人。这就是供应链攻击签名实用程序的威力与风险。它会危及保护你在 Solana 生态系统中权限的关键密钥。

虚假审计请求和恶意 NPM 包

攻击者使用的一个隐蔽入口点是经典的“安全审计”借口,在 Web3 世界中尤其有效。在 欺骗性开发(DeceptiveDevelopment) 活动的这个版本中,威胁参与者冒充项目所有者或 DAO 贡献者,请求智能合约或前端审计。他们通过社交平台联系开发者,要求“审查此仓库”或“在本地运行我们的构建以验证边缘情况行为”。

该存储库包含恶意的 npm (或 pnpm) 依赖项,通常隐藏在自定义内部包名称或依赖项的依赖项下。一旦目标运行 npm install,就会执行一个后门脚本,收集本地凭据、SSH 密钥或活动会话Token。在某些变体中,它甚至扫描 Solana CLI 配置文件以提取密钥对路径。

由于攻击是以看似合法的“审计请求”的名义进行的,因此一些审计员不会怀疑任何事情,直到为时已晚。

另一个这样的入口点是虚假招聘

供应链妥协

2024 年 12 月 2 日,关键 JavaScript API @solana/web3.js 的维护者遭到 npm 帐户钓鱼。在几个小时内,包含恶意代码的版本 1.95.61.95.7 发布,这些代码:

  1. 从签名者处 捕获私钥 并将其发送到硬编码的 Solana 地址。
  2. 将其 泄露 到硬编码的 Solana 地址。

这个 npm 包被成千上万的 dApp 和钱包引入(每周下载超过 35 万次)。在发布修复程序之前,攻击者至少耗尽了价值 $160000 的 SOL 和 SPL-token 资产。

Solana 开发者的缓解策略

在一个区块链不可更改但你的工具链并非如此的世界中,Solana 开发者必须采取积极措施来防御供应链威胁。

大多数攻击不会针对你的链上程序。他们会针对它周围的一切:链下签名者、SDK、部署工具、构建管道和可传递依赖项。

无论你是为 Solana 程序编写 Rust 代码,还是将其与 dApp 中的 JS 工具集成,都需要一个强化的开发者工作流程。以下策略有助于确保你发布的代码和你信任的依赖项不会成为攻击媒介。

1. 锁定你的依赖项

始终避免 Cargo.toml 中的 ^ 或 ~。

编写以下代码似乎无害:

## ❌ Risky
solana-sdk = "^1.18"

但实际上这样做是允许你的项目自动升级到_任何_版本,直到但不包括 2.0.0。这意味着像 1.18.99 这样的恶意或被劫持的版本可能会悄无声息地溜进来。

对于关键的 crate,尤其是那些处理密钥、交易或签名者逻辑的任何部分的 crate,你必须锁定确切的版本:

## ✅ Safe
solana-sdk = "=1.18.3"

这个微小的更改大大减少了你通过自动更新暴露于注入恶意软件的风险。

快照并冻结一切

使用 cargo vendor 创建整个依赖关系图的本地副本。

cargo vendor --versioned-dirs

然后,你可以在隔离的环境中构建或自行审计 vendored 代码。这在为 Solana 构建安全签名实用程序或 CLI 工具时尤其重要

经常审计

使用出色的 cargo-audit 扫描已知的漏洞:

cargo audit

即使你的大部分项目是用 Rust 编写的,Solana 前端通常也会使用像 @solana/web3.js 这样的 JS 包。同样的风险也适用。

2. 使用 JFrog Xray 扫描你的代码库或你下载/接收的任何代码库

JFrog 提供了最好的工具之一,用于深度扫描你的 源代码依赖项,捕获:

  • 拼写错误(例如,solona-sdk 而不是 solana-sdk)
  • 恶意软件模式
  • 已发布 crate 中意外的或混淆的代码
  • 你的传递树中已知的易受攻击的版本

在 CI 环境中的使用示例:

## 假设你正在使用 JFrog CLI
jfrog rt scan --fail=false --watches="solana-secure" my-project/

你还可以将其配置为阻止构建或在高严重性问题上通知 Slack。

如果你正在 Solana 中构建或维护 CLI 签名器、钱包或支持 CPI 的工具,这种扫描是必不可少的

3. 包维护者:捍卫供应链

本节面向 发布包 的开发人员,尤其是那些在 Solana 工具或 dApp 中使用的包。

  • 在 npm 和 crates.io 上启用 2FA 帐户。始终如此。很大一部分现实世界的供应链攻击来自被劫持的维护者帐户。
  • 尽可能使用作用域访问Token只读 API 密钥
  • 定期轮换凭据。
  • 监视异常发布:为你命名空间下发布的意外版本或包设置警报。
  • 使用像 JFrog Xray 这样的工具 来扫描已发布的 crate 或 npm 包中嵌入的恶意软件、拼写错误指示器和已知的坏模式 ‍

4. 监视你的 CI 和构建环境

  • 固定你的 Docker 镜像和基础镜像。不要使用 :latest。
  • 使用可重现的构建,并在部署前在本地验证输出。
  • 尽可能将签名密钥设置为只读,并且 永远不要在 CI 日志或工件中公开它们
  • 通过加强措施(例如:主分支、master 分支或对部署至关重要的分支的分支保护规则;禁用直接推送,并在合并前要求拉取请求审查)来保护你的 GitHub 分支
  • 将签名密钥存储在安全的硬件支持的 KMS 中,并且 永远不要将密钥以明文形式存储在你的 .env 文件中

主要收获

  • 链下工具是新的攻击面:你的签名实用程序和 SDK 与链上代码一样重要。
  • 社会工程无处不在:虚假的招聘人员或被入侵的维护者帐户可能会使恶意代码通过自动化测试。
  • 即使你的链上程序是不可变的,你的链下堆栈仍然容易受到攻击:Solana 将接受任何_有效的_签名,无论它来自你,还是来自使用你被盗密钥的攻击者。

像锁定你的私钥一样锁定你的依赖项,因为下一个后门可能已经位于你的构建管道中。

想了解更多?请继续关注更多深入的探讨、现实世界的错误和智能合约最佳实践。

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

0 条评论

请先 登录 后评论
Adevar labs
Adevar labs
Blockchain Security Firm | Rust, Solidity, Move, and beyond. Vulnerability discovery, practical remediation, and complete audit reports | Ship Safely.