Jasminelorkan/wazuh-siem-detection-lab

GitHub: Jasminelorkan/wazuh-siem-detection-lab

一个实践性 SOC 作品集项目,基于 Wazuh 部署多 OS 日志采集并编写映射 MITRE ATT&CK 的自定义检测规则,包含完整的调试与设计推理笔记。

Stars: 0 | Forks: 0

# Wazuh SIEM 检测实验 一个实践性的 SOC 分析师作品集项目:部署 Wazuh,连接多操作系统日志源,并构建自定义的 MITRE ATT&CK 映射检测规则,包含每一步完整的调试和设计推理笔记。 ## 概述 构建此实验是为了填补简历上的一个特定空白:实操 SIEM 经验。本项目的目标并非照本宣科地跟随教程,而是在真实的基础设施限制下部署 Wazuh,连接真实的日志源,触发真实的攻击行为,并从零开始编写和调试自定义检测逻辑。 **环境:** - Wazuh Cloud(托管型 manager/indexer/dashboard,免费试用版) - Agent 1:Windows 11 笔记本电脑(原生 Wazuh agent) - Agent 2:WSL2 Ubuntu 实例(Wazuh agent) ## 架构 / 日志源 | 来源 | 角色 | 提供的内容 | |---|---|---| | `windows-endpoint-01` | Windows 11 原生 agent | Event ID 4625(登录失败),Event ID 4688(进程创建,已启用命令行审计) | | `wsl-linux-agent-002` | WSL2 Ubuntu agent | `/var/log/auth.log`、`/var/log/syslog`,以及后来的 `/var/log/dnsmasq.log` | 两个 agent 都经过了端到端验证:在构建任何上层应用之前,通过 Discover/事件搜索确认了 agent 连接状态,以及实际索引的事件流(而不仅仅是“Active”状态)。 ![两个 agent 在 Wazuh dashboard 中显示为活跃状态](https://static.pigsec.cn/wp-content/uploads/repos/cas/d4/d4e14d3d43eb9932a0ce46ae1c8bfab858344544f8a4ed81d43d8ef10c91531c.png) ## 规则 1:暴力破解检测(默认规则) - **Rule ID:** 60122 — "Logon Failure - Unknown user or bad password" - **触发条件:** 反复出现的 Windows Event ID 4625(登录失败) - **结果:** 确认单次登录失败事件被正确检测和索引。曾尝试实现完整的暴力破解*关联*告警(将多次失败捆绑为一个告警),但在本地未能实现,因为 Windows 11 内置的账户锁定保护会在连续 4-5 次快速失败尝试后强制重启——这是一种合法的 OS 级别控制措施,限制了在本地测试中安全生成的测试量/速度。这是在个人且未加入域的机器上测试暴力破解检测时,一个真实且可解释的限制,而不是流水线本身的缺陷:单事件检测(规则 60122)已在真实的 4625 数据上验证有效。 ## 规则 2:自定义规则 — 可疑的 PowerShell 执行 (T1059.001) **Rule ID:** 100002 | **MITRE ATT&CK:** T1059.001(命令和脚本解释器:PowerShell) ``` windows ^4688$ (?i)powershell\.exe (?i)(-enc|-EncodedCommand) Suspicious PowerShell execution with encoded/obfuscated command (possible T1059.001) T1059.001 ``` **为什么选择此模式:** 攻击者通常使用 PowerShell 的 `-EncodedCommand` 标志来传递 Base64 编码的脚本,从而逃避明文关键字扫描。存在合法用途(例如,自动化脚本为避免 shell 转义问题),但很少见,大多数正常的 PowerShell 使用并不需要它。考虑到合法使用的基准率较低,以及漏报真实编码 payload 的巨大代价,这是一个成本合理的分诊信号,而不是“发现即拦截”的规则:误报只会耗费分析师几分钟的审查时间;漏报则可能意味着错过了恶意软件的执行。 **前置工作:** Windows 默认不记录进程创建(Event ID 4688),即使启用了该功能,默认情况下也不包含命令行参数。这两项都必须显式启用:使用 `auditpol` 进行进程创建审计,以及通过一个注册表项(`ProcessCreationIncludeCmdLine_Enabled`)来捕获命令行(Windows 家庭版没有组策略编辑器,因此直接在注册表中设置)。 **调试经历:** 尽管底层的 4688 事件已被正确记录,该规则最初并未触发。通过检查类似且*确实触发*的事件(一条通用的 Wazuh 规则,67027)的原始 JSON 进行诊断,发现该规则使用了 `win.eventdata.image`,而这个字段在当前解码器的结构中并不存在。正确的字段应该是 `win.eventdata.newProcessName`。修正了字段路径后,重新测试,规则成功触发。 ![自定义规则 100002 触发并映射到 MITRE T1059.001](https://raw.githubusercontent.com/Jasminelorkan/wazuh-siem-detection-lab/main/screenshots/custom-rule-firing.png) **已知限制:** 当前的正则表达式明确检查 `-enc` 和 `-EncodedCommand`,但 PowerShell 接受任何无歧义的标志名称前缀(例如,`-en`、`-e`)。更完善的规则应该考虑到这一点;在此将其作为已记录的缺陷暂缓处理,而不是作为一个未经验证的修复。 ## 规则 3:DNS 隧道检测(已设计,未部署)— T1071.004 **MITRE ATT&CK:** T1071.004(应用层协议:DNS) **检测逻辑(此前通过对真实 iodine DNS 隧道流量的 Wireshark 实操分析验证):** 仅在三个条件同时出现时触发告警 (1) NULL DNS 记录类型占主导,(2) 单一域名持久性且缺乏域名多样性,(3) 高熵子域名字符串。单独来看,这些条件都无法可靠地将隧道流量与正常浏览区分开来(专门测试了查询量/速率,并排除了其作为独立鉴别因素的可能性);三者的组合才是关键信号。 **发现的日志源缺陷:** Windows 默认不记录 DNS 客户端查询。启用 DNS-Client Operational 日志(Applications and Services Logs → Microsoft → Windows → DNS-Client → Operational)可以捕获被查询的域名,但**不包括记录类型**——这直接阻碍了条件 (1) 的满足。Sysmon Event ID 22(DNSEvent)也有同样的局限性。 **变通方案:** 在 WSL2 Ubuntu agent 上安装了 `dnsmasq` 作为专用的非默认本地解析器(通过 `nslookup 127.0.0.1` 显式查询,绝不能将其设置为系统的默认 DNS,以免影响正常的机器网络)。配置为将查询记录(`log-queries`)输出到专用文件(`log-facility=/var/log/dnsmasq.log`),而不是混入系统的 `syslog` 中。 **在运行 dnsmasq 过程中调试的实际问题:** 1. **端口冲突:** dnsmasq 无法绑定 53 端口——`systemd-resolved` 已经在多个本地地址上占用了该端口。通过确认 socket 在每个(地址,端口)对上是唯一的得以解决,并将 dnsmasq 显式绑定到一个空闲地址(`listen-address=127.0.0.1`)。 2. **绑定依然失败:** 仅使用 `listen-address` 是不够的,dnsmasq 默认的绑定行为仍然尝试进行更广泛的接口绑定。添加了 `bind-interfaces` 以强制执行严格的单地址绑定。 3. **查询返回 SERVFAIL:** dnsmasq 启动并接受了查询,但没有配置上游解析器(`-r /run/dnsmasq/resolv.conf` 指向了一个不存在的文件,因为自动 resolvconf 集成失败了——这是预料之中的,因为故意没有将 dnsmasq 集成为系统默认值)。通过手动指定 `server=8.8.8.8` 作为上游解析器解决了问题。 **验证:** 通过 `dnsmasq` 自身的日志确认,每次查询的记录类型(例如,`query[NULL] ...`)和完整域名均被捕获——这填补了 Windows 原生日志记录无法解决的具体空白。 ![dnsmasq 日志确认捕获了记录类型和域名](https://raw.githubusercontent.com/Jasminelorkan/wazuh-siem-detection-lab/main/screenshots/dnsmasq-record-type-confirmed.png) 通过 bash `for` 循环在紧凑的时间窗口内,针对固定的虚假基础域名(`test-web.com`)生成了一波 NULL 类型查询测试爆发,并使用了随机的高熵子域名字符串(`tr -dc "A-Za-z0-9" < /dev/urandom | head -c 16`),产生的日志数据在结构上与最初在 Wireshark 中观察到的隧道模式保持一致。 ![dnsmasq 日志显示带有高熵子域名的 NULL 类型查询](https://raw.githubusercontent.com/Jasminelorkan/wazuh-siem-detection-lab/main/screenshots/dnsmasq-null-burst.png) **状态:已根据真实的捕获日志数据完成设计和验证;尚未作为实时 Wazuh 规则部署。** Wazuh Cloud 试用环境在 2 天后被终止,且在项目时间范围内无法获得新的试用资格。虽然考虑过在本地重新安装完整的 Wazuh manager 技术栈,但 indexer 的资源需求使其非常不适合在非服务器硬件上长期使用。规则逻辑、字段映射(`ossec.conf` 中针对 `/var/log/dnsmasq.log` 的 `` 条目,与 `auth.log`/`syslog` 使用的模式相同)以及 MITRE 映射已完全设计完毕;在获得环境访问权限的前提下,实时部署是唯一剩下的步骤。 ## 经验总结 / 基础设施笔记 - 本地安装 Wazuh manager(尤其是 indexer)确实非常消耗资源;在硬件资源受限的情况下,托管的云服务是进行实操学习的更现实选择,而非退而求其次的方案。 - WSL2 的默认内存分配(约为主机 RAM 的 50%)不足以满足 Wazuh 规定的最低要求;必须通过 `.wslconfig` 显式调高上限(使用 `memory=`,单位为整数 MB,而不是十进制 GB)。 - WSL2 内持续的高 CPU 负载(例如 indexer 的 JVM 进程)可能会在轻薄的笔记本硬件上产生明显的热负荷——在本地运行资源消耗密集的服务时,除了关注 RAM 数据外,还需要留意 `top`/`ps aux --sort=-%mem` 和物理温度。 - 面向企业评估的免费云试用(企业邮箱要求、电话验证、使用情况审查)在用于个人学习/作品集目的时,可能会成为实际的障碍。
标签:AI合规, PB级数据处理, Wazuh, 安全实验环境, 安全运维, 安全运营中心, 红队行动, 网络映射