suryatejpattem/apt29-detection-engineering
GitHub: suryatejpattem/apt29-detection-engineering
一个针对 8 项 APT29 攻击技术的检测工程项目,完整展示了 Sigma 规则编写、Splunk 转换、误报调优及 CI 自动化验证的闭环流程。
Stars: 1 | Forks: 0

# APT29 检测工程
这是一个涵盖 8 项 APT29 技术完整生命周期的检测工程项目:
运行技术、捕获遥测数据、编写 Sigma 规则、将其转换为 Splunk、
证明其能触发、针对正常的管理员活动测量误报,并对其进行调优。
范围限定于单台 Windows 工作站。检测结果分别在攻击窗口和受控的良性窗口中进行测量,因此误报数据是真实的,
而非假设的。
## 实验环境
```
[ WS01 - Windows 11 victim ] [ Ubuntu - Splunk ]
Sysmon (SwiftOnSecurity cfg, index=main
LSASS ProcessAccess enabled) receives :9997
PowerShell Script Block Logging
|
| Universal Forwarder ships 3 channels:
| WinEventLog:Security
| WinEventLog:Microsoft-Windows-Sysmon/Operational
| WinEventLog:Microsoft-Windows-PowerShell/Operational
+------------------------------------------------> Splunk
```
攻击在 WS01 上使用 Atomic Red Team 运行。一个单独的正常管理员活动区块(良性窗口)提供了误报基线。
## 仓库布局
```
apt29-detection-lab/
├── README.md
├── detections/
│ ├── T1059.001_powershell_encoded.yaml
│ ├── T1547.001_run_keys.yaml
│ ├── T1053.005_scheduled_task.yaml
│ ├── T1087_discovery.yaml
│ ├── T1136.001_create_account.yaml
│ ├── T1003.001_lsass.yaml
│ ├── T1218.005_mshta.yaml
│ ├── T1070.001_clear_logs.yaml
│ └── splunk_winevent_pipeline.yml # custom pySigma pipeline (EventID -> EventCode)
├── attacks/
│ └── raw-capture.md # per-technique notes: what each attack left behind
└── results/
├── results_table.md # full metrics table
├── discovery/ # screenshots + summary.md (one folder per technique)
├── powershell/
├── runkeys/
├── schtask/
├── account/
├── lsass/
├── mshta/
└── clearlogs/
```
## 检测是如何构建的(闭环过程)
每条规则都经历了相同的循环过程。以 T1059.001(编码的 PowerShell)为例:
**1. 在 WS01 上运行该技术**
```
Invoke-AtomicTest T1059.001 -TestNumbers 17
```
**2. 在 Splunk 中确认原始遥测数据**
```
index=main host=WS01 sourcetype="WinEventLog:Microsoft-Windows-Sysmon/Operational"
EventCode=1 Image="*powershell*" CommandLine="* -e *"
```
**3. 编写 Sigma 规则** (`detections/T1059.001_powershell_encoded.yaml`)
```
logsource:
category: process_creation
product: windows
detection:
selection_img:
Image|endswith: '\powershell.exe'
selection_flag:
CommandLine|contains: [' -e ', ' -enc', ' -EncodedCommand']
condition: selection_img and selection_flag
```
**4. 使用 pySigma 将 Sigma 转换为 Splunk**
```
sigma convert -t splunk -p sysmon -p detections/splunk_winevent_pipeline.yml \
detections/T1059.001_powershell_encoded.yaml
```
sysmon pipeline 映射了 Sigma 的通用字段名;自定义的
`splunk_winevent_pipeline.yml` 将 `EventID` 重写为 `EventCode`,因为
转发的 Windows 日志使用的是 `EventCode`。如果没有这一步,规则虽然能顺利转换,但
返回的结果会是零命中。安全日志规则 (4698/4720/1102) 仅使用自定义
pipeline 进行转换,而不使用 sysmon pipeline。
**5. 确认生成的搜索能返回攻击事件。** Index 和 sourcetype
会根据实际部署进行添加(Sigma 保持在环境无关的状态)。
## 测量方法
对于每条规则,在定义的窗口内:
- **TP** — 在真实攻击时触发
- **FP** — 在良性活动时触发
- **FN** — 遗漏的真实攻击实例
- **precision = TP / (TP + FP)**,**recall = TP / (TP + FN)**
每条规则测量两次:原始状态(调优前)和调优状态(调优后)。窗口:
- 攻击:各技术的时间戳记录在 `attacks/raw-capture.md` 中
- 良性:06/25 18:07–18:48(受控的管理员活动,无攻击)
指标来源于一个攻击窗口和一个 41 分钟的良性窗口——这是一个小样本
实验室测量,旨在展示调优效果,而非生产环境的基准测试。
## 结果
| # | 技术 | ATT&CK ID | 调优前 FP | 调优后 FP | 精确率 (原始 -> 调优) | 召回率 | 调优方法 |
|---|-----------------------|------------|-----------|----------|----------------------------|--------|--------------------------------------------------|
| 1 | 突发发现 | T1087.002 | 9 | 0 | 0.75 -> ~1.0 | 1.00 | 阈值:>=5 个不同的发现命令 / 5 分钟 |
| 2 | PowerShell 编码 | T1059.001 | 1 | 见备注 | 0.50 (见备注) | 1.00 | 通过 4104 检查解码脚本 |
| 3 | 注册表 Run 键 | T1547.001 | 1 | 0 | 0.50 -> 1.0 | 1.00 | 按目标路径过滤(可疑 vs 受信任) |
| 4 | 计划任务 | T1053.005 | 1 | 0 | 0.67 -> 1.0 | 1.00 | 按任务操作过滤(解释器/LOLBin) |
| 5 | 创建账户+权限提升| T1136.001 | 1 | 0 | 0.50 -> 1.0 | 1.00 | 基于目标 SID 关联 4720 -> 4732(Admin) |
| 6 | LSASS 转储 | T1003.001 | 0 | 0 | 1.0 | 1.00* | 无 — 高信号 comsvcs MiniDump 模式 |
| 7 | Mshta | T1218.005 | 0 | 0 | 1.0 | 1.00 | 无 — 精确到脚本/URL/.hta 以提高精确率 |
| 8 | 清除事件日志 | T1070.001 | 0 | 0 | 1.0 | 1.00 | 无 — 安全日志清除 (1102) 即是信号 |
在五条可调优的规则中 (1–5):平均精确率 **0.58 -> 0.90**,误报
**13 -> ~0**,召回率保持在 **1.00**(未遗漏任何攻击)。
\* LSASS 召回率在 comsvcs 方法下为 1.00;该规则在设计上针对性很强,不
涵盖其他转储方法。
**PowerShell 备注:** 原始的标志规则精确率为 0.50(它在一个良性的
编码命令上触发了)。调优是通过 4104 对解码脚本进行内容检查。在
这个实验室中,攻击测试 payload 和良性命令都解码为无害的
`Write-Host`,因此内容层不会对两者发出警报——无法声称获得了诚实的数值提升,因此该规则按原样报告。在
真实的入侵中,如果 payload 解码为下载器,内容层将标记出
攻击并放行良性命令。
## 结论
**1. 调优不是一刀切的。** 五条规则在合法活动上触发了,并且
每条都需要不同的方法:行为阈值、解码内容检查、
路径过滤、操作过滤以及事件序列关联。有三条规则在
本质上属于高信号——对于这些规则,正确的做法是测量并确认精确率,
然后保持原样,而不是发明一种数据无法支持的削减规则。
**2. `net` 在遥测数据中表现为 `net1` 运行。** `net group` / `net user` 在内部
作为 `net1.exe` 执行。仅匹配 `net ` 的规则会遗漏一半的发现活动;
匹配字符串已被更正,以便同时捕获两者。
**3. PPL 改变了 LSASS 检测。** 在 `RunAsPPL=2` 下,每个转储工具在
打开读取句柄之前都在内核层被拒绝了,因此 Sysmon EID 10 没有记录任何恶意
访问。可行的检测是命令模式 (EID 1, `comsvcs.dll MiniDump`),
无论转储是否成功,它都能捕获到尝试。在没有 PPL 的
主机上,访问掩码规则将是更强大的、与无关方法的检测。
**4. 多值 SID 破坏了简单的关联。** 关联账户创建 ->
提升为管理员失败了,因为 `Security_ID` 同时携带了操作者和目标,
并且操作者 SID 存在于每个事件中。解决方法是专门提取目标 SID
(在 New Account / Member 部分使用 `rex`)并基于此进行关联——
这也是生产环境中的方法,因为它不需要 admin-SID 允许列表。
**5. 集中式 SIEM 击败了本地日志清除。** 在主机上清除安全日志后,
1102 事件和所有先前的事件仍然在 Splunk 中(已经被
转发)。相同的清除操作通过三种方式被捕获:原生 1102、`wevtutil` 的 Sysmon 进程
创建,以及 PowerShell 4104。
**6. 在扩展之前验证字段映射。** 转发的 Windows 日志使用
`EventCode`,而不是 `EventID`。规则虽然能顺利转换,但在自定义
pipeline 重写该字段之前返回的结果是零命中——这在编写第一条规则时就发现了,
在编写其他七条规则之前。
## 自动化与验证
检测规则被视为代码。GitHub Actions 工作流
(`.github/workflows/validate-rules.yml`) 会在每次影响
`detections/` 的推送时运行,并使用 pySigma 将所有 Sigma 规则转换为 Splunk SPL。如果
任何规则停止编译,构建就会失败——因此损坏的规则会立即被发现,
而不是在以后才被发现。这就是“检测即代码”实践:版本控制,
自动验证的检测。
仓库包含每种检测的两种形式:
- `detections/*.yaml` — 可移植的 Sigma 规则(事实来源,由 CI 验证)
- `detections/spl/*.spl` — 实际部署的经过调优的 Splunk 查询,包括
存在于 SPL 而不是 Sigma 中的调优逻辑(阈值、关联、目标 SID 提取)。
标签:AI合规, AMSI绕过, OpenCanary, Sigma规则, 威胁检测, 安全, 目标导入, 超时处理