arrayref 投毒案:构建期脚本与 yank 机制被全面武器化

arrayref 投毒案:构建期脚本与 yank 机制被全面武器化

Rust供应链安全CargoAPT

数据源:HN + web research

86 分钟隐秘扩散:从十载零依赖到后门投递

2026 年 8 月 20 日 07:15 UTC,拥有 2.45 亿次累计下载量的 Rust 底层库 arrayrefcrates.io 上突发更新至 0.3.10 版本。在长达十年的维护历史中,这个包含 4 个宏定义的小型库从未引入任何外部依赖。本次版本更新新增了对 proc-macro1 的依赖,在 86 分钟的网络在线窗口内,将构建期后门精准推向了全球 Rust 开发者的编译环境。

arrayref 历史版本 0.3.9 的下载量高达 1.52 亿次,深植于生态底层。一个长期保持零依赖的基础组件突然改写构建依赖树,容易避开依赖审计团队的日常抽查。如此高的下载基数意味着,绝大多数自动化流水线在触发依赖构建时,对底层的突发变更毫无察觉。

Wiz 安全团队的遥测数据显示,arrayref 存在于 35% 以上的企业环境中,在配置了 Rust 工具链的系统中覆盖率高达 75%。该库通过 tiny-skiasctk-adwaitawinit 等组件深入 eguiiced GUI 生态。攻击者选择在末端基础库中植入恶意代码,能以极高的概率在图形应用构建过程中实现静默渗透。

arrayref 之外,受影响的发布版本还包括上线 90 分钟的 [email protected] 与上线 107 分钟的 [email protected]。虽然安全响应团队在两小时内全面删除了涉及的恶意包,但自动化 CI/CD 流水线在此期间已拉取了这些恶意组件。

伪装与瞒天过海:proc-macro1 如何绕过工程审视

恶意依赖 proc-macro1 针对拥有 1.54 亿次下载量的基础库 proc-macro2 实施了拼写抢注(Typosquatting)。发布账号 dtolney 模仿知名开发者 David Tolnay,在项目元数据中伪造作者信息 David Tolnay <[email protected]>,并将 repository 字段填入指向 404 页面的虚假地址。这种视觉相似度与知名维护者信息的混淆,极大地削弱了审阅者的警惕心理。

为进一步掩盖恶意意图,proc-macro1 源代码目录完全复制了 proc-macro2 的实现逻辑,甚至同步替换了文档链接和 Issue 引用。这种全量代码克隆保证了任何上层代码调用都能正常编译通过。任何常规的单元测试或接口检查都无法暴露代码主体的异常。

真正的攻击载荷被隐藏在 proc-macro1build.rs 脚本中。恶意脚本将控制服务器的 URL 字符串分片为 Base64 编码数组 SRC_URL_PARTSEND_URL_PARTS,在编译期进行拼接重组。这段逻辑解码后的远端地址为 hxxps://23.254.165.112:9089/,对应 C2 节点 23.254.165.112:443

静态分析工具在扫描源代码时通常关注标准语法结构,这种分片编码配合构建脚本的混淆技术成功躲过了轻量级检查。后门代码完全脱离了主库的接口定义,仅在 Cargo 调用构建脚本阶段被触发激活。

武器化的 Cargo 机制:从 build.rs 到 yank 诱饵

SafeDep 对 arrayref 构建期恶意 payload 的分析 图:SafeDep 对 arrayref 构建期恶意 payload 的分析流程。来源:safedep.io

build.rs 内部,攻击者实现了一个跳过所有证书校验的自定义 TLS 校验器 AcceptAll verifier。该校验器强制信任自签名证书,确保在没有预装合法根证书的容器环境中也能无障碍发起 HTTPS 连接。后门程序利用这种网络兼容度,消除了中间人审查与证书验证带来的连接失败风险。

在 Unix 系统上,后门脚本释放并执行临时文件 /tmp/rust-setup;在 Windows 系统上,脚本写入 %TEMP%\rust-setup.ps1rust-setup-launch.vbs 进行后台隐蔽启动。载体启动后会立即脱离构建进程主线程,避免因持续网络请求导致编译过程卡死超时。即使开发者中断编译,已经运行的后台子进程依然在宿主系统中静默存活。

攻击者接管维护者账号后,恶意废弃(yank)了 arrayref 历史上的正常版本 0.3.50.3.9。当下游项目重新执行构建时,Cargo 会弹出版本提示 consider updating to a version that is not yanked。警告机制原本旨在引导开发者弃用带有已知漏洞的依赖,却在此处直接把开发人员推向了唯一的未废弃版本 0.3.10

包管理器的安全防护设计在账号被接管后发生了机制扭曲。防御性的更新建议演变成引导下游主动引入恶意的后门版本的诱饵,展现了依赖治理机制被逆向利用的破坏力。

APT 的影子:AES-128-GCM 加密与凭据盗取

Wiz 对 arrayref 供应链攻击与 DPRK 活动重叠的分析 图:Wiz 安全团队发现的供应链攻击基础设施关联。来源:wiz.io

第二阶段被下载的载体针对 x86_64 架构的 Linux、Windows、macOS 以及 aarch64 架构的 macOS 进行了专门编译,文件命名为 rust-crate_0.1.0~0.4.0。全平台架构的精准适配表明攻击方具备完备的交叉编译环境,意图一次性覆盖常见的开发者终端与服务器环境。

根据 Wiz 的分析,该载体包含功能完整的木马模块,通过 HTTPS POST 请求将包含主机元数据的 Base64 JSON 报文回传至 C2 接口 /49890878。木马会直接查询 Chrome、Brave 和 Edge 的 SQLite 凭据存储数据库,读取已保存的登录信息与扩展设置。

载体内置了基于硬编码密钥 i am botking 的 AES-128-GCM 加密通信算法,并采用内置 RSA-2048 私钥验证来自控制端的四类控制命令。这类加密机制与权限校验逻辑表明,该攻击载体是经过长期打磨的成熟后门武器。

安全威胁情报显示,C2 端点 /49890878 与 SSL 证书签发者 WIN-A6QF8AHPQH1\Administrator@WIN-A6QF8AHPQH1 与微软归因于朝鲜黑客组织 Sapphire Sleet 的 Mastra 活动高度重合。此外,涉案 IP 节点 23.254.167.216 曾出现在 UNC1069 针对 axios npm 包的攻击历史中。这些基础设施的交集表明,高度有组织化的 APT 团队正在把攻击焦点转向开源语言生态的构建阶段。

信任架构重塑:Rust 依赖构建安全的工程反思

针对本次投毒事件,Rust 官方安全响应团队发布了本地缓存排查命令:find ~/.cargo/registry/cache -type f \( -name 'arrayref-0.3.10.crate' -o -name 'proc-macro1-*.crate' ... \) -print。然而事后的缓存清理只能对已知受污染的环境进行抹除,无法挽回编译时刻已经发生的凭据外泄与本地提权。

arrayref 事件突显出当前包管理机制下的深层挑战:只要在 Cargo.toml 中增加一行依赖,Cargo 默认的构建行为就会在开发者本地无差别执行该依赖的 build.rs。当维持了多年的账号信任被破解,包管理器的自动更新机制与废弃警告反而加速了恶意载体的扩散速度。

仅仅依赖对 crates.io 的账号安全审计和事后撤包无法彻底消除此类威胁。要从根本上抵御构建期攻击,生态需要默认对 build.rs 的执行权限施加沙箱限制,并在包管理器层面重新审视依赖废弃(yank)带来的自动化升级风险。

参考链接:

  • SafeDep 对 arrayref 构建期恶意 payload 的分析文章
  • Wiz 安全研究对 arrayref 供应链攻击与 DPRK 活动重叠的分析报告
  • Nextron Systems 关于 proc-macro1 威胁情报