摘要: crates.io上3个广泛使用的Rust crate被投毒,arrayref累计下载2.45亿次,恶意代码在构建时自动执行,基础设施与朝鲜黑客组织高度重叠。
你正在赶一个项目进度,cargo build 一把编译通过,运行正常,提交代码,下班回家。
你不知道的是,就在编译的那几秒钟里,一个恶意脚本已经悄悄在你电脑上跑完了——下载了远程载荷、建立了持久化后门、开始窃取你浏览器里保存的所有密码。
这不是假设。这是8月20日刚刚发生在Rust生态里的真实攻击。
一、三个crate,86分钟,一场精心策划的投毒
8月20日UTC时间07:15,crates.io上三个广泛使用的Rust crate几乎同时发布了新版本:arrayref 0.3.10、internment 0.8.7、append-only-vec 0.1.9。
这些版本号看起来就是正常的迭代更新。但它们有一个共同点:都在Cargo.toml里加了一行依赖——proc-macro1。
注意,是proc-macro1,不是proc-macro2。后者是Rust生态中最基础的过程宏库之一,几乎每个Rust项目都会用到。前者是一个彻头彻尾的仿冒品——一个typosquat(拼写抢注)包。更狡猾的是,proc-macro1的库代码是从proc-macro2原样复制的,所以编译完全正常,不会报任何错。
但proc-macro1的build script(构建脚本)里藏着恶意代码。在Rust中,build script会在编译时自动执行——不需要你调用任何函数,cargo build、cargo check、cargo test都会触发它。
这个build script做了什么?从base64碎片中重组出C2服务器地址,禁用TLS证书验证,然后根据你的操作系统和CPU架构下载对应的恶意载荷。Linux和macOS写到/tmp/rust-setup,Windows写一个PowerShell脚本再通过VBScript隐藏执行。
二、arrayref:2.45亿次下载的重量级目标
这次被投毒的三个crate中,arrayref是最重磅的。根据crates.io API数据,arrayref的累计下载量达到245,385,500次——2.45亿。仅在过去90天内,就有5390万次下载。crates.io上有403个不同的crate依赖它。
更重要的是它的依赖链位置。The Hacker News验证了完整的依赖路径:winit → sctk-adwaita → tiny-skia → arrayref。这些依赖关系全部使用caret范围(^0.3.x),意味着只要arrayref发布0.3.10,Cargo就会自动拉取这个被投毒的版本。
攻击者还非常阴险地在发布恶意版本的同一分钟内,把arrayref 0.3.5到0.3.9全部yank掉了。这样一来,当Cargo提示”consider updating to a version that is not yanked”时,唯一可选的”正常”版本就是被投毒的0.3.10。
GitHub用户jhobern就是这样中招的。他在RustSec的报告里写道:”0.3.5–0.3.9全部被yank了,cargo的’考虑升级到未被yank的版本’警告就是诱饵。我就是这样踩进去的。”
三、朝鲜黑客的影子
Rust安全响应团队在86到107分钟内删除了这些恶意版本,响应速度已经很快了。但攻击者的基础设施暴露了一些耐人寻味的线索。
云安全公司Wiz分析后发现,这次攻击使用的基础设施与近期多起朝鲜黑客发起的供应链攻击高度重叠——包括Mastra npm包投毒事件和axios投毒事件。微软以高置信度将Mastra事件归因于Sapphire Sleet(朝鲜APT组织),Google Threat Intelligence Group则将axios事件归因于MIDNIGHT NEPTUNE(前称UNC1069)。
虽然没有厂商正式将这次crates.io事件归因于特定组织,但基础设施重叠、攻击手法相似(维护者账号被入侵、typosquat依赖、构建时执行),朝鲜黑客的指纹相当明显。
攻击者使用的C2服务器地址为23.254.165.112,域名hwsrv-798836.hostwindsdns.com。第二阶段载荷会通过HTTPS POST与C2通信,在Windows上通过注册表Run键持久化,在macOS上通过LaunchAgent,在Linux上通过systemd用户服务。支持的命令包括:终止自身、重配C2、安装持久化、下载并执行更多脚本。
Wiz的分析还指出,这个恶意软件会查询Chrome、Brave和Edge浏览器的SQLite登录数据库来窃取凭证。
四、Cargo生态的系统性短板
这次事件暴露了Cargo/crates.io生态在供应链安全上的几个明显短板:
没有发布冷却期。 GitHub在7月已经为Dependabot加入了新发布包的冷却窗口机制。Cargo也有一个类似的PR(global-min-publish-age设置,可以阻止拉取太新的依赖),8月18日进入最终评论期——就在攻击发生前两天——但到8月21日仍未合并。如果这个功能已经上线,这次攻击可能根本不会成功。
维护者账号保护不足。 arrayref的唯一所有者是David Roundy,2009年10月注册的老账号。这个账号是怎么被入侵的?目前不得而知。但一个显而易见的问题是:crates.io是否强制要求维护者启用双因素认证?从高价值crate被入侵的频率来看,答案显然是否定的。
yank机制的滥用。 攻击者利用yank机制把所有正常版本标记为”已撤回”,诱导Cargo推荐恶意版本。yank本来是一个让维护者撤回有问题版本的善意功能,但在账号被入侵的场景下,它反而成了攻击武器。
五、你现在该做什么
如果你是Rust开发者,以下几件事现在就该做:
立刻排查。 搜索~/.cargo/registry/cache目录,看有没有arrayref 0.3.10、internment 0.8.7、append-only-vec 0.1.9的缓存文件。如果有,说明你在那个时间窗口内编译过包含恶意版本的项目。
锁定arrayref版本。 把arrayref固定在0.3.9或更早版本。Rust安全响应团队在响应过程中已经unyank了这些版本,所以你可以正常使用。
检查异常文件。 在Linux/macOS上检查/tmp/rust-setup是否存在,在Windows上检查%TEMP%\rust-setup.ps1和%TEMP%\rust-setup-launch.vbs。同时检查是否有可疑的systemd用户服务、LaunchAgent或注册表Run键。
检查网络连接。 查看你的网络日志或EDR告警,是否有到23.254.165.112(端口9089和443)或hwsrv-798836.hostwindsdns.com的连接记录。
对CI/CD加冷却期。 在Cargo.toml或CI配置中,考虑添加依赖版本的最小发布年龄限制。等新版本发布一段时间后(比如7天)再自动升级,给安全社区留出检测恶意版本的时间。
六、供应链攻击的未来:更快、更隐蔽、更自动化
npm、PyPI、RubyGems、crates.io——几乎所有主流开源包仓库都在被系统性地攻击。攻击者的手法越来越成熟:不再是简单粗暴地上传一个明显恶意的包,而是入侵合法维护者账号、利用typosquat伪装、把恶意代码藏在build script里、利用yank机制诱导升级。
更值得关注的是,这次攻击从发布到被发现只用了不到90分钟,说明安全社区的监控能力在提升。但反过来看,攻击者的基础设施准备、账号入侵、版本yank、恶意发布——这些动作在几分钟内就完成了,说明攻击方也在高度自动化。
这是一场军备竞赛。开源生态的防御工具需要跑得比攻击者更快。
Cargo的global-min-publish-age PR还在等合并。GitHub的Dependabot冷却期已经上线。其他包仓库呢?还在等什么?
IoC(入侵指标):
- 网络:23.254.165.112:9089(载荷服务器)、23.254.165.112:443(C2)、hwsrv-798836.hostwindsdns.com
- 文件:/tmp/rust-setup、%TEMP%\rust-setup.ps1、%TEMP%\rust-setup-launch.vbs
- 二进制:rust-crate_0.1.0、_0.2.0、_0.3.0、_0.4.0
- 伪造账号:dtolney(crates.io ID 438608)、rchaitm@gmail.com
信息来源: The Hacker News / RustSec / Nextron Systems / Wiz / StepSecurity







发表评论
您还未登录,请先登录。
登录