eegeeZA/supply-chain-scanner

GitHub: eegeeZA/supply-chain-scanner

一款专注于 npm 供应链安全事件的主机取证与应急响应扫描器,能够在恶意软件自行清理后依然检测出其执行痕迹。

Stars: 0 | Forks: 0

# supply-chain-scanner ![Python](https://img.shields.io/badge/python-%3E%3D3.11-blue) ![License](https://img.shields.io/badge/license-MIT-green) 一个用于供应链安全事件的取证与应急响应扫描器。它回答了现有 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安全, 主机取证, 供应链攻击, 后门检测, 子域名变形, 存活证据, 安全合规, 安全扫描器, 工具集, 库, 应急响应, 持久化机制检查, 数字取证, 文档安全, 无后门, 横向移动检测, 端点安全, 网络代理, 网络安全, 网络连接监控, 自动化脚本, 补丁管理, 请求拦截, 隐私保护