eegeeZA/supply-chain-scanner
GitHub: eegeeZA/supply-chain-scanner
一款专注于 npm 供应链安全事件的主机取证与应急响应扫描器,能够在恶意软件自行清理后依然检测出其执行痕迹。
Stars: 0 | Forks: 0
# supply-chain-scanner


一个用于供应链安全事件的取证与应急响应扫描器。它回答了现有 SCA 工具都未曾解决的一个问题:**这台机器是否受到了攻击,以及还残留了哪些证据?**
诸如 OSV-Scanner、Trivy 和 Grype 等安全通告工具,主要是将您项目中的依赖图与已知的 CVE 数据库进行比对。而本工具则更进一步——它直接检查主机本身的痕迹,这些痕迹甚至在恶意软件自我删除后依然存在。
## 本扫描器的功能
### 其他工具所不具备的三项能力
**GHOST 检测。** 当 npm 安装一个包时,它会在 postinstall 脚本运行_之前_写入一个隐藏的 lockfile(`node_modules/.package-lock.json`)。这意味着即使 postinstall 脚本删除了其自身所在的目录,也无法抹去这条记录。扫描器会将此隐藏的 lockfile 与磁盘上当前的文件进行交叉比对。一个被安装随后又被删除的包将会作为 GHOST 状态显示——这是即便什么都没留下,也能确认其被执行过的铁证。
**主机取证检查。** 除了包文件之外,扫描器还会检查:
- 恶意软件投放有效载荷的已知文件路径(根据不同的安全事件针对特定平台)
- Shell 配置文件(`.zshrc`、`.bashrc` 等)中是否被注入了 IOC 字符串
- 持久化机制:macOS 的 LaunchAgents、Linux 的 systemd/cron/XDG 自启动项,Windows 的启动文件夹和注册表运行键
- npm 缓存条目——即使在完全清理后,也能确认曾下载过对应的 tarball
- npm install 日志——记录了生命周期脚本的执行情况
- 连接到已知 C2 地址的活动网络连接
**`--since` 应急响应模式。** 在应对正在进行的安全事件时,您只需检查在攻击时间窗口内发生的安装行为。通过 `--since 2026-03-31T00:21:00`(或使用事件 ID,如 `--since axios-2026-03-31`)可以跳过在此时间窗口之前的所有安装记录,使针对性扫描的速度大约提升 10 倍。
### 其他涵盖范围
- 所有 npm lockfile 格式:`package-lock.json`、`yarn.lock`、`pnpm-lock.yaml`、`bun.lock`、`deno.lock`
- 任意深度的已安装包:npm 扁平化布局、嵌套结构、pnpm 虚拟存储、Yarn Berry PnP ZIP 归档
- 全局包存储:Volta、nvm、fnm、Deno、Bun、npx 缓存、pnpm CAS
- 通过 `docker save` 扫描 Docker 镜像层——无需解压到磁盘
- 跨生态系统:Python、Ruby、Rust、Go、PHP (Composer)、Java (Maven)、Homebrew、Chocolatey
- 针对 npm 包的实时 OSV.dev 安全通告查询(`--online`)
### 零外部依赖
`scan.py` 是一个单文件,可在 Python 3.11+ 环境下运行,无需安装任何第三方包。IOC 数据库已内置其中——只需审计这一个文件,只需验证一个 SHA256 哈希值。
## Axios 漏洞利用事件 —— 本扫描器如何对其进行检查
在 UTC 时间 2026 年 3 月 31 日 00:21 至 03:15 期间,一名威胁行为者发布了两个恶意版本的 axios npm 包(`1.14.1` 和 `0.30.4`)。每个版本都包含一个被植入的依赖项(`plain-crypto-js@4.2.1`),该依赖项部署了一个凭据收集器和一个跨平台远程访问木马。这些包在被下架前每周下载量高达 1 亿次以上——暴露窗口期约为三个小时。
同一攻击者在此期间还入侵了 `trivy`、`kics`、`litellm` 和 `telnyx`。
**扫描器针对此事件会检查以下内容:**
| 检查项 | 检查目标 |
|------------------|-------------------------------------------------------------------------------------------------------------|
| Lockfiles | 任何 lockfile 中解析到的 `axios@1.14.1` 或 `axios@0.30.4` |
| `node_modules` | 任意深度下安装的任一恶意版本 |
| 隐藏的 lockfile | GHOST 状态——axios 曾被安装,但其目录现已消失 |
| npm 缓存 | 恶意版本的 tarball 已获取到 `~/.npm/_cacache/` 中 |
| npm 日志 | `~/.npm/_logs/` 中记录的 `postinstall` 生命周期脚本的执行情况 |
| 文件遗留物 | `/Library/Caches/com.apple.act.mond` (macOS)、`/tmp/ld.py` (Linux)、`%PROGRAMDATA%\wt.exe` (Windows) |
| Shell 配置文件 | 被注入到 `.zshrc`、`.bashrc` 或类似文件中的 IOC 字符串 |
| 持久化 | LaunchAgents (macOS)、systemd 单元、启动项 |
| 实时网络连接 | 与 `142.11.206.73:8000` 或 `sfrclak.com` 的活动连接 |
如果您在 UTC 时间 2026 年 3 月 31 日 00:21 至 03:15 期间运行过 `npm install`,并且 axios 是直接或间接依赖项,请使用 `--since` 将扫描范围限定在该时间窗口内:
```
python3 scan.py ~/dev --since axios-2026-03-31
```
如果报告了 CRITICAL 或 HIGH 级别的发现,请立即轮换:npm token、AWS/Azure/GCP 凭据、SSH 密钥、数据库密码和 API token。
## 快速入门
```
# 扫描您的开发目录
python3 scan.py ~/dev
# Incident-response 模式 — 仅检查攻击时间窗口内的安装
python3 scan.py ~/dev --since axios-2026-03-31
```
无需安装。仅需 Python 3.11 或更高版本,且只使用标准库。
## 所有标志和选项
### 位置参数
| 参数 | 描述 |
|--------|--------------------------------------------------------------------------------|
| `ROOT` | 要扫描的目录。默认为 `/`(全操作系统扫描)。单独使用 `--docker` 时请省略此参数。 |
### 选项
| 标志 | 默认值 | 描述 |
|--------------------------|--------------------|------------------------------------------------------------------------------------------------------------------------------------------------------|
| `--workers N` | min(CPU 数量, 8) | 用于并行文件解析的工作线程数 |
| `--iocs FILE` | (内置) | 自定义 IOC 数据库 JSON 文件的路径 |
| `--since ISO_OR_ID` | — | 应急响应模式:仅扫描在此时间戳当天或之后修改的 `node_modules`。接受 ISO 日期时间(`2026-03-31T00:21:00`)或事件 ID(`axios-2026-03-31`) |
| `--update-iocs` | — | 从上游 URL 下载最新的 `iocs.json`,验证其 SHA256,写入磁盘并退出 |
| `--docker [IMAGE ...]` | — | 通过 `docker save` 扫描 Docker 镜像。可传入特定的镜像名称,或省略名称以扫描所有本地镜像 |
| `--top-layers N` | 5 | 要扫描的最近 Docker 镜像层数。使用 `0` 扫描所有层 |
| `--online` | — | 针对所有发现的 npm 包,实时在线查询 OSV.dev 的恶意软件安全通告 |
| `--host` / `--no-host` | auto | 启用或禁用主机级别的取证检查(文件遗留物、Shell 配置文件、持久化、npm 缓存、npm 日志)。当 `ROOT` 为 `/` 或被省略时自动启用;否则禁用 |
### 输出格式
各标志之间互斥。默认为人类可读的彩色文本。
| 标志 | 输出 |
|-----------|--------------------------------------------------------------------------------|
| `--json` | 机器可读的 JSON,包含 `summary` 和 `findings` 数组——可通过管道传递给 `jq` 处理 |
| `--sarif` | SARIF 2.1.0 格式,适用于 GitHub Code Scanning 或 VS Code |
| `--junit` | JUnit XML 格式,适用于 GitLab CI 或 Jenkins |
| `--html` | 自包含的 HTML 报告——无需网络连接 |
### 退出码
| 代码 | 含义 |
|------|------------------------------------------------------------------------|
| `0` | 干净——未发现任何严重级别的问题 |
| `1` | 发现 CRITICAL 或 HIGH 级别问题——请立即采取行动 |
| `2` | 扫描错误(参数错误、文件缺失等) |
| `3` | 仅有 WARNING——存在易受攻击的配置,但未确认已被入侵 |
### 示例
```
# 完整 OS 扫描
python3 scan.py
# 针对特定目录进行扫描
python3 scan.py ~/dev
# Incident-response 模式
python3 scan.py ~/dev --since 2026-03-31T00:21:00
python3 scan.py ~/dev --since axios-2026-03-31
# Machine-readable 输出
python3 scan.py ~/dev --json
python3 scan.py ~/dev --json | jq '.findings[] | select(.severity == "CRITICAL")'
python3 scan.py ~/dev --json | jq '.stats'
# GitHub Code Scanning
python3 scan.py ~/dev --sarif > results.sarif
# 离线报告
python3 scan.py ~/dev --html > report.html
# Docker 扫描
python3 scan.py --docker # all local images
python3 scan.py --docker nginx:latest node:18-slim # specific images
python3 scan.py ~/dev --docker # filesystem + Docker
# 实时 OSV.dev advisory 检查
python3 scan.py ~/dev --online
# 使用自定义 IOC 数据库
python3 scan.py ~/dev --iocs /path/to/custom-iocs.json
# 更新嵌入式 IOC 数据库
python3 scan.py --update-iocs
```
## CI 集成
本仓库在 `.github/workflows/scan.yml` 中包含了一个开箱即用的 GitHub Actions 工作流。将其复制到您的仓库中即可:
- 在每次推送和拉取请求时运行扫描器
- 将扫描结果上传至 GitHub Code Scanning(可在 Security 标签页中查看)
- 如果出现任何 CRITICAL 或 HIGH 级别的发现,则使构建失败
- 将原始 JSON 结果作为工作流构件保留 30 天
构建门禁由 `check_findings.py` 实现,它会读取 JSON 输出,将其转换为 SARIF 2.1.0 以上传至 Code Scanning,并在发现任何 CRITICAL 或 HIGH 级别的问题时以退出码 1 终止。该工作流能正确处理非零退出码——即使构建最终因扫描发现问题而失败,SARIF 文件也总是会被上传。
默认情况下,CI 中的 `scan.py .` 会以**仓库限定模式**运行(禁用主机取证检查),这样构建结果仅取决于仓库内容,而不受运行器状态的影响。如需在专用的应急响应扫描任务中启用完整的主机取证功能,请传入 `--host`。
## 结果解读
| 严重级别 | 含义 | 操作 |
|-----------|--------------------------------------------------------------------------------------------------|------------------------------------------------------------------------------------------------------------------------------|
| CRITICAL | 确认安装或运行了恶意软件包 | 将该机器视为已被入侵。轮换所有凭据(参见事件的 `what_to_rotate` 列表)。如有可能,立即隔离该机器。 |
| HIGH | 存在有力的取证证据(GHOST 状态、npm 缓存/日志、文件遗留物、持久化) | 即使包已不复存在,也极大概率曾被执行过。轮换凭据,并进行进一步调查。 |
| WARNING | 存在易受攻击的配置(如浮动的版本范围、缺少 lockfile、未设置 `ignore-scripts` 等) | 尚未确认被入侵,但该配置存在安全隐患。请加固配置。 |
如果针对 axios 事件的扫描返回了 CRITICAL 或 HIGH 结果,请立即轮换:npm token、AWS/Azure/GCP 云凭据、SSH 密钥、数据库密码,以及在该攻击时间窗口内可从该机器访问的任何 API token。
## 互补工具
本扫描器主要涵盖取证应急响应。请结合以下工具一起运行,以实现全面覆盖:
| 工具 | 补充功能 | 适用场景 |
|------------------------------------------------------|----------------------------------------------------------------------------------------------------|------------------------------------------|
| [OSV-Scanner](https://google.github.io/osv-scanner/) | 针对 11 个以上生态系统的 CVE 安全通告扫描;支持离线;lockfile 和 Docker 镜像的 CVE 扫描 | 定期 CI 门禁,合并前检查 |
| [Trivy](https://github.com/aquasecurity/trivy) | Docker/K8s/IaC 扫描;镜像内的 OS 包 CVE 扫描;源码中的机密检测 | 容器镜像加固,IaC 安全 |
| [Grype](https://github.com/anchore/grype) | 轻量级 CVE 扫描器;支持离线数据库;可与 Syft 搭配生成 SBOM | 离线/隔离环境的 CVE 审计 |
| [Socket.dev](https://socket.dev) | 针对 npm 包恶意代码模式的行为静态分析 | 安装前的 PR 门禁(SaaS 模式) |
| npm audit | 针对 npm 安全通告数据库的内置 CVE 检查 | 快速的 lockfile 检查,无需安装 |
## 环境要求
- Python 3.11 或更高版本
- 无需安装任何包——仅使用标准库
- 在 `PATH` 中具有 `docker` 命令行工具以进行 `--docker` 扫描(可选)
- 使用 `lsof` / `ss` / `netstat` 进行实时网络连接检查(可选,由操作系统提供)
标签:Cloudflare, Conpot, DNS 反向解析, DNS 解析, GHOST检测, GraphQL安全矩阵, IOC扫描, IP 地址批量处理, macOS安全, MITRE ATT&CK, Node.js安全, npm供应链安全, npm包管理器, OpenCanary, Python, Windows安全, 主机取证, 供应链攻击, 后门检测, 子域名变形, 存活证据, 安全合规, 安全扫描器, 工具集, 库, 应急响应, 持久化机制检查, 数字取证, 文档安全, 无后门, 横向移动检测, 端点安全, 网络代理, 网络安全, 网络连接监控, 自动化脚本, 补丁管理, 请求拦截, 隐私保护