VibhavChennamadhava/Active-Directory-SOC-Splunk-Lab

GitHub: VibhavChennamadhava/Active-Directory-SOC-Splunk-Lab

基于 Vultr 云基础设施搭建的端到端 SOC 实验室,利用 Splunk SIEM 检测未授权 RDP 登录并通过 Shuffle SOAR 自动触发 Discord 通知与 Active Directory 账户禁用的闭环响应。

Stars: 0 | Forks: 0

# Active-Directory-SOC-Splunk 实验室 ![Windows Server 2022](https://img.shields.io/badge/Windows%20Server-2022-0078D6?logo=windows&logoColor=white) ![Ubuntu 22.04](https://img.shields.io/badge/Ubuntu-22.04-E95420?logo=ubuntu&logoColor=white) ![Splunk Enterprise](https://img.shields.io/badge/Splunk-Enterprise-000000?logo=splunk&logoColor=white) ![Shuffle SOAR](https://img.shields.io/badge/Shuffle-SOAR-FF6F00) ![Active Directory](https://img.shields.io/badge/Active%20Directory-DS-1E90FF) ![Vultr](https://img.shields.io/badge/Vultr-Cloud-007BFC?logo=vultr&logoColor=white) ![Discord](https://img.shields.io/badge/Discord-Webhooks-5865F2?logo=discord&logoColor=white) ## 概述 本实验端到端模拟了一个小型企业 SOC pipeline:一台承载 Active Directory Domain Services 的 Windows Server 2022 域控、一台加入域的 Windows 测试工作站,以及一台运行 Splunk Enterprise 作为 SIEM 的 Ubuntu 22.04 主机。两台 Windows endpoint 的遥测数据通过 Universal Forwarder 转发到 Splunk,在此由计划内的 correlation search 检测源自企业 IP 范围之外的未经授权成功 RDP 登录(EventCode 4624,Logon Types 7 和 10)。当规则触发时,Splunk 会将 alert payload 转发给 Shuffle SOAR workflow,该 workflow 会通过 Discord webhook 通知分析师,向他们发送包含是/否处置提示的电子邮件,并在确认后通过 LDAP 在 Active Directory 中禁用违规用户。整个环境运行在单个 VPC 内的 Vultr 云基础设施上,使分析师的体验与真实的 SOC 调查保持一致:检测、triage、决策、响应、确认。 ## 目标 - 建立一个可运行的 Active Directory 林(`MyDFIR.local`),包含一台域控、一台加入域的工作站和一个测试用户账户 - 使用 Universal Forwarder 在默认 indexer 端口 (9997) 上,将来自两个 endpoint 的 Windows 安全日志遥测集中到 Splunk - 编写一个 Splunk SPL 检测规则,按 Logon Type 和源 IP 过滤 EventCode 4624,以呈现未经授权的成功 RDP 登录 - 将 Shuffle SOAR workflow 连接到 Splunk webhook,使触发的告警流入自动化 playbook - 实现分析师参与的闭环响应:Discord 通知、邮件决策、AD 账户禁用、向频道回传确认消息 - 通过 VPC 隔离、Vultr 防火墙组和基于主机的 `ufw` 规则,实践云网络加固 ## 架构 ![网络拓扑图](https://static.pigsec.cn/wp-content/uploads/repos/2026/06/8555e65304095028.png) | 虚拟机名称 | 角色 | 操作系统 | 公网 IP (Vultr 分配) | 私有 VPC IP | |---------|------|----|---------------------------|----------------| | `mydfir-ad-dc01` | Active Directory 域控 | Windows Server 2022 Standard | `216.x.x.136` | `10.22.96.4` | | `cloud-instance` (测试机) | 加入域的 Windows 工作站 | Windows Server 2022 Standard | `155.x.x.10` | `10.22.96.3` | | `mydfir-splunk` | Splunk Enterprise SIEM + UF 接收器 | Ubuntu 22.04 LTS | `216.128.x.18` | `10.22.96.5` | 这三台虚拟机均位于多伦多地区的同一个 Vultr VPC 中。虚拟机之间的流量保留在 `10.22.96.0/20` 私有子网内;Vultr 防火墙组控制所有来自公网的入站流量。 ## 使用的技术 | 技术 | 版本 | 用途 | |------------|---------|---------| | Vultr Cloud | 当前平台 | 为所有三台虚拟机和 VPC 提供底层 IaaS 托管 | | Windows Server | 2022 Standard | 域控和测试 endpoint 操作系统 | | Active Directory Domain Services | 内置 (Server 2022) | 身份、身份验证、组策略 | | Ubuntu Server | 22.04 LTS | Splunk indexer 的主机操作系统 | | Splunk Enterprise | 9.x (免费试用) | SIEM — 索引、搜索、告警 | | Splunk Universal Forwarder | 9.x | 将 `WinEventLog:Security` 从 endpoint 发送到 indexer | | Splunk Add-on for Microsoft Windows | 最新版 | 对 `user`、`Logon_Type`、`Source_Network_Address` 进行字段提取 | | Shuffle SOAR | 云托管 | 编排平台 — webhook 触发器、分支化 workflow | | Discord | N/A | 通过传入 webhook 的通知渠道(取代了 Slack) | | LDAP (通过端口 389) | AD 内置 | Shuffle AD 应用用于禁用账户的通道 | | `ufw` | 0.36 | Splunk Ubuntu 虚拟机上的基于主机的防火墙 | ## 实验网络设计 该实验建立在位于多伦多地区的单个 Vultr VPC(`10.22.96.0/20`)上。每台虚拟机在部署后都启用了 VPC 成员资格,这迫使系统重启,并为每台主机在私有子网上分配了第二个 NIC。开箱即用的 Windows 主机在第二个 NIC 上启动了 `169.254.x.x` APIPA 地址,而不是预期的 `10.22.96.x` 地址,因此需要在两台 Windows 虚拟机上为 Vultr VPC 适配器手动配置静态 IP、子网掩码和 DNS 指针。 单个 Vultr 防火墙组(`mydfir-ad-project-2.0`)应用于所有三台机器。规则仅根据功能需要逐步添加: | 端口 / 协议 | 源 | 添加原因 | |-----------------|--------|--------------| | TCP 22 (SSH) | 我的公网 IP | 从分析师工作站管理 Ubuntu Splunk 主机 | | TCP 3389 (MS-RDP) | 我的公网 IP(后来为了告警测试扩大到 `anywhere`) | 管理 Windows 虚拟机,随后故意暴露以生成未经授权的登录遥测 | | TCP 8000 (Splunk Web) | 我的公网 IP | 从浏览器访问 Splunk Web UI | | TCP 9997 (Splunk indexer) | VPC 对等节点 | 从两个 Windows endpoint 到 indexer 的 Universal Forwarder 流量 | | TCP 389 (LDAP) | Shuffle 云出口范围 | Shuffle SOAR 的 Active Directory 应用需要访问 DC 来禁用账户 | Ubuntu Splunk 主机除了 Vultr 防火墙外,还运行了 `ufw` —— 在流量成功到达 indexer 之前,必须同时开放这两层的端口 8000 (Web UI) 和 9997 (UF 接收器)。 ## 检测逻辑 每当账户成功登录时,Windows 都会记录 **EventCode 4624**。对于本实验而言,有趣的插曲在于 Logon Type 字段: - **Logon Type 10** — RemoteInteractive:典型的 RDP 会话 - **Logon Type 7** — Unlock:之前锁定的 RDP 会话被解锁,这仍然代表机器上的一个交互式会话 对这两种类型进行过滤可以捕获完整的 RDP 风格登录足迹。`Source_Network_Address` 携带原始 IP;空值或 `-` 值是本地登录,为了减少干扰已被剔除。对于“已授权与未授权”的判定,假设企业 IP 范围以 `40.` 开头,因此在演示场景中,任何不以此前缀开头的地址都被视为未授权。 最终搜索计划每分钟运行一次,覆盖过去 60 分钟的数据: ``` index=mydfir-ad EventCode=4624 (Logon_Type=7 OR Logon_Type=10) Source_Network_Address=* Source_Network_Address!="-" Source_Network_Address!=40.* | stats count by _time, ComputerName, Source_Network_Address, user, Logon_Type | sort -_time ``` `stats` 行纯粹是为了美观 —— 它将干扰较大的原始事件压缩为分析师进行 triage 实际需要的五个字段。 ## SOAR 工作流 ``` Splunk alert ──HTTP POST──▶ Shuffle webhook │ ▼ Discord (alert channel) │ ▼ Email user-input node ("Disable this user?") │ ┌───────┴───────┐ YES NO │ │ ▼ ▼ Active Directory (end — no action) disable user │ ▼ Get user attributes │ contains "Account disabled"? │ ▼ Discord (confirmation) "Account has been disabled" ``` 逐步说明: 1. Splunk 计划搜索触发,并将其结果 JSON POST 到 Shuffle webhook URI。 2. Shuffle 的 webhook 触发器对 payload 进行标准化;runtime 参数(如 `$exec.result.user`、`$exec.result.Source_Network_Address`、`$exec.result.search_name` 和 `$exec.result._time`)变得可供下游节点使用。 3. Discord HTTP 节点使用频道的传入 webhook URL,将格式化的告警发布到实验 Discord 服务器的 `#alerts` 频道。 4. 用户输入节点向分析师收件箱发送电子邮件,询问*“您想禁用该用户吗?”*,并提供一对 True/False 链接。 5. 如果选择 True,Active Directory 应用将通过 LDAP 进行身份验证(服务器 `10.22.96.4`,端口 389,base DN `CN=Users,DC=MyDFIR,DC=local`),并对告警 payload 中的用户执行 **Disable User** 操作。 6. 随后的 **Get User Attributes** 调用会获取 `userAccountControl`;workflow 根据响应是否包含 `ACCOUNT_DISABLED` 进行分支判断。 7. 如果禁用成功,第二个 Discord 节点将发布确认消息:`Account: 已被禁用。` ## 证据 / 结果 **环境配置** ![Vultr 虚拟机部署](https://static.pigsec.cn/wp-content/uploads/repos/2026/06/6c7dd5ac1a095034.png) ![Vultr 防火墙组](https://static.pigsec.cn/wp-content/uploads/repos/2026/06/488b734911095041.png) ![验证了机器之间的 VPC 连接性](https://static.pigsec.cn/wp-content/uploads/repos/2026/06/177894bc9a095048.png) **Active Directory 配置** ![AD DS 角色安装](https://static.pigsec.cn/wp-content/uploads/repos/2026/06/6a4acd6dbd095057.png) ![域控升级,创建 MyDFIR.local 林](https://static.pigsec.cn/wp-content/uploads/repos/2026/06/aa777460ba095059.png) ![创建 Jenny Smith (JSmith) 测试用户](https://static.pigsec.cn/wp-content/uploads/repos/2026/06/56c8dbfea4095105.png) ![测试机成功加入 MyDFIR.local](https://static.pigsec.cn/wp-content/uploads/repos/2026/06/45ad850474095109.png) **Splunk SIEM** ![在 Ubuntu 上安装 Splunk](https://static.pigsec.cn/wp-content/uploads/repos/2026/06/f9d16968c0095115.png) ![创建 mydfir-ad 索引](https://static.pigsec.cn/wp-content/uploads/repos/2026/06/cc2be9ae0f095122.png) ![在域控上安装 Universal Forwarder](https://static.pigsec.cn/wp-content/uploads/repos/2026/06/de75619b94095128.png) ![事件从两个 Windows endpoint 流入 mydfir-ad](https://static.pigsec.cn/wp-content/uploads/repos/2026/06/7790b17e3a095135.png) **检测和告警** ![Windows add-on 正确解析了 Source_Network_Address](https://static.pigsec.cn/wp-content/uploads/repos/2026/06/01767c89e4095141.png) ![使用 1 分钟 cron 计划保存未经授权的登录告警](https://static.pigsec.cn/wp-content/uploads/repos/2026/06/432e8d3ac8095147.png) ![在 Splunk 的 Activity 菜单中可见触发的告警](https://static.pigsec.cn/wp-content/uploads/repos/2026/06/dcb57b31f0095152.png) **SOAR 自动化** ![围绕 Splunk webhook 构建的 Shuffle workflow](https://static.pigsec.cn/wp-content/uploads/repos/2026/06/77d32d7e93095158.png) ![Discord 传入 webhook 配置](https://static.pigsec.cn/wp-content/uploads/repos/2026/06/a651e30304095204.png) ![分析师邮件提示 —— “您想禁用该用户吗?”](https://static.pigsec.cn/wp-content/uploads/repos/2026/06/b2d28f53cd095210.png) ![AD 禁用后回传到 Discord 的确认消息](https://static.pigsec.cn/wp-content/uploads/repos/2026/06/df11e14aad095217.png) ## 挑战与故障排除 **添加 workflow 机器人时 Slack OAuth 返回“Invalid permissions”。** Shuffle Slack 应用在免费 Slack 工作区上的 OAuth 授权步骤持续失败 —— Shuffle 请求的机器人作用域并不都能在我使用的工作区版本上授予。与其去折腾 Slack 工作区管理,不如将通知渠道换成 Discord。Discord 的传入 webhook 是一个单一的 URL,完全不需要 OAuth 握手,因此 Shuffle 中的 HTTP 节点可以直接使用最简单的 `{ "content": "..." }` JSON body 进行发布。整个渠道切换花了大约十分钟。 **Shuffle 云托管的 Active Directory 应用验证失败,报 MD4 哈希类型错误。** 当 AD 节点首次尝试通过 LDAP 绑定到 DC 时,它返回了一个引用 MD4 的 Python `hashlib` 异常 —— Shuffle 云 worker 中的底层 Python runtime 使用的是默认禁用 MD4 的 OpenSSL 版本,而 LDAP NTLM 身份验证路径正好调用了它。解决办法是退回使用管理员凭据直接进行简单绑定,设置 `useSSL=false` 并将 search base 设置为 `CN=Users,DC=MyDFIR,DC=local`。绑定成功了,**Get User Attributes** 调用返回了数据,**Disable User** 也起作用了。彻底的修复方案是运行一个由我控制 Python 镜像的自托管 Shuffle worker。 **VPC NIC 启动时得到的是 `169.254.x.x` APIPA,而不是 `10.22.96.x`。** 在每台 Windows 虚拟机上启用 VPC 并重启后,`ipconfig` 显示新的“Ethernet instance 02”适配器处于链路本地范围内,而不是 VPC 的 `10.22.96.0/20`。Vultr 的控制台不会将 DHCP 推送到 VPC NIC 上 —— 预期是由用户进行静态配置。修复方法是将其适配器设置为*使用以下 IP 地址*,并填入 Vultr UI 中的 VPC IP(DC 上为 `10.22.96.4`,测试机上为 `10.22.96.3`),子网掩码 `255.255.240.0`,DNS 指向加入域的主机的 DC。此后,从 DC `ping 10.22.96.5` 立即成功。 **添加 Vultr 防火墙规则后,端口 8000 上的 Splunk Web 无法访问。** 我在 Vultr 防火墙组中添加了限定在我的 IP 范围内的 TCP/8000 规则,刷新浏览器,但仍然出现连接超时。Ubuntu 主机运行着 `ufw`,并具有自己的默认拒绝入站策略。在 Splunk 主机上运行 `ufw allow 8000` 使 UI 立即加载。同样的双重防火墙模式在 UF 接收器的 9997 端口上又坑了我一次 —— 必须同时打开两层防火墙。 **首次登录时 Splunk 报告 IOWait 性能警告。** Splunk 主机(4 vCPU / 8 GB / 160 GB)的云虚拟机共享 CPU 规格对于实验来说没问题,但在初始索引历史 Windows 事件期间,Splunk 标记出了 IOWait 升高。我记录了这一点,确认磁盘实际上并未饱和,然后继续操作 —— 对于生产部署,这将促使我使用专用 CPU 和 NVMe 支持的磁盘。 **测试机上的 Universal Forwarder 安装无法接受本地 JSmith 用户。** Universal Forwarder MSI 在 Windows 账户下启动其服务,而测试工作站以 `JSmith`(一个没有本地管理员权限的普通域用户)身份登录。安装程序在服务账户步骤抛出异常。注销并以 `MyDFIR\Administrator` 身份(使用 Vultr 控制台上的域管理员凭据)重新启动 MSI 使安装得以完成;随后该服务被重新配置为在 `LocalSystem` 下运行,以便它可以读取 `WinEventLog:Security` 频道。 **必须在 `etc\system\local\` 中手动创建 `inputs.conf`。** 全新的 Universal Forwarder 安装仅在 `etc\system\default\` 下附带 `inputs.conf`,而 Splunk 的最佳实践是在 `local\` 中分层覆盖,而不是编辑默认值。我复制了该文件,以管理员身份在记事本中打开它,附加了以下内容: ``` [WinEventLog://Security] index = mydfir-ad disabled = false ``` 然后从 `services.msc` 重启了 **SplunkForwarder** 服务。几秒钟内,事件就开始进入 `mydfir-ad` 索引。 ## 经验教训 - **两个防火墙意味着两条规则。** 云平台防火墙和主机防火墙(`ufw`,Windows Defender 防火墙)是独立的。一个防火墙中的规则并不适用于另一个,测试期间的静默超时几乎总是可以追溯到我忘记的那一层。 - **VPC 不是自动配置的 —— 它只是被开通了。** 在 Vultr 中勾选启用 VPC 仅会添加 NIC。静态 IP、掩码、网关和 DNS 仍必须在客户端上设置,尤其是 DNS,它会因普通的“找不到域”错误而中断域加入过程。 - **Logon Type 比 EventCode 更重要。** 在任何真实环境中,仅靠 EventCode 4624 实在太吵了。将其与 Logon Type 7 和 10 结合使用,可将搜索范围缩小到交互式/远程交互式会话,这才是真正值得告警的攻击者常用技术。 - **云 SOAR 很方便,但也受限。** Shuffle 云 worker 中禁用 MD4 的 OpenSSL 版本悄无声息地破坏了 LDAP NTLM 路径,而且无法更换 runtime。对于实验之外的任何事情,自托管 worker 才是正确的答案。 - **引入分析师闭环的成本很低。** 用户输入节点将单次的“自动禁用” playbook 变成了一个 triage 流程 —— 告警、提示、确认、行动、再次确认 —— 只需大约五分钟的额外工作。这种模式几乎可以扩展到任何响应行动。 ## 未来改进 - [ ] 将 Shuffle 迁移到自托管实例,以解决 MD4 LDAP 问题,并通过 NTLM 绑定解除对 Disable User 操作的阻止 - [ ] 在 Splunk 旁集成 Wazuh HIDS,以进行基于主机的检测和文件完整性监控 - [ ] 为 RDP 登录分析构建 Splunk 仪表板 —— 地理位置、主要源 IP、登录类型细分、失败与成功比率 - [ ] 将检测覆盖范围扩展到暴力破解活动 (EventCode 4625),并添加一条相关性规则,用于检测同一来源的 N 次失败及其随后的 4624 登录 - [ ] 在分析师工作站网段和实验网段之间实施 pfSense,以练习网络隔离和 IDS 部署 ## 前置条件 - Vultr 账户(或任何支持 Windows Server 2022 和 Ubuntu 22.04 以及 VPC 功能的云服务提供商) - 关联到云账户的有效付款方式 - 本地 RDP 和 SSH 客户端 - 用于下载 Splunk Enterprise 和 Universal Forwarder 的 Splunk.com 账户 - Shuffle SOAR 账户(云端对于演示已足够;长期首选自托管) - 您拥有用于 webhook 控制权的 Discord 账户和服务器 - 具备 Windows 管理和 Linux 命令行的基础知识 ## 如何复现 按顺序阅读以下文档: 1. [01 — 环境配置](docs/01-environment-setup.md) — Vultr 虚拟机、防火墙组、VPC、静态 IP 修复 2. [02 — Active Directory 配置](docs/02-active-directory-config.md) — AD DS 安装、林创建、测试用户、域加入 3. [03 — Splunk 配置](docs/03-splunk-configuration.md) — Splunk 安装、Universal Forwarder 部署、遥测验证 4. [04 — 检测与告警](docs/04-detection-and-alerting.md) — EventCode 4624 SPL 搜索、计划告警 5. [05 — SOAR 自动化](docs/05-soar-automation.md) — Shuffle workflow、Discord webhook、分析师邮件、AD 禁用 有关外部参考资料、工具版本以及演示的 MITRE ATT&CK 技术,请参见 [references.md](references.md)。
标签:Active Directory, Checkov, PE 加载器, Plaso, SOAR, 安全实验室, 安全运营, 扫描框架