Ayyadi266/Detection-as-code

GitHub: Ayyadi266/Detection-as-code

一个基于四层证据模型的 Sigma 检测规则验证框架,通过将规则与真实攻击遥测和良性活动语料进行分层比对,诚实量化每条检测规则的有效性和误报风险。

Stars: 0 | Forks: 0

# 检测即代码 (Detection-as-Code) Sigma 检测规则映射到 MITRE ATT&CK,每一条规则均经过真实攻击遥测数据的验证,并与真实的良性活动进行比对——同时**明确追踪每一条规则背后的证据强度**,绝不夸大未经证实的内容。 本仓库有意保持较小的规模:共五条规则,涵盖 Windows Sysmon、原生 Windows 事件日志和 Linux syslog,其中包括一条真实的关联规则。其价值不在于数量,而在于证明每条规则有效性时所遵循的严格纪律,并清晰声明其不适用之处。 ## 本仓库致力于解决的问题 编写一条 Sigma 规则很容易。但证明它能检测到真实攻击,且不会让你淹没在误报中——这才是最困难的部分,也是大多数作品集所忽略的环节。 需要避免的具体失败模式如下: 因此,这里的每条规则都经过分层验证,并且每条规则都带有一个标签,准确标明其证据强度。仅针对自己编写的样本验证的规则会被标记为 **仅限测试样本 (fixture-only)**,并且永远不会被计入已验证规则中——这不是把它隐藏在脚注里,而是直接显示在生成的状态表中。 ## 证据模型 分为四个层级,严格区分,绝不混淆: | | **Tier 1 — 测试样本 (fixtures)** | **Tier 2 — 公开攻击** | **Tier 2b — 良性语料库** | **Tier 3 — 自生成数据** | |---|---|---|---|---| | 在 CI 中运行 | ✅ 每次推送 | ❌ 本地 | ❌ 本地 | ❌ 本地 | | 数据 | 我编写的 JSON 样本 | 来自 [EVTX-ATTACK-SAMPLES](https://github.com/sbousseaden/EVTX-ATTACK-SAMPLES) 的真实 EVTX | 真实良性机器遥测数据 | 我生成的真实遥测数据(Docker 中的 sshd/sudo) | | 引擎 | pySigma → SQL → SQLite | [Zircolite](https://github.com/wagga40/Zircolite) | Zircolite | pySigma → SQL → SQLite | | 检出意味着 | 测试按预期通过 | **真阳性**(好) | **潜在误报**(坏) | **真阳性**(好) | | **证明** | 无回归,无明显误报 (FP) | 能在*公开*的真实攻击中触发 | 在良性活动中的噪声程度 | 能在我制造的真实攻击中触发 | | **不能证明** | 真实世界的有效性 | 误报率 | 真阳性率 | 公开语料库的来源 | 为什么是四个层级而不是一个数字:每个层级回答了一个不同的问题,将它们合并会让薄弱的答案掩盖在强大的答案背后。具体来说: - **Tier 2b 是一种误报信号,绝不是验证徽章。** 命中良性数据是需要分诊排查的问题,而不是值得庆祝的事情。它是单独报告的,永远不会提升规则的验证状态。 - **Tier 3 是真实的,但属于自生成数据。** 目前没有类似于 EVTX-ATTACK-SAMPLES 的公开 Linux 攻击语料库,因此 Linux 规则是针对由容器中真实的 `sshd`/`sudo` 产生的遥测数据进行验证的——它确实是真实的,但在来源可靠性上弱于第三方语料库。它拥有自己的徽章和颜色,并且永远不会被描述为公开语料库验证。 生成的规则徽章如下: | 徽章 | 含义 | |---|---| | **已验证 (公开真实数据)** | 每个检测路径都能在公开攻击语料库中触发 | | **已验证 (自生成遥测)** | 每个路径都能在此处生成的真实遥测上触发 (Tier 3) | | **已验证 (部分)** | 部分路径已在真实数据上确认;至少有一个路径仅限测试样本,且已被指明 | | **仅限测试样本 (FIXTURE-ONLY)** | 仅通过自行编写的测试样本——证明的是自洽性,而非有效性 | | **未测试** | 无测试样本 | ## 状态 真实状态来源为 **[docs/coverage.md](docs/coverage.md)** —— 由运行器输出生成,绝不进行人工编辑。快照如下: | 规则 | ATT&CK | 日志来源 | 状态 | 误报 (FP) 信号 | |---|---|---|---|---| | [LSASS 进程访问](rules/windows/proc_access_lsass_suspicious.yml) | T1003.001 | Windows Sysmon EID 10 | 已验证 (部分) — 2/3 路径 | **未测量** (需要 Sysmon) | | [可疑的 PowerShell ScriptBlock](rules/windows/ps_scriptblock_suspicious_content.yml) | T1059.001 | Windows PowerShell 4104 | 已验证 (部分) — 4/5 路径 | 0 误报 / 81 条良性 | | [可疑服务创建](rules/windows/service_creation_suspicious_image.yml) | T1543.003 | Windows System 7045 | 已验证 (部分) — 2/3 路径 | 0 误报 / 48 条良性 | | [SSH 暴力破解](rules/linux/ssh_bruteforce.yml) | T1110.001 | Linux sshd (关联规则) | 已验证 (自生成) — 1/1 路径 | 0 误报 / 40 条良性 | | [Sudo 滥用](rules/linux/sudo_abuse.yml) | T1548.003 | Linux sudo | 已验证 (自生成) — 3/3 路径 | 0 误报 / 20 条良性 | 没有任何规则针对*公开*语料库得到完全验证,因为三个 Windows 规则各自包含一个没有匹配公开样本的检测路径(异常的 LSASS 访问掩码;编码的 PowerShell 路径;释放的二进制服务映像),而两个 Linux 规则根本没有公开语料库。这些事实在上面的徽章中清晰可见,而不是被掩盖过去。 ## 诚实的局限性 在此提前声明,因为一个隐藏自身盲区的验证测试工具比没有工具更糟糕。这些局限性中的每一项也都被记录在它所影响的对象旁边。 - **规则 1 的误报率尚未测量。** LSASS 访问 (Sysmon EID 10) 需要良性的 Sysmon 语料库,而捕获主机上未安装 Sysmon。这被报告为未测量——*而不是*零误报。这是一个具体的后续步骤(见下文),而不是隐秘的遗漏。 - **PowerShell 良性语料库(81 个事件)规模较小且不具代表性。** 它是在没有管理员权限的情况下捕获的,因此 Windows 只记录了它*已经*认为可疑的脚本块——这是一个在开发者机器上采集的、有偏见的样本。它证明了流水线的有效性并给出了早期信号;但可信的误报率需要随着时间的推移,在普通机器上启用完整的 Script Block 日志记录。这种偏见在覆盖率文档中紧挨着“0”被逐字陈述。 - **SSH 规则遗漏了低速分散的暴力破解。** 它按源 IP 统计失败次数;在多个 IP 上分散少量尝试的攻击者会低于触发阈值。这被设定为已知的局限性负向测试样本,而不是被隐藏起来。 - **`|cidr` 被 SQLite 后端近似**为 `LIKE` 前缀:对于 /8、/16、/24 是精确的,对于其他掩码则是近似的。 - **关联 `timespan` 在 SQL 中未被执行。** 后端是在整个评估的数据集中计算匹配项,而不是在滑动窗口中——对于有界限的捕获来说是正确的,在流式部署中则交由 SIEM 处理。这在规则和覆盖率文档中均有记录。 - **Tier 1 测试样本由作者编写**,只能捕获回归问题,永远不能证明有效性。这就是各层级被分开报告的全部原因。 ## 工作原理及原因 ### pySigma 是一个*转换器*,而不是*引擎* 这是最核心的决定。`SigmaRule` 没有 `.match()` 方法,`sigma-cli` 也没有 `test` 子命令——`sigma check` 是一个永远看不到事件的静态检查工具。必须由某个环节来实际执行查询。 规则使用 **`pySigma-backend-sqlite`** 转换为 SQL,并针对内存中的 SQLite 表运行。该后端由 SigmaHQ 维护,并且**与 Zircolite 内部使用的转换器相同**,因此 Tier 1(测试样本)和 Tier 2(真实 EVTX)共享相同的检测语义。当一条规则通过了 Tier 1 却在 Tier 2 中失败时,意味着*规则本身*出错了——而不是两个引擎不一致。保留这一信号才是核心意义所在。 被拒绝的替代方案及其原因: - **`sigma-rule-matcher`** 只需三行代码就能返回一个布尔值,但是当规则声明为 `EventID: 10` 而事件包含字符串 `"10"` 时,它会**静默返回 `False`**——这是一种静默的假阴性,这在验证工具中比没有工具更糟糕。(它还会在遇到 `Field: null`、布尔值和列表值字段时抛出异常。) - **手动实现的匹配器**意味着需要重新实现大约 40 个 Sigma 修饰符,其中的每一个 bug 都会变成一个不易察觉的错误检测声明。 - **Chainsaw / Hayabusa** 在 Tier 2 中各自携带独立的引擎(Hayabusa 还需要先转换规则),这会破坏 Tier 1 ↔ Tier 2 的语义一致性。 ### 会静默破坏结果的细节 - **SQLite 的 `NUMERIC` 列类型亲和性至关重要。** 如果没有亲和性,`EventID=10` 将无法匹配字符串 `"10"`——这正是导致 `sigma-rule-matcher` 被淘汰的那类静默假阴性。如果使用 `TEXT` 亲和性,`|gt: 9` 会由于按字典序比较而错误地拒绝 `"10"`。`NUMERIC` 是唯一能同时正确处理两者的选择;这是经过经验验证的,而非凭空假设。 - **测试样本是扁平的、Sigma 原生的 JSON** (`{"Image": ..., "CommandLine": ...}`),在转换时*不使用*任何 pipeline。原始 EVTX 形状的测试样本测试的将是 SigmaHQ 的字段映射 pipeline 而不是规则本身,因此一旦失败将无法定位原因。Zircolite 在查询之前正是将 EVTX 扁平化成这种形状,因此这两个层级自然趋同。 - **关联是真实的,不是伪造的。** SSH 暴力破解是一种关联(按源 IP 分组的 `event_count`),sqlite 后端会将其转换为 `GROUP BY ... HAVING event_count >= N`。一个单一的“密码错误”规则只能检测到一次输错密码的情况,而不是暴力破解——因此该规则是一个真正的基础规则加关联的组合。 - **Linux 没有公开语料库,因此它使用自生成的遥测数据。** 一个已提交的脚本会在 Docker 中启动真实的 `sshd`/`sudo`,驱动真实的登录失败 / sudo 滥用,并捕获实际的 `/var/log/auth.log`。这不是手工编写的日志行——而是真实的 daemon 输出。 ### 诚实机制(强制执行,而非口头承诺) - **部分验证由机器检查。** 每个规则的检测路径都在 `tests/variants.yml` 中声明;运行器从逐字引用的规则中为每个路径派生出子谓词,并验证标记为某个路径的测试样本实际触发的正是*该*路径(而不是另一个),且没有任何检测路径逃脱追踪。标记错误的测试样本或未被追踪的路径都会导致构建失败。 - **文档是生成的,绝不是手写的。** `docs/coverage.md` 和 `docs/attack_layer.json` 是从提交的 JSON 结果生成的。如果发生偏差,CI 会重新生成它们并报错,因此被减弱的规则不能遗留下一份盲目乐观的状态文档。 - **真实捕获数据永远不会被提交。** GPL-3.0 的 EVTX 样本和用户自己的机器遥测数据保留在被 gitignored 的 `.tools/` 目录下;只有确保无 PII(个人身份信息)的统计数字才会进入提交的结果中。 ## 后续步骤 明确且不隐藏——这些是进一步工作将会填补的诚实空白: 1. **测量规则 1 的误报率。** 安装 Sysmon 并开启 ProcessAccess (EID 10) 日志记录,捕获良性语料库,并将其添加到 Tier 2b 的映射中。在此之前,该规则对于真阳性是已验证(部分)的,但对于假阳性是未测量的。 2. **捕获具有代表性的 PowerShell 良性语料库。** 在一台日常使用的普通机器上启用完整的 Script Block 日志记录并让其累积,用值得信赖的语料库替换目前规模小且存在偏差的 81 事件语料库。具体步骤见 [docs/benign_corpus.md](docs/benign_corpus.md)。 3. **扩大公开语料库覆盖率**,在已有可用样本的情况下,推动规则从部分验证向完全的公开语料库验证迈进。 ## 快速开始 ``` pip install -r requirements.txt sigma check rules/ # static lint python scripts/test_rules.py --json results/tier1.json # Tier 1 (also all CI runs) ``` Tier 2 / 2b / 3 需要真实数据和额外工具,因此它们在本地运行: ``` # Tier 2(公开攻击)+ Tier 2b(良性语料库)— 需要 Zircolite(不在 PyPI 上) python scripts/validate_real.py --setup python scripts/validate_real.py --json results/tier2.json # Tier 3(自生成)— 需要 Docker bash scripts/gen_ssh_telemetry.sh # real sshd -> auth.log bash scripts/gen_sudo_telemetry.sh # real sudo -> auth.log python scripts/validate_selfgen.py --json results/tier3.json # 从上述所有内容重新生成 honest status docs python scripts/generate_coverage.py # -> docs/coverage.md python scripts/generate_heatmap.py # -> docs/attack_layer.json ``` ## ATT&CK 层 docs/attack_layer.json` 可加载到 [ATT&CK Navigator](https://mitre-attack.github.io/attack-navigator/) 中。技术根据**证据的强度**进行着色,而不是基于是否存在规则文件: - 🟩 **绿色** — 已针对公开攻击语料库验证 - 🟦 **蓝色** — 已针对自生成的遥测数据验证 (Tier 3) - 🟦 **青色** — 已验证(部分):真实数据已确认,但某个具名路径仅限测试样本 - 🟨 **琥珀色** — 仅限测试样本 - 🟥 **红色** — 未测试 每项技术还将其假阳性信号作为 tooltip 元数据携带(例如“0 个潜在误报 / 81 个良性事件”,或“误报率未测量”)。这刻意生成了一张看起来比通常的“技术有对应规则 → 绿色”热力图*更不起眼*的映射图。这正是其意图所在:颜色反映的是关于证据的真实情况,而非投入的努力。 ## 仓库结构 ``` rules/ windows/ LSASS access, PowerShell 4104, service creation 7045 linux/ SSH brute force (correlation), sudo abuse tests/ fixtures/ Tier 1: positive/ (must match), negative/ (must not match) variants.yml declared detection paths per rule (machine-checked) real_data/ mapping.yml Tier 2 samples, Tier 2b benign corpora, Tier 3 captures scripts/ sigma_engine.py shared: Sigma -> SQL, single-event + correlation evaluation test_rules.py Tier 1 runner (+ variant integrity checks) validate_real.py Tier 2 (public attacks) + Tier 2b (benign) via Zircolite validate_selfgen.py Tier 3 (self-generated telemetry) parse_authlog.py Linux auth.log -> flat events gen_ssh_telemetry.sh Tier 3 capture: real sshd in Docker gen_sudo_telemetry.sh Tier 3 capture: real sudo in Docker generate_coverage.py -> docs/coverage.md (generated) generate_heatmap.py -> docs/attack_layer.json (generated) results/ committed PII-safe result JSONs (docs are generated from these) docs/ GENERATED: coverage.md, attack_layer.json; and benign_corpus.md (procedure) .github/workflows/ci.yml Tier 1 + sigma lint + docs-staleness gate ``` 真实数据**未被内嵌 (vendored)**:`.tools/` (被 gitignored) 包含下载的 GPL-3.0 EVTX 样本、克隆的 Zircolite,以及本地捕获的良性/自生成遥测数据。
标签:AMSI绕过, Detection-as-Code, Sigma规则, URL发现, 威胁检测, 安全检测, 目标导入, 请求拦截, 逆向工具