nagol0618/threat-hunting-supply-chain-attack

GitHub: nagol0618/threat-hunting-supply-chain-attack

一份完整的威胁狩猎案例,展示了如何利用 Splunk 与 Sysmon 日志追踪并确认通过恶意 npm 包引发的供应链攻击链。

Stars: 0 | Forks: 0

# 🔍 威胁狩猎:通过恶意 npm 包的供应链攻击 ![平台](https://img.shields.io/badge/Platform-TryHackMe-red?style=flat-square&logo=tryhackme) ![SIEM](https://img.shields.io/badge/SIEM-Splunk%208.2.6-orange?style=flat-square) ![日志](https://img.shields.io/badge/Logs-Sysmon-blue?style=flat-square) ![ATT%26CK](https://img.shields.io/badge/MITRE%20ATT%26CK-T1195%20%7C%20T1059%20%7C%20T1547-purple?style=flat-square) ![结果](https://img.shields.io/badge/Result-Investigation%20Successful-brightgreen?style=flat-square) ![分数](https://img.shields.io/badge/Score-335%20pts-brightgreen?style=flat-square) ## 概述 本报告记录了在 Splunk 中针对 **PawPressMe**(一家小型在线媒体公司)进行的完整威胁狩猎调查,该调查模拟了一次供应链攻击。从威胁情报简报和狩猎假设出发,我利用 Sysmon 日志在 Splunk 中重构了从初始妥协到持久化的完整攻击链——识别出患者零号、确认影响范围,并将每个阶段映射到 MITRE ATT&CK。 **假设:** 攻击者可能利用了一个受损的第三方软件包来获得系统的初始访问权限,并静默地准备负载以供后续执行。他们很可能建立了持久化机制,以便在不被立即发现的情况下维持访问权限。 **结论:✅ 已证实** — 通过 Splunk 中的 Sysmon 事件代码 1、11、13 和 22 日志证据确认。 **结果指标:** | 指标 | 结果 | |------|------| | 假设验证 | ✅ 已证实 | | 识别出的技术/战术 | 100% | | 检测到的 compromised 资产 | 100% | | 检测到的 IOCs | 40% | | 攻击链阶段 | 3 / 3 | ## 环境 | 组件 | 详情 | |------|------| | 目标组织 | PawPressMe(模拟) | | SIEM | Splunk Enterprise 8.2.6 | | 日志来源 | Windows Sysmon(事件日志:`Microsoft-Windows-Sysmon/Operational`) | | 网络 | `10.10.50.0/24` 企业局域网 | | 备份服务器 | `pawbackup` @ `10.10.50.5` | | 范围内主机 | paw-tom、paw-marie、paw-tabitha、paw-leo、paw-penny、paw-sally | ### 员工 | 姓名 | 角色 | 主机 | |------|------|------| | Tom Whiskers | 联合创始人兼临时 IT 管理员 | paw-tom | | Marie Purrman | 财务经理 | paw-marie | | Tabitha Clawson | 撰稿人 | paw-tabitha | | Leo Meowrell | 多媒体编辑 | paw-leo | | Penny Pawsworth | 社交媒体专员 | paw-penny | | Sally Felina | 创始人兼创意总监 | paw-sally | ## 威胁情报 ### 提供的 IOCs **基于主机的:** | 类型 | 值 | |------|-------| | NPM 包 | `healthchk-lib@1.0.1` | | 注册表路径 | `HKCU\Software\Microsoft\Windows\CurrentVersion\Run` | | 注册表值名称 | `Windows Update Monitor` | | 注册表值数据 | `powershell.exe -NoP -W Hidden -EncodedCommand ` | | 下载文件 | `%APPDATA%\SystemHealthUpdater.exe` | | PowerShell 命令 | `Invoke-WebRequest -Uri ... -OutFile ...` | | 进程执行 | `powershell.exe -NoP -W Hidden -EncodedCommand ...` | | 脚本工件 | 在 `package.json` 的 `"postinstall"` 中发现 | **基于网络的:** | 类型 | 值 | |------|-------| | 下载 URL | `http://global-update.wlndows.thm/SystemHealthUpdater.exe` | | C2 主机名 | `global-update.wlndows.thm`(注意:拼写错误 — `wlndows` 而非 `windows`) | | 协议 | HTTP(未加密) | | 端口 | 80 | | 流量行为 | 通过 PowerShell 下载文件到 `%APPDATA%` | ### 攻击背景 TryDetectThis 情报确认了一次针对 npm 和 Python 包仓库的协调供应链攻击。攻击者获得了被忽视的开源软件包的贡献者权限,然后发布包含 postinstall 载荷的恶意更新,在安装时静默执行。 ## 调查 ### 步骤 1 — 确认数据存在 在搜索任何 IOC 之前,我确认 Splunk 实例已加载数据并识别可用的日志来源。 ``` index=* ``` **结果:** 返回 1,051 个事件。左侧面板显示了 `ComputerName` 字段的 **3 个不同值** — 确认存在来自多个主机的 Sysmon 日志。日志来源:`Microsoft-Windows-Sysmon/Operational`。 ### 步骤 2 — 寻找 C2 域(患者零号) 最强的网络 IOC 是拼写错误的 C2 域。我在所有主机上搜索它。 ``` index=* w1ndows.thm ``` **结果:1 个事件** ``` ComputerName: paw-tom EventCode: 22 (Sysmon DNS Query) Image: C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe QueryName: global-update.wlndows.thm QueryResults: ::ffff:127.0.0.1 Time: 6/21/2025 10:58:29 AM ``` **发现:** `paw-tom`(Tom Whiskers)是**患者零号**。他的机器上 PowerShell 向攻击者的 C2 域发起了一次 DNS 查询,时间为 `10:58:29`。这是 Sysmon 事件代码 22 — DNS 查询 — 在任何 TCP 连接建立之前就会触发。 ### 步骤 3 — 围绕患者零号进行横向搜索 确认受害主机后,我按时间顺序提取了 `paw-tom` 上的所有活动。 ``` index=* ComputerName="paw-tom" | sort _time ``` 点击左侧面板中的 `CommandLine` 字段,可查看顶级进程执行。关键条目如下: ``` npm install healthchk-lib@1.0.1 powershell.exe -NoP -W Hidden -EncodedCommand JABkAGUAcwB0... ``` ### 步骤 4 — 寻找恶意软件包 ``` index=* ComputerName="paw-tom" healthchk ``` **结果 — 事件代码 11(文件创建):** ``` Image: C:\Program Files\nodejs\node.exe TargetFilename: C:\Development\node_modules\healthchk-lib\scripts\postinstall.ps1 User: PAW-TOM\itadmin-tom Time: 6/21/2025 10:58:27 AM ``` **发现:** `node.exe` 将 `postinstall.ps1` 写入磁盘 — 恶意 npm 包的 postinstall 脚本已被提取并暂存。 **事件代码 1(进程创建)— npm 安装:** ``` Image: C:\Program Files\nodejs\node.exe CommandLine: node.exe npm-cli.js install healthchk-lib@1.0.1 CurrentDirectory: C:\Development\ ParentImage: C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe User: PAW-TOM\itadmin-tom Time: 6/21/2025 10:58:24 AM ``` ### 步骤 5 — 寻找编码后的 PowerShell 执行 ``` index=* ComputerName="paw-tom" EncodedCommand ``` **结果 — 事件代码 1(进程创建):** ``` Image: C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe CommandLine: powershell.exe -NoP -W Hidden -EncodedCommand JABkAGUAcwB0... ParentImage: C:\Windows\System32\cmd.exe ParentCommandLine: cmd.exe /d /s /c powershell.exe -NoP -W Hidden -EncodedCommand... CurrentDirectory: C:\Development\node_modules\healthchk-lib\ IntegrityLevel: High Time: 6/21/2025 10:58:27 AM ``` **可见的进程链:** ``` powershell.exe (parent, PID 1452) └─ node.exe — npm install healthchk-lib@1.0.1 (PID 1924) └─ cmd.exe — postinstall script fires (PID 1616) └─ powershell.exe -NoP -W Hidden -EncodedCommand (PID 5880) ``` **解码后的 Base64 载荷** 执行以下操作: 1. 从 `http://global-update.wlndows.thm/` 下载 `SystemHealthUpdater.exe` 2. 将其保存到 `%APPDATA%\SystemHealthUpdater.exe` 3. 对用于注册表 Run 键的 `Start-Process` 命令重新编码为 Base64 ### 步骤 6 — 寻找注册表持久化 ``` index=* "Windows Update Monitor" ``` **结果 — 事件代码 13(注册表值设置):** ``` Image: C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe TargetObject: HKU\S-1-5-21-...\Software\Microsoft\Windows\CurrentVersion\Run\Windows Update Monitor Details: powershell.exe -NoP -W Hidden -EncodedCommand UwB0AGEAcgB0AC0... RuleName: T1060,RunKey ProcessGuid: {c5d2b969-9053-6856-e701-000000002a01} Time: 6/21/2025 10:58:29 AM ``` **发现:** 恶意 PowerShell 写入了一个名为 `Windows Update Monitor` 的注册表 Run 键 — 故意模仿合法 Windows 进程名称。解码后的命令为: ``` Start-Process 'C:\Users\Administrator\AppData\Roaming\SystemHealthUpdater.exe' ``` 这确保了 `SystemHealthUpdater.exe` 在每次用户登录时自动启动。攻击者现在可以无限期地在重启后保持访问权限。 ### 步骤 7 — 范围确定 为确定攻击是否扩散到 `paw-tom` 之外,我同时在所有主机上运行了组合 IOC 搜索。 ``` index=* (healthchk-lib OR "Windows Update Monitor" OR wlndows.thm OR SystemHealthUpdater OR EncodedCommand) | stats count by ComputerName, EventCode | sort ComputerName ``` **结果:** ``` ComputerName EventCode count paw-tom 1 12 paw-tom 11 2 paw-tom 13 1 paw-tom 22 1 ``` **发现:** 感染仅限于 `paw-tom`。未发现其他主机名。横向移动到备份服务器(`paw` @ `10.10.50.5`)未被检测到。 我还直接检查了备份服务器: ``` index=* EventCode=3 DestinationIp="10.10.50.5" ``` **结果:0 个事件。** 备份服务器未受影响。 ## 攻击链 ``` [10:58:24] Tom Whiskers runs: npm install healthchk-lib@1.0.1 │ │ EventCode 1 — Process Create (node.exe → npm-cli.js) ▼ [10:58:27] postinstall.ps1 extracted to disk │ │ EventCode 11 — File Created ▼ [10:58:27] npm triggers postinstall → cmd.exe spawned by node.exe │ │ EventCode 1 — Process Create (node.exe → cmd.exe) ▼ [10:58:27] cmd.exe launches: powershell.exe -NoP -W Hidden -EncodedCommand │ │ EventCode 1 — Process Create (cmd.exe → powershell.exe) ▼ [10:58:29] Registry Run key written: "Windows Update Monitor" │ │ EventCode 13 — Registry Value Set (T1060/RunKey) ▼ [10:58:29] DNS query: global-update.wlndows.thm │ │ EventCode 22 — DNS Query ▼ [10:58:29] SystemHealthUpdater.exe downloaded to %APPDATA% │ │ EventCode 11 — File Created ▼ [BACKDOOR ACTIVE — survives reboot via Run key] ``` ### 找到每个步骤的 Splunk 查询 | 时间戳 | 事件代码 | 攻击步骤 | 查询 | |--------|----------|----------|------| | 10:58:24 | EC-1 | npm 安装 healthchk-lib@1.0.1 | `index=* ComputerName="paw-tom" npm` | | 10:58:27 | EC-11 | postinstall.ps1 写入磁盘 | `index=* ComputerName="paw-tom" healthchk` | | 10:58:27 | EC-1 | cmd.exe 由 node.exe 启动 | `index=* EventCode=1 ParentImage="*node.exe*"` | | 10:58:27 | EC-1 | powershell.exe -EncodedCommand | `index=* ComputerName="paw-tom" EncodedCommand` | | 10:58:29 | EC-13 | 注册表 Run 键写入 | `index=* "Windows Update Monitor"` | | 10:58:29 | EC-22 | DNS 查询到 C2 域 | `index=* w1ndows.thm` | | 10:58:29 | EC-11 | SystemHealthUpdater.exe 下载 | `index=* SystemHealthUpdater` | ## MITRE ATT&CK 映射 | 阶段 | 战术 | 技术 ID | 技术 | |------|------|----------|------| | 1 — 初始访问 | TA0001 | [T1195](https://attack.mitre.org/techniques/T1195/) | 供应链妥协 | | 2 — 执行 | TA0002 | [T1059.001](https://attack.mitre.org/techniques/T1059/001/) | 命令与脚本解释器:PowerShell | | 3 — 持久化 | TA0003 | [T1547.001](https://attack.mitre.org/techniques/T1547/001/) | 启动/登录自动执行:注册表 Run 键 | ## 关键发现与经验教训 ### 为什么这种攻击难以被检测到(缺乏行为分析) - 链条中的每个二进制文件(`node.exe`、`cmd.exe`、`powershell.exe`)都是**合法、已签名的 Microsoft 或 Node.js 可执行文件** - npm 安装流程在开发机器上是**预期行为**,容易混入正常噪声 - 恶意包名称 `healthchk-lib` 听起来像是一个合理的实用工具 - C2 域 `wlndows.thm` 使用了细微的拼写错误(`l` 替代 `i`),以规避随意审查 - 持久化注册表键 `Windows Update Monitor` 模仿合法 Windows 服务名称 ### 哪些检测手段本可更早发现 | 检测机会 | 方法 | |----------|------| | 阻止下载 | 防火墙出站规则:禁止 PowerShell 向未知域名发起端口 80 连接 | | 异常父进程 PowerShell 告警 | SIEM 规则:事件代码 1,其中 `node.exe → cmd.exe → powershell.exe` | | 编码命令告警 | SIEM 规则:事件代码 1,其中 `CommandLine` 包含 `-EncodedCommand` | | 非标准进程写入注册表告警 | SIEM 规则:事件代码 13,其中写入者为 `powershell.exe` 且路径包含 `CurrentVersion\Run` | | npm 包审计 | 在 CI/CD 中禁止 postinstall 脚本或使用 `--ignore-scripts` 标志 | ### 建议的补救措施(针对 paw-tom) 1. **删除** `HKCU\Software\Microsoft\Windows\CurrentVersion\Run\Windows Update Monitor` 2. **删除** `%APPDATA%\Roaming\SystemHealthUpdater.exe` 3. **阻止** `global-update.wlndows.thm` 在边界防火墙 4. **审计** `C:\Development\node_modules\` 中是否存在其他可疑包 5. **检查** 该主机上的所有 npm 安装历史 6. **重置** `PAW-TOM\itadmin-tom` 凭据 — 管理员级进程运行了恶意软件 7. **实施** npm `--ignore-scripts` 策略或 postinstall 脚本允许列表 ## Sysmon 事件代码参考 | 代码 | 事件类型 | 威胁狩猎用途 | |------|----------|--------------| | 1 | 进程创建 | 父子链、命令行参数、`-EncodedCommand` | | 3 | 网络连接 | 意外进程发起的出站连接 | | 10 | 进程访问 | lsass.exe 读取 = 凭证转储 | | 11 | 文件创建 | 可执行文件被异常路径丢弃 | | 12/13 | 注册表事件 | Run 键写入、持久化机制 | | 22 | DNS 查询 | C2 域通信、最早网络信号 | | 23 | 文件删除 | 执行后清理证据 | ## 使用的 SPL 查询 ### 方向定位 ``` index=* index=* | eventcount summarize=false index=* ``` ### IOC 狩猎 ``` index=* w1ndows.thm index=* healthchk-lib index=* "Windows Update Monitor" index=* SystemHealthUpdater index=* EncodedCommand ``` ### 主机跳转 ``` index=* ComputerName="paw-tom" | sort _time index=* ComputerName="paw-tom" earliest="06/21/2025:10:58:00" ``` ### 父子进程狩猎 ``` index=* EventCode=1 ParentImage="*node.exe*" Image="*cmd.exe*" index=* EventCode=1 ParentImage="*cmd.exe*" Image="*powershell*" index=* EventCode=1 CommandLine="*EncodedCommand*" index=* EventCode=1 Image="*powershell*" | table _time ComputerName ParentImage CommandLine | sort _time ``` ### ProcessGuid 跳转 ``` index=* ProcessGuid="{c5d2b969-9053-6856-e701-000000002a01}" ``` ### 范围确定 ``` index=* (healthchk-lib OR "Windows Update Monitor" OR wlndows.thm OR SystemHealthUpdater OR EncodedCommand) | stats count by ComputerName, EventCode | sort ComputerName ``` ### 横向移动检查 ``` index=* EventCode=3 DestinationIp="10.10.50.5" ``` ## 仓库结构 ``` threat-hunting-supply-chain-attack/ ├── README.md ← this writeup ├── artifacts/ │ ├── attack_chain_evidence_map.svg ← visual query-to-evidence map │ └── splunk_queries.md ← all SPL queries reference └── reference/ └── splunk_threat_hunting_reference.pdf ← full field cheatsheet ``` ## 工具与参考 - [TryHackMe 威胁狩猎模拟器](https://tryhackme.com/threat-hunting-sim) - [MITRE ATT&CK T1195 — 供应链妥协](https://attack.mitre.org/techniques/T1195/) - [MITRE ATT&CK T1059.001 — PowerShell](https://attack.mitre.org/techniques/T1059/001/) - [MITRE ATT&CK T1547.001 — 注册表 Run 键](https://attack.mitre.org/techniques/T1547/001/) - [Sysmon 事件 ID 参考 — Microsoft](https://learn.microsoft.com/en-us/sysinternals/downloads/sysmon) - [Splunk SPL 参考](https://docs.splunk.com/Documentation/Splunk/latest/SearchReference) ## 关于 **Logan Garner** — 位于丹佛都会州立大学(Metropolitan State University of Denver)的 IT 与网络安全专业学生(预计 2027 年 5 月毕业)。 [![TryHackMe](https://img.shields.io/badge/TryHackMe-nagol0618-red?style=flat-square&logo=tryhackme)](https://tryhackme.com/p/nagol0618) [![GitHub](https://img.shields.io/badge/GitHub-nagol0618-black?style=flat-square&logo=github)](https://github.com/nagol0618) [![LinkedIn](https://img.shields.io/badge/LinkedIn-Logan%20Garner-blue?style=flat-square&logo=linkedin)](https://linkedin.com/in/logan-garner-368798277)
标签:AI合规, ATT&CK T1059, ATT&CK T1195, ATT&CK T1547, Health Hazard, IOC检测, PawPressMe, Sysmon, TryHackMe, 供应链攻击, 初始访问, 协议分析, 取证调查, 威胁情报, 开发者工具, 恶意npm包, 攻击链, 文档安全, 日志取证, 暗色界面, 权限提升, 网络安全, 隐私保护