免费获取学习方案
ARTICLE DETAIL

资讯详情

深耕编程基础知识与建站技术分享的一线实战洞察。

用 Fleet 检测 Mini Shai-Hulud npm 供应链蠕虫:从感染链拆解到双层检测实战

用 Fleet 检测 Mini Shai-Hulud npm 供应链蠕虫:从感染链拆解到双层检测实战 用 Fleet 检测 Mini Shai-Hulud npm 供应链蠕虫从感染链拆解到双层检测实战【免费下载链接】fleetOpen device management项目地址: https://gitcode.com/GitHub_Trending/fl/fleet2026 年 5 月npm 官方源遭到一次活跃的供应链蠕虫攻击TanStack 的 42 个包、84 个版本被植入后门另有 175 个包、跨 17 个命名空间被波及。攻击者通过劫持 CI 的 OIDC 令牌绕过 2FA 与签名校验在npm install时静默 fork 后台守护进程窃取开发者凭证再以盗用的维护者身份向 npm 重新发布恶意版本。本文基于 Fleet 安全团队使用 Fleet 平台在自身 30 台主机上执行检测的完整记录还原感染链、双层检测方案SQL 实时查询 深扫脚本、完整 IOC 清单与分阶段应急响应手册并深入解析npm_packages表的覆盖盲区——这是大多数只依赖签名校验与软件清单的团队最容易忽视的检测缺口。核心要点速览安装一切正常正是整个攻击的关键Mini Shai-Hulud 在npm install期间 fork 并脱离终端开发者看到的是完全正常的安装输出后台却有一个守护进程在悄悄收割凭证。隐藏它的行为恰恰也是检测它的抓手。签名有效不代表包是安全的蠕虫通过合法维护者的 OIDC 令牌发布因此其 Sigstore 证明attestation全部有效双因素认证也形同虚设。信任必须从签名延伸到行为。Fleet 提供两层检测实时查询live queries可在数秒内完成全舰队暴露面检查通过 Fleet 的 run-script 运行的深扫脚本则提供逐主机的文件系统级覆盖。两者互补必须同时运行。npm_packages表只能看到全局安装它不会进入项目级node_modules/目录——而被攻陷的包恰恰住在这里。一个拥有 20 个受感染项目的开发者可能返回 0 行。文件系统扫描补上了这个缺口。检测覆盖所有开发者所在平台查询与脚本同时适配 Linux、macOS 和 Windows一次狩猎覆盖整个舰队与操作系统无关。先轮换凭证再做取证如果受影响的包在过去一周内接触过某台机器请默认凭证已经泄露。响应手册的第一步是在分钟而不是小时量级内完成 DNS 封禁与凭证轮换。事件回顾一次 OIDC 令牌劫持引发的连锁感染TanStack/router 仓库中一个无人维护的遗留提交orphaned commit让攻击者劫持了 CI 工作流的 OIDC 令牌。这个凭证绕过直接穿透了两因素认证和 npm 的发布保护机制攻击者借此将一个 2.3 MB 的载荷router_init.js以 post-install 钩子的形式注入到数十个合法包中。npm install时的完整感染链如下通过 postInstall 钩子执行router_init.js。进程 fork、与终端脱离并立即交还控制权——安装过程看起来一切正常。守护进程按顺序收割凭证GitHub Actions OIDC 令牌、AWSIMDSv2、Secrets Manager、跨区域 SSM、HashiCorp Vault、Kubernetes 服务账户。蠕虫使用窃取的维护者身份向 npm 重新发布恶意版本。通过在.claude/和.vscode/目录中投放钩子实现持久化。数据外带通过 Session 的 P2P 网络传输到filev2.getsession[.]org。通过 GitHub GraphQL API 提交仓库 commit并将作者伪造成claudeusers.noreply.github.com。为什么这次攻击不一样大多数恶意 post-install 脚本是同步执行的并且会把输出泄露到终端。这个变种选择了 fork 后脱离——这是最关键的行为差异。开发者看到一次干净的安装构建日志里没有任何异常迹象。Mini Shai-Hulud 的其他几个特征同样值得标记Sigstore 证明提供的是虚假的安全感。恶意软件通过合法维护者的 OIDC 令牌发布因此它生成的来源证明provenance attestation是有效的。签名校验无法区分被攻陷的凭证和真实的凭证。OIDC 传播绕过了 2FA。蠕虫用已签发的令牌重新发布而不是用密码。一旦令牌落入攻击者手中双因素认证便不再提供任何保护。去中心化的命令与控制C2。通过 Session 的 P2P 网络外带数据意味着没有任何单一 IP 或域名能干净地回溯到攻击者。DNS 封禁filev2.getsession[.]org是必要的但远不充分。开发者工具链成为持久化通道。瞄准.claude/和.vscode/是蓄意为之这些目录跨项目存活且紧邻高权限凭证。此外Socket.dev 对这次攻击的报告指出了两个即使在官方公告发布之前也很有用的深度检测指标PBKDF2 盐值svksjrhjkcejg以及恶意package.json中出现的字符串IfYouRevokeThisTokenItWillWipeTheComputerOfTheOwner。我们用 Fleet 检测它的方法双层检测Fleet 安全团队对舰队中的每台主机都执行了两层检测且两层同时运行第 1 层实时查询live queries。快速的舰队级 SQL 扫描用于暴露受感染的全局包、持久化文件、活跃恶意进程以及已知 C2 连接。结果在数秒内返回。Fleet 通过 osquery 分发实时查询服务端会在distributed/read轮询中唤醒命中的主机并下发live-campaign ID查询任务相关实现见 server/service/osquery.go。第 2 层run-script 深扫脚本。逐主机的全面文件系统分析补上 SQL 看不到的部分——尤其是安装在每个项目node_modules/目录里的被攻陷包。每台主机大约 30 秒完成。两层缺一不可原因如下。npm_packages表的覆盖盲区Fleet 代理查询npm_packages表时只统计全局安装的包默认路径类似~/.npm-global、/usr/local/lib/node_modules、/opt/homebrew/lib/node_modules。它不会进入项目本地的node_modules/目录。这一点可以从仓库内置的软件清单查询得到印证在 docs/queries.yml 的 Linux 内置查询中npm 包来自SELECT name, version, npm_packages AS source, ... FROM npm_packages配合全局目录扫描实现docs/01-Using-Fleet/standard-query-library/standard-query-library.yml 中Get installed Linux software标准报告同样把 npm 包来源映射到npm_packages表。而npm_packages表本质上是 osquery 对全局node_modules树的枚举不会递归项目级依赖。现实中几乎没有人全局安装 npm 包。一个拥有 20 个活跃项目的开发者如果每个项目的node_modules/里都装着被攻陷的tanstack/react-router1.169.8那么对该主机的npm_packages查询将返回 0 行。SQL 查询给你一个快速的全局暴露检查。脚本给你完整的可见性。两者都需要。深扫脚本正是为了填补这个缺口它们使用find ... -maxdepth 10 -type d -name node_modules枚举用户主目录下的每一个node_modules/目录然后将每个依赖树与完整的受攻陷版本清单逐一校验。Fleet SQL 实时查询三层指标分类Fleet 安全团队交付了三个平台专属的 SQL 文件Linux、macOS、Windows通过UNION ALL组合多种指标类别并为每条结果打上严重级别标签EXPOSURE_global_pkg_version - 全局 npm 树中存在受攻陷版本 CRITICAL_persistence_* - 存在 systemd 服务、LaunchAgent 或载荷文件 CRITICAL_active_payload_* - 恶意进程正在运行 HIGH_persistence_editor_hook - 存在 .claude/ 或 .vscode/ 钩子查询覆盖的范围包括直接受攻陷的42 个 TanStack 包、84 个版本。通过共享载荷 SHA256、C2 域名和攻击标记识别出的、来自更广泛 Mini Shai-Hulud 行动的另外 133 个包、322 个版本。tanstack/setup——任何版本都被标记为伪造包。常见安装位置含 NVM下的载荷文件路径。命令行中带有router_init.js、router_runtime.js、tanstack_runner.js的活跃进程检测。Linux 上的 systemd 用户服务gh-token-monitor.service以及 macOS 上对应的com.user.gh-token-monitor.plistLaunchAgent。.claude/和.vscode/中的编辑器钩子。深扫脚本七阶段全盘文件系统分析mini_shai_hulud_scan_fleet_deep.shLinux/macOS与mini_shai_hulud_scan_windows.ps1Windows顺序执行超时上限为 300 秒。两者遵循相同的七个阶段阶段检查项具体内容1系统持久化systemd 用户服务与 LaunchAgent2载荷文件按 SHA256 在 home 与全局路径中查找router_init.js和tanstack_runner.js3编辑器钩子.claude/router_runtime.js、.claude/setup.mjs、.vscode/setup.mjs4本地 npm 包递归检查每一个node_modules/目录5Git 死信箱提交伪造作者claudeusers.noreply.github.com、voicproducoes账号、恶意提交哈希6攻击标记PBKDF2 盐值svksjrhjkcejg、package.json中的攻击字符串、恶意提交引用7工作流注入扫描.github/workflows/*.yml中的toJSON(secrets)、C2 域名、__DAEMONIZED、router_init每次运行返回四种退出码之一语义明确方便接入自动化0CLEAN未发现任何指标。1EXPOSED存在受攻陷的包但没有执行证据。2HIGH发现编辑器钩子持久化。3CRITICAL很可能存在载荷文件或系统持久化产物。在 Fleet 中通过 run-script 执行这类脚本时可以参考脚本执行机制的实现约束Fleet 为单次脚本执行设置了 5 分钟的最大执行时长MaxHostExecutionTime服务端同步等待的窗口为 5 分钟加 1 分钟MaxServerWaitTime超时会返回Timeout. Fleet stopped the script...的提示见 pkg/scripts/scripts.go 与 server/service/integration_enterprise_test.go。300 秒的深扫超时正是为贴合这一上限而设计。另外全局禁用脚本时 Fleet 会直接拒绝执行ScriptsDisabled配置见 server/service/scripts.go运行前需确认组织未在服务端设置中关闭脚本功能。我们舰队中的实测结果在 24 台 Linux 与 macOS 主机上每台脚本都以退出码 0干净完成且全覆盖。代表性的结尾输出[*] Phase 6 - campaign markers in package.json Scanning package.json files in /root... [OK] no campaign markers found [*] Phase 7 - injected GitHub workflows [OK] no malicious workflows found SUMMARY (hostautomater duration31s) CRITICAL findings: 0 HIGH findings: 0 EXPOSURE findings: 0 VERDICT: CLEAN, no indicators found在 Windows 侧五台目标主机中的四台DC01、DC02、WIN10-1、WRK-AI干净完成另有一台在采集结果时仍在执行中。失陷指标IoC清单主指标指标值或模式恶意文件router_init.jsSHA256ab4fcadaec...601266cRunner 文件tanstack_runner.jsSHA2562ec78d5...e27fc96伪造包tanstack/setup任何版本一律视为恶意活跃进程命令行中出现运行router_init.js的node进程C2 外带已确认filev2.getsession[.]orgC2 外带已报告api.masscan.cloud、litter.catbox.moe伪造作者claudeusers.noreply.github.com持久化位置平台路径Linux~/.config/systemd/user/gh-token-monitor.serviceLinux~/.local/bin/gh-token-monitor.shmacOS~/Library/LaunchAgents/com.user.gh-token-monitor.plist全平台~/.claude/router_runtime.js、~/.claude/setup.mjs全平台~/.vscode/setup.mjs高影响受攻陷版本包恶意版本tanstack/react-router1.169.5、1.169.8tanstack/router-core1.169.5、1.169.8tanstack/react-start1.167.68、1.167.71tanstack/router-plugin1.167.38、1.167.41mistralai/mistralai2.2.2、2.2.3、2.2.4opensearch-project/opensearch3.5.3、3.6.2、3.7.0、3.8.042 个 TanStack 包直接受影响。Fleet 的查询还覆盖了更广泛攻击行动中的 175 个额外包。应急响应手册15 分钟内在解析器与防火墙上封禁到filev2.getsession[.]org和api.masscan.cloud的 DNS 出口。在开始调查前先阻断外带。将 SQL 查询作为 Fleet 实时查询部署到每个端点。隔离任何返回 CRITICAL 结果的主机退出码 3 或存在活跃进程。按此顺序轮换凭证npm 令牌、GitHub PAT、AWS、Vault、Kubernetes。1 小时内通过 Fleet run-script 部署深扫脚本。SQL 覆盖全局包脚本覆盖磁盘上每一个node_modules/目录。审计 git 历史中作者为claudeusers.noreply.github.com或voicproducoes账号的提交。检查 CI/CD 工作流文件中是否有toJSON(secrets)、getsession.org和router_init。24 小时内对过去 7 天内安装过受影响包的任何机器主动轮换凭证即使扫描结果是干净的——恶意软件可能已经完成了外带。审计 npm 发布日志检查组织包是否有异常发布。将 GitHub Actions 引用固定为提交 SHA而不是标签。我们带走的经验教训仅凭 Sigstore 来源证明不够。有效签名无法检测 OIDC 令牌失陷——凭证本身就是合法的。信任必须从签名延伸到行为。post-install 钩子仍是高风险的攻击面。它们以用户权限执行而在开发者机器或 CI runner 上这种权限对于它们实际做的工作来说高得离谱。开发者工具目录是优质目标。攻击者总是去凭证聚集的地方。把.claude/、.vscode/及类似配置路径当作敏感面而不是个人偏好。本地node_modules/扫描是强制项。npm_packages表很快、很有用但不能单独依赖。文件系统级分析必须成为检测计划的一部分。轮换先于取证。如果受影响包在过去一周内落在某台机器上请默认凭证已经泄露。轮换时钟应该以分钟计而不是小时。延伸阅读想在自己的舰队中复现这套检测可以进一步研读本仓库中的相关材料Fleet 内置软件清单查询的完整 SQL 定义见 docs/queries.yml标准查询库中的软件报告见 docs/01-Using-Fleet/standard-query-library/standard-query-library.yml脚本执行与超时机制的实现见 pkg/scripts/scripts.go 和 server/service/scripts.go实时查询分发逻辑见 server/service/osquery.go。若你的组织同时存在其他 AI 工具与 MCP 滥用风险docs/solutions/all/queries/openclaw-detection.queries.yml 中的 openclaw 检测查询也提供了同类思路。【免费下载链接】fleetOpen device management项目地址: https://gitcode.com/GitHub_Trending/fl/fleet创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表