Shai-Hulud 蠕虫攻击概述
2025 年 9 月 15 日晚,一场针对 npm 生态系统的大规模供应链攻击开始爆发,这种被命名为"Shai-Hulud"的恶意软件以其自我复制能力迅速引起安全研究人员的关注。截至目前,已有约 150 个 npm 包被感染,包括每周下载量达数百万次的流行包如@ctrl/tinycolor 以及 CrowdStrike 公司的多个软件包。这次攻击以《沙丘》小说中的巨型沙虫命名,因其将窃取的凭证发布在包含"Shai-Hulud"名称的 GitHub 仓库中。
与之前的供应链攻击不同,Shai-Hulud 蠕虫具有自我传播能力,能够自动感染下游包,形成"级联式妥协",使攻击范围迅速扩大。这种能力使其成为迄今为止观察到的最严重的 JavaScript 供应链攻击之一。
Shai-Hulud 蠕虫的技术剖析
攻击载荷与执行机制
Shai-Hulud 蠕虫的恶意代码主要通过 bundle.js 脚本执行,该脚本在受感染包的 package.json 文件中通过 postinstall 钩子被触发。与之前的攻击不同,该脚本是跨平台的,同时支持*nix 和 Windows 环境。当开发者安装受感染的包时,恶意脚本会自动执行以下操作:
下载适合当前平台的 TruffleHog(合法的密钥查找工具)
在本地文件系统和可用仓库中搜索高熵字符串(加密密钥、API 令牌等)
分析环境变量(GITHUB_TOKEN、NPM_TOKEN、AWS_ACCESS_KEY_ID、AWS_SECRET_ACCESS_KEY)
通过查询 npm whoami 和 GitHub user API 端点验证令牌有效性
恶意脚本特别针对 Linux 或 macOS 环境设计,故意跳过 Windows 系统,并专门枚举 AWS、Azure 和 Google Cloud Platform 的密钥。这种选择性攻击表明攻击者对目标环境有明确的偏好,可能是为了提高攻击成功率或避开特定的安全检测机制。
自我复制机制的实现
Shai-Hulud 蠕虫最独特的特性是其自我复制和传播能力。当开发者安装受感染的包时,恶意软件会在环境中寻找 NPM 令牌。如果找到令牌,它会修改该令牌有权访问的 20 个最流行的包,将自身代码复制到这些包中,并发布新版本。
这种自我复制机制通过以下步骤实现:
凭证搜索与验证:恶意代码使用 TruffleHog 工具扫描系统中的 .npmrc 文件,寻找有效的 NPM 令牌。找到令牌后,会通过 whoami 端点验证其有效性和权限范围。
目标包选择:恶意代码会查询该令牌可访问的所有 NPM 包,并根据下载量等指标选择最流行的 20 个包作为传播目标。
代码注入与发布:对于每个目标包,恶意代码会从 npm 下载当前版本的受感染包,将子版本号加 1,添加指向 postinstall 钩子的链接,将自身副本写入 bundle.js 文件,将这个被植入木马的"新版本"包发布到 npm。
持久化机制:除了感染 NPM 包外,恶意代码还会写入一个名为 shai-hulud-workflow.yml 或 shai-hulud.yaml 的 GitHub Actions 工作流文件到目标仓库的.github/workflows 目录。一旦提交,这个工作流会在未来的 CI 运行中持续触发,从而实现持久化。
这种多层次的传播机制创造了一种级联效应:一个受感染的包会导致维护者凭证被泄露,进而感染该用户维护的所有其他包。这使得 Shai-Hulud 蠕虫能够在短时间内实现指数级传播,成为迄今为止观察到的最严重的 JavaScript 供应链攻击之一。
数据外泄机制
Shai-Hulud 蠕虫采用了一种主要方式窃取数据:在受害者的 GitHub 账户下创建名为"Shai-Hulud"或"Shai-Hulud Migration"的公共仓库,并在那里发布被盗数据。
恶意软件使用窃取的 GitHub 令牌以受害者身份创建这些公共仓库,将收集到的密钥和系统信息上传为 JSON 文件。同时,它还会创建新的 GitHub 工作流(github/workflows/shai-hulud-workflow.yml),该工作流将收集的密钥编码为 JSON 并可能传输到远程服务器。此外,攻击者还会将受害者的私有仓库标记为公开,造成更严重的信息泄露。
卡巴斯基的分析也提到,攻击者可能通过 GitHub Actions 工作流将数据传输到 webhook.site 服务器,但目前尚未在其他技术报告中找到具体的硬编码端点信息。
NPM 供应链攻击的演进:从 qix 到 Shai-Hulud
qix 事件(2025 年 9 月 8 日)
在 Shai-Hulud 蠕虫出现前一周,已有一起NPM供应链投毒事件发生。攻击者通过网络钓鱼攻击入侵了 NPM 包维护者 JoshJunon(用户名 qix)的账户,并在多个高下载量的 NPM 包中注入了恶意软件。
攻击者使用了伪装成合法 npmjs.com 域名的钓鱼网站,向维护者发送威胁邮件,声称如果维护者不点击链接更新其双重认证,账户将被锁定。这种社会工程学攻击手段成功诱导开发者输入了账户凭证,从而使攻击者获取了对其 NPM 账户的完全控制权。
qix 事件中的恶意代码主要针对加密货币交易进行监控和劫持。恶意代码作为基于浏览器的拦截器被注入到 index.js 文件中,能够劫持网络流量和应用程序 API,监控加密货币地址和交易,并将这些交易重定向到攻击者控制的钱包地址。
这次攻击影响了包括 debug、chalk 和 supports-color 等在内的 18 个流行软件包,这些受影响的 NPM 包每周总下载量超过 26 亿次,影响范围极其广泛。
valorkin 和 scttcper 事件(2025 年 9 月 15 日)
就在 qix 事件一周后,另一起严重的 NPM 组件投毒事件发生了,影响了两位知名开发者维护的近 40 个开源组件。这次攻击针对开发者 valorkin(维护 86 个开源项目)和 scttcper(维护 54 个开源项目)的账户进行了凭证窃取,并在他们维护的热门组件中植入了恶意代码。
虽然没有公开资料明确说明 valorkin 和 scttcper 的账户是如何被入侵的,但考虑到时间接近性和攻击模式相似性,很可能也是通过类似 qix 事件中使用的钓鱼邮件方式。
攻击者在组件源码中直接植入混淆恶意文件 bundle.js,其主要功能是在组件安装过程中静默窃取受害者系统平台信息、环境变量数据以及主流业务(包括 NPM、Github、AWS 及 GCP 等)的 token 密钥。攻击者在 package.json 文件中添加了 postinstall 指令,这是一种常见的供应链攻击技术。当用户通过 npm install 安装该组件时,会自动执行 bundle.js 文件。
受影响的组件包括 ngx-bootstrap、ng2-file-upload 和@ctrl/tinycolor 等,这些组件的历史总下载量超过亿次,影响范围极其广泛。
Shai-Hulud 蠕虫攻击(2025 年 9 月 15 - 16 日)
Shai-Hulud 蠕虫攻击在 valorkin 和 scttcper 事件的同一天开始爆发,这表明它可能是从这些被入侵的账户开始传播的。首个被该蠕虫修改的 NPM 包似乎是在 2025 年 9 月 14 日 17:58 UTC 左右被更改的。
与前两次攻击不同,Shai-Hulud 蠕虫增加了自我复制和传播能力,这是前两次攻击所不具备的。这种能力使得攻击范围能够呈指数级扩大,从最初的几个包迅速扩散到数百个包。
三起事件的对比分析与归因
相似之处
时间接近性:三起事件在 2025 年 9 月 8 日至 16 日的短短一周多时间内相继发生,表明可能是同一攻击者或攻击组织的连续行动。
攻击目标选择:三起事件都针对了维护多个高下载量 NPM 包的知名开发者,表明攻击者有意识地选择影响范围最大的目标。
供应链攻击模式:三起事件都属于典型的供应链攻击,通过入侵上游开发者账户,向其维护的组件中植入恶意代码,从而影响下游用户。
使用 postinstall 钩子:所有攻击都利用了 NPM 的 postinstall 钩子机制,使得当用户安装这些组件时,自动执行混淆后的恶意代码。
差异与技术演进
恶意代码功能:qix 事件中的恶意代码主要针对加密货币交易进行监控和劫持,而 valorkin/scttcper 事件和 Shai-Hulud 蠕虫则专注于窃取系统信息和各类服务的 token。
技术复杂度:从 qix 事件到 valorkin/scttcper 事件,再到 Shai-Hulud 蠕虫,攻击的技术复杂度呈现明显的上升趋势。valorkin/scttcper 事件中使用的技术明显更为复杂,包括利用 TruffleHog 工具、通过 GitHub 仓库进行数据外传等创新手法,而 qix 事件中的恶意代码相对简单。
自我复制能力:Shai-Hulud 蠕虫增加了自我复制和传播能力,这是前两次攻击所不具备的。这种能力使得攻击范围能够呈指数级扩大,从最初的几个包迅速扩散到数百个包。
影响范围:qix 事件影响的组件每周下载量达 26 亿次,而 valorkin/scttcper 事件影响的组件历史总下载量为亿级,Shai-Hulud 蠕虫则影响了至少 187 个 NPM 包。虽然 qix 事件的潜在影响范围最大,但 Shai-Hulud 蠕虫的自我复制能力使其实际危害可能更为严重。
归因分析
基于三起事件的相似性和技术演进路径,我们可以提出以下归因假设:
同一攻击者或组织:三起事件很可能是由同一攻击者或攻击组织实施的。时间接近性、攻击手法的相似性以及技术的逐步演进都支持这一假设。卡巴斯基的分析也指出,Shai-Hulud 攻击模式与近期 s1ngularity 事件类似。
技术能力提升:攻击者展示了快速学习和技术迭代的能力。从最初的简单钓鱼和加密货币劫持,到复杂的凭证窃取和数据外传,再到具有自我复制能力的蠕虫,攻击者的技术水平在短时间内显著提升。
目标转变:攻击者的目标似乎从直接的经济利益(劫持加密货币交易)转变为更广泛的信息收集和基础设施控制(窃取各类服务的 token 和凭证)。这可能表明攻击者的动机发生了变化,或者是为了实现更长期、更复杂的攻击计划。
防御建议
针对此类供应链攻击,建议采取以下防御措施:
对开发者的建议
立即检查并更新受影响组件:使用 npm list ngx-bootstrap 或 npm list -g ngx-bootstrap 检查是否安装了受影响版本,如有则立即回滚到安全版本。
启用双因素认证:为 NPM、GitHub 等账户启用双因素认证,降低账户被盗风险。
定期轮换凭证:定期更换开发环境中使用的各类 token 和密钥,限制潜在泄露的影响范围。
使用锁文件固定依赖版本:使用 package-lock.json 或 yarn.lock 锁定依赖版本,避免自动更新到可能被投毒的新版本。
对企业的建议
建立私有 NPM 仓库:使用 Nexus、Artifactory 等工具建立企业私有 NPM 仓库,对外部包进行安全审查后再引入。
实施供应链安全监控:部署如 OpenSCA-cli 等工具,对项目依赖进行持续安全监控。
制定应急响应计划:针对供应链攻击制定专门的应急响应流程,包括检测、隔离、修复和恢复等步骤。
进行开发环境隔离:将开发环境与生产环境严格隔离,限制开发环境中的凭证权限范围。
等待更新期:考虑在新版本发布后等待约两周时间再进行开源软件包的更新,因为在这段时间内,软件包劫持攻击通常会被察觉到,恶意版本会被移除或修复。
结论
2025 年 9 月的 NPM 供应链攻击系列事件展示了现代供应链攻击的复杂性和危险性。从 qix 事件的简单钓鱼和加密货币劫持,到 valorkin/scttcper 事件的复杂凭证窃取,再到 Shai-Hulud 蠕虫的自我复制和传播,攻击者的技术能力和攻击范围不断扩大。这三起事件很可能是由同一攻击者或攻击组织实施的,展示了其快速学习和技术迭代的能力。
这些攻击凸显了开源软件供应链的脆弱性,以及保护开发者账户和凭证的重要性。对于开发者和企业来说,启用双因素认证、定期轮换凭证、使用锁文件固定依赖版本、建立私有 NPM 仓库等措施变得尤为重要。同时,NPM 等平台也应考虑切换到需要明确人工同意的发布模式,使用防钓鱼的双因素认证方法,以增强整个生态系统的安全性。
随着开源软件在现代应用开发中的重要性不断增加,类似 Shai-Hulud 这样的供应链攻击将继续成为网络安全领域的重大挑战。只有通过行业协作、改进安全实践和提高开发者安全意识,我们才能更有效地应对这些威胁。
附录:Shai-Hulud 蠕虫 IOC 和受影响包列表
IOC 列表
恶意文件名: bundle.js - 主要恶意脚本文件 shai-hulud-workflow.yml / shai-hulud.yaml - GitHub Actions 恶意工作流文件
GitHub 仓库命名模式: "Shai-Hulud" - 用于数据外泄的仓库名 "Shai-Hulud Migration" - 用于持久化或分阶段执行的仓库名
行为指标: 下载并执行 TruffleHog 工具 在 package.json 中添加 postinstall 钩子 创建未授权的 GitHub Actions 工作流 创建名为"Shai-Hulud"的 GitHub 仓库
受影响的 NPM 包(部分列表)
@crowdstrike/commitlint@8.1.1, 8.1.2
@crowdstrike/falcon-shoelace@0.4.2
@crowdstrike/foundry-js@0.19.2
@crowdstrike/glide-core@0.34.2, 0.34.3
@crowdstrike/logscale-dashboard@1.205.2
@crowdstrike/logscale-file-editor@1.205.2
@crowdstrike/logscale-parser-edit@1.205.1, 1.205.2
@crowdstrike/logscale-search@1.205.2
@crowdstrike/tailwind-toucan-base@5.0.2
browser-webdriver-downloader@3.0.8
ember-browser-services@5.0.3
ember-headless-form-yup@1.0.1
ember-headless-form@1.1.3
ember-headless-table@2.1.6
ember-url-hash-polyfill@1.0.13
ember-velcro@2.2.2
eslint-config-crowdstrike-node@4.0.4
eslint-config-crowdstrike@11.0.3
monorepo-next@13.0.2
remark-preset-lint-crowdstrike@4.0.2
verror-extra@6.0.1
yargs-help-output@5.0.3
声明:本文来自奇安信威胁情报中心,版权归作者所有。文章内容仅代表作者独立观点,不代表安全内参立场,转载目的在于传递更多信息。如有侵权,请联系 anquanneican@163.com。