CyberDracula/shai-hulud-2-scanner
GitHub: CyberDracula/shai-hulud-2-scanner
一款针对 Shai-Hulud 系列 npm 供应链攻击的取证审计工具,通过 IOC 匹配和行为启发式分析扫描本地缓存、全局安装目录和项目依赖。
Stars: 28 | Forks: 6
# Shai-Hulud 1.0/2.0 恶意软件扫描器
[](https://github.com/CyberDracula/shai-hulud-2-scanner/releases)
[](https://nodejs.org/)
[](LICENSE)
[](https://github.com/CyberDracula/shai-hulud-2-scanner)
[](package.json)
[](CHANGELOG.md#200---2025-12-01)
[](package.json)
[](scan.js)
[](https://github.com/CyberDracula/shai-hulud-2-scanner/commits/main)
一款旨在检测 Shai-Hulud 1.0/2.0(及相关)npm 供应链攻击的取证审计工具。它根据 Wiz Research 提供的 IOC(失陷指标)扫描本地缓存、全局安装目录和项目目录。
## 🛡️ 安全加固 (v2.0.0)
Shai-Hulud Scanner 现包含高级安全防护:
- **符号链接与路径遍历保护:** 防止扫描过程中出现恶意符号链接和目录逃逸。
- **资源限制:** 强制执行最大内存、文件数量和扫描持续时间限制,以避免资源耗尽。
- **CSV 注入防御:** 所有 CSV 报告均经过净化处理,以防止公式/代码注入。
- **敏感数据脱敏:** 报告中绝不包含 API 密钥、用户信息和机密信息。
- **优雅关机:** 如果被中断,将生成包含截止当时所有发现的部分报告。
阅读此处了解更多信息:https://www.wiz.io/blog/shai-hulud-2-0-ongoing-supply-chain-attack
## 🚀 特性
* **零依赖:** 运行于标准 Node.js (v14+)。无需 'npm install'。一分钟内即可审计完代码。
* **双重威胁情报:** 自动与两个 IOC 源同步:
* [Wiz Research](https://github.com/wiz-sec-public/wiz-research-iocs) - 官方 Shai-Hulud 2.0 软件包 (CSV)
* [Hemachandsai Malicious Packages](https://github.com/hemachandsai/shai-hulud-malicious-packages) - 扩展黑名单 (JSON)
* **智能缓存:** IOC 数据缓存 30 分钟,以减少网络请求。如果网络不可用,自动回退到离线数据。
* **深度 NVM 支持:** 自动检测 NVM 安装 和每个已安装的 Node 版本。
* **取证扫描:** 检查物理恶意软件文件(setup_bun.js, bun_environment.js),无论版本号如何。
* **元数据扫描:** 根据实时威胁情报源验证已安装的软件包。
* **幽灵检测:** 对匹配目标软件包名称的空/损坏目录(潜在的失败恶意软件安装)发出警报。
* **企业级报告:** 生成经过净化的 CSV 报告,并具有可选的集中上传功能供组织使用。
* **不区分大小写检测:** 无论文件名大小写如何,均标记恶意软件。
* **扫描统计:** 报告扫描的文件总数、扫描持续时间和摘要统计信息。
* **内置帮助系统:** 使用 `--help` 运行以获取使用说明。
* **环境变量配置:** 可以通过环境变量设置 API 密钥和上传 URL,以实现安全的自动化。
## 📋 前置条件
* Node.js:已安装并在 PATH 中可用。
* 互联网连接:需要从以下位置获取最新的 IOC 列表:
* Wiz Research IOC 仓库
* Hemachandsai 恶意软件包数据库
## 🛠️ 安装
1. 将 `scan.js` 下载到集中文件夹。
2. 立即运行 —— 无需安装!
## 🏃 使用方法
你可以直接使用 Node 运行脚本,或使用提供的辅助脚本。
### 全系统扫描(默认)
扫描所有系统缓存(npm, Yarn, pnpm, NVM)和当前目录。**仅生成本地 CSV 报告。**
```
node scan.js
```
### 仅项目扫描
传递一个路径以**仅扫描该特定项目目录**(跳过系统缓存以加快扫描速度):
```
node scan.js C:\Projects\MyApp
or
node scan.js /home/user/projects/myapp
```
### 带自定义路径的全系统扫描
要同时扫描系统缓存和特定目录,请使用 `--full-scan` 标志:
```
node scan.js C:\Projects\MyApp --full-scan
or
node scan.js /home/user/projects/myapp --full-scan
```
### 高级选项
**绕过缓存(强制重新下载)**
IOC 数据缓存 30 分钟。要强制重新下载:
```
node scan.js --no-cache
```
**通过环境变量设置 API 密钥/上传 URL**
为了安全的自动化,你可以设置以下环境变量:
```
export SHAI_HULUD_API_KEY="your-secure-api-key"
export SHAI_HULUD_UPLOAD_URL="https://your-company-api.example.com/upload"
```
这些将覆盖 `scan.js` 中的默认值,推荐用于 CI/CD。
#### 限制目录遍历深度
控制扫描器遍历目录的深度(默认值:5)。有助于加快扫描速度或聚焦于本地:
```
node scan.js --depth=3
node scan.js C:\Projects\MyApp --full-scan --depth 7
```
注意:
* 接受 `--depth=` 或 `--depth ` 格式
* 适用于仅项目模式和全系统扫描模式
#### CI/CD 集成(退出代码)
根据发现严重性控制扫描器何时使构建失败。默认情况下,扫描器始终以代码 0 退出。使用 `--fail-on` 启用 CI/CD 模式:
```
node scan.js /path/to/project --fail-on=critical
node scan.js /path/to/project --fail-on=warning
node scan.js /path/to/project --fail-on=off
```
**模式:**
* `--fail-on=critical`:仅在发现 **CRITICAL**(严重)问题时以退出代码 1 退出 (FORENSIC_MATCH, CRITICAL_SCRIPT, VERSION_MATCH, WILDCARD_MATCH, LOCKFILE_HIT, WILDCARD_LOCK_HIT)
* `--fail-on=warning`:在发现 **CRITICAL**(严重)或 **WARNING**(警告)问题时以退出代码 1 退出(包括 SCRIPT_WARNING, GHOST_PACKAGE, CORRUPT_PACKAGE)
* `--fail-on=off`:始终以退出代码 0 退出(仅报告,从不使构建失败)
**Jenkins 示例:**
```
stage('Security Scan') {
steps {
sh 'npx @cyberdracula/shai-hulud-2-scanner /path/to/project --fail-on=critical'
}
}
```
**GitHub Actions 示例:**
```
- name: Scan for Supply Chain Attacks
run: npx @cyberdracula/shai-hulud-2-scanner /path/to/project --fail-on=critical
```
**GitLab CI 示例:**
```
security_scan:
script:
- npx @cyberdracula/shai-hulud-2-scanner /path/to/project --fail-on=critical
```
### 可选:组织报告
**仅适用于公司/组织:** 如果你想在多台机器之间集中汇总扫描结果,可以配置自动报告上传:
1. 在 `scan.js` 顶部编辑配置:
const UPLOAD_API_URL = 'https://your-company-api.example.com/upload';
const API_KEY = 'your-secure-api-key';
2. 正常运行扫描 —— 报告将自动上传。
3. 要禁用上传并仅生成本地 CSV:
node scan.js --no-upload
## ✅ 已知误报(可安全忽略)
React Native 项目:ios/ 文件夹中的 contents.json 文件是标准的 iOS 资产目录文件(Xcode 资源),而非恶意软件指标。这些可以安全忽略。
## 解读报告 (shai-hulud-report.csv)
该工具将发现分类为不同的严重级别。理解每一项的含义对于正确响应至关重要。
| 发现类型 | 严重性 | 描述 | 所需操作 |
|-------------|----------|-------------|-----------------|
| **FORENSIC_MATCH** | 🔴 **CRITICAL** | 发现高置信度恶意软件文件(setup_bun.js, bun_environment.js, truffleSecrets.json, actionsSecrets.json, .github/workflows/discussion.yml),无需内容验证 | ⚠️ **系统已失陷。** 请参阅下方的紧急响应步骤。 |
| **FORENSIC_ARTIFACT** | 🟠 **HIGH** | 检测到可疑文件(bundle.js, contents.json, cloud.json, environment.json),经深度检查后匹配恶意内容特征 | 调查文件来源。如果是合法的(例如 React Native contents.json),标记为安全。否则,立即移除。 |
| **WILDCARD_MATCH** | 🔴 **CRITICAL** | 软件包匹配严格黑名单,其中所有版本均为恶意。 | ⚠️ **立即删除。** 遵循下方的补救步骤。 |
| **CRITICAL_SCRIPT** | 🔴 **CRITICAL** | Install/preinstall/postinstall 脚本包含高置信度恶意行为(例如将远程代码管道传输到 shell,base64→sh 链,特权 Docker 标志,工作流后门文件) | ⚠️ **需要行动** 视为事件:隔离主机,移除软件包,轮换凭证,调查横向移动。 |
| **VERSION_MATCH** | 🟠 **HIGH** | 软件包名称和版本匹配已知感染列表 | 卸载软件包。检查 lockfile。清除缓存。 |
| **LOCKFILE_HIT** | 🟠 **HIGH** | 恶意版本被锁定在 package-lock.json/yarn.lock 中 - 每次运行 `npm install` 时都会自动安装 | ⚠️ **对 CI/CD 至关重要。** 删除 lockfile,移除软件包,重新生成。 |
| **WILDCARD_LOCK_HIT** | 🟠 **HIGH** | Lockfile 包含已知恶意软件的依赖项(任何版本)。 | 删除 lockfile,移除依赖项,使用安全版本重新生成。 |
| **GHOST_PACKAGE** | 🟡 **WARNING** | 存在具有目标名称的文件夹,但为空/已损坏 | 手动调查。可能是安装失败或清理残留物。 |
| **SCRIPT_WARNING** | 🟡 **WARNING** | Install/preinstall/postinstall 脚本具有可疑指标(例如通过 Buffer/Base64 混淆,动态 Function(),GitHub API/artifact 使用,`nc`/`socat`) | 审查并验证脚本意图。如果不是业务关键,移除或固定安全版本;提出安全工单。 |
| **SAFE_MATCH** | 🔵 **INFO** | 软件包名称匹配目标,但版本安全 | 无需操作。记录仅用于审计目的。 |
### 行为启发式(安装脚本扫描器)
扫描器分析常见的生命周期钩子(`preinstall`、`install`、`postinstall`、`prepublish`、`prepare`)并标记:
* 高置信度恶意模式:将远程内容管道传输到 shell,base64→shell 链,Docker `--privileged` 和主机挂载,工作流后门文件
* 可疑指标:通过 `Buffer.from(..., 'hex'|'base64')` 混淆,动态 `Function(...)`,GitHub API/artifact 使用,后门原语(`nc`、`socat`)
* 白名单安全脚本:典型工具,如 `tsc`、`node-gyp`、`prebuild-install`、`opencollective-postinstall`、`electron-builder install-app-deps`、`lerna bootstrap`、`nx/turbo run`、`esbuild`
#### 指标(你可能在 `Issue_Type` 和 `Details` 中看到的内容)
扫描器发出标准化的指标标签以帮助分类:
* `REMOTE_CODE_EXEC`:下载或将远程内容管道传输到 shell;子 shell/反引号 curl/wget;带有网络获取的 `bash -c`
* `OBFUSCATION`:Base64/hex 解码,`String.fromCharCode`,转义序列,打包或编码的 payload
* `CODE_INJECTION`:`eval`,`Function(...)`,直接 `child_process` 执行,同步 exec/spawn 使用
* `SHAI_HULUD`:引用加载器或 payload 制品(`setup_bun`、`bun_environment`、签名令牌)
* `PERSISTENCE`:CI/CD 工作流后门文件(例如 `.github/workflows/discussion.yml`)
* `PRIV_ESC`:Docker `--privileged` 运行或主机文件系统挂载(`-v /:/host`)
* `INSECURE_NETWORK`:安装时脚本中的纯 `http://` 网络调用
* `EXFIL_ATTEMPT`:来自生命周期脚本的 GitHub API 交互或 Actions artifact 上传
* `BACKDOOR_PRIMITIVE`:使用 `nc` 或 `socat` 进行反向 shell 或监听器
### 🚨 紧急响应步骤(如果发现 FORENSIC_MATCH 或 WILDCARD_MATCH)
**你的系统已失陷。恶意软件可能已窃取凭证。**
#### 1. 立即行动
**Windows (PowerShell):**
```
# 停止所有 package managers 和 builds
Stop-Process -Name node, npm, yarn, pnpm -Force -ErrorAction SilentlyContinue
# 清除所有 caches
npm cache clean --force
yarn cache clean --all
pnpm store prune
Remove-Item node_modules -Recurse -Force -ErrorAction SilentlyContinue
```
**macOS/Linux (Bash):**
```
# 停止所有 package managers 和 builds
killall -9 node npm yarn pnpm 2>/dev/null
# 清除所有 caches
npm cache clean --force
yarn cache clean --all
pnpm store prune
rm -rf node_modules
```
#### 2. 检查后门
**Windows (PowerShell):**
```
# 查找恶意 GitHub workflows
Get-ChildItem -Path .github\workflows -Filter "discussion.yaml" -Recurse -ErrorAction SilentlyContinue
Get-ChildItem -Path .github\workflows -Filter "formatter_*.yml" -Recurse -ErrorAction SilentlyContinue
```
**macOS/Linux (Bash):**
```
# 查找恶意 GitHub workflows
find .github/workflows -name "discussion.yaml" 2>/dev/null
find .github/workflows -name "formatter_*.yml" 2>/dev/null
```
**检查自托管运行器(名为 "SHA1HULUD"):**
访问:`https://github.com///settings/actions/runners`
#### 3. 轮换所有凭证(假设已泄露)
恶意软件针对以下机密:
- **GitHub:** 个人访问令牌、部署密钥、Actions secrets
- **云提供商:** AWS 凭证 (AKIA 密钥)、GCP 服务账号、Azure 令牌
- **包管理器:** npm 令牌registry 凭证
- **环境变量:** 所有 API 密钥、数据库密码、服务令牌
- **SSH 密钥:** 重新生成受感染机器上的所有 SSH 密钥
#### 4. 搜索泄露的机密
你的凭证可能已发布到公共 GitHub 仓库:
```
# 在 GitHub 上搜索您组织的暴露数据
# 访问:https://github.com/search?q="Shai-Hulud"+OR+"SHA1-HULUD"+""&type=repositories
```
**⚠️ 跨受害者泄露:** 你的机密可能出现在其他受害者拥有的仓库中。你必须广泛搜索。
#### 5. 清理并重建
**Windows (PowerShell):**
```
# 移除 lockfiles
Remove-Item package-lock.json, yarn.lock, npm-shrinkwrap.json -ErrorAction SilentlyContinue
# 从 package.json 中移除恶意 package(手动编辑)
# 使用安全版本重新安装
npm install
# 验证没有保留恶意软件文件
Get-ChildItem -Recurse -Include setup_bun.js, bun_environment.js, truffleSecrets.json, cloud.json, contents.json, environment.json, actionsSecrets.json
```
**macOS/Linux (Bash):**
```
# 移除 lockfiles
rm -f package-lock.json yarn.lock npm-shrinkwrap.json
# 从 package.json 中移除恶意 package(手动编辑)
# 使用安全版本重新安装
npm install
# 验证没有保留恶意软件文件
find . -type f \( -name "setup_bun.js" -o -name "bun_environment.js" -o -name "truffleSecrets.json" -o -name "cloud.json" -o -name "contents.json" -o -name "environment.json" -o -name "actionsSecrets.json" \)
```
#### 6. CI/CD 流水线审查
**LOCKFILE_HIT 在 CI/CD 环境中尤其危险:**
- 恶意软件在 `preinstall` 期间执行(在你的代码运行之前)
- 在 CI 中同步运行(阻塞直到完成窃取)
- 可能尝试 Docker 提权
- 可以修改 sudoers 以持久化获取 root 访问权限
**操作:** 审查过去 30 天的所有 CI/CD 日志,查找:
- 意外的网络连接
- 失败的提权尝试
- 新注册的 GitHub 运行器
- 异常的工作流执行
### 理解 LOCKFILE_HIT 风险
当在**项目和缓存中**同时发现时,这意味着:
1. **自动重复感染:** 每次运行 `npm install` 都会重新安装恶意软件
2. **团队范围暴露:** 所有克隆仓库的开发者都会被感染
3. **CI/CD 受损:** 每次流水线运行都会执行恶意软件
4. **容器构建:** 每次 Docker 构建都会受损
**Lockfile 充当定时炸弹** —— 恶意软件会不断卷土重来,直到你将其从 lockfile 中移除并轮换所有凭证。
## 🔄 更新离线回退文件
扫描器在 `fallback/` 目录中包含离线回退 IOC 文件。要保持最新:
```
node update-fallbacks.js
```
此实用程序:
- 从两个来源下载最新的威胁情报
- 显示当前文件状态(年龄和大小)
- 更新离线时使用的回退文件
- 定期运行此程序以维护最新的离线数据
## 免责声明
此工具按“原样”提供以协助检测。它依赖于来自 Wiz Research 的公开 IOC。如果恶意软件作者更改文件名或软件包版本,可能会出现漏报。请始终对关键系统执行手动验证。
## 贡献
欢迎贡献!请在 GitHub 仓库上提交 issue 或 pull request。
## 贡献者
特别感谢所有为 Shai-Hulud 2.0 Scanner 项目做出贡献的人:
- MaSMas0 (https://github.com/MaSMas0) — 2.0 版本的安全加固
- Hemachandsai (恶意软件包 IOC 源)
- Wiz Research (威胁情报)
标签:AMSI绕过, GitHub Advanced Security, IOC扫描, IP 地址批量处理, MITM代理, Node.js安全, NPM攻击, Shai-Hulud, TLS, Wiz研究, 取证审计, 威胁检测, 安全加固, 文档安全, 网络信息收集, 网络安全, 自定义脚本, 自定义脚本, 防御工具, 隐私保护, 零依赖