1. 一次自动化检测工程踩坑实录:数据基础决定上层建筑
做安全检测工程(Detection Engineering)的人,大概都动过同一个念头:能不能把 ATT&CK 映射、规则编写、测试验证、上线部署这一整套流程塞进 CI/CD 流水线里,让 Jenkins 帮我们把活儿干了?我们团队也不例外。去年有段时间,我花了不少精力尝试用 Jenkins 搭建一套检测规则的自动化流水线,目标很明确——规则写完自动跑测试、自动比对 ATT&CK 覆盖率、自动推到 SIEM(我们用的是 Splunk)里生效。听起来很美好对吧?但实际做下来,最大的拦路虎根本不是 Jenkins 配置有多复杂,也不是 CI/CD 流程设计有多难,而是数据本身根本不到位。
这篇文章我想把这段经历完整拆开讲。核心关键词包括 Jenkins、CI/CD、ATT&CK、SIEM、Splunk,也会涉及 Jenkins 可用环境变量、Jenkins 安装与配置、Jenkins 自动部署这些实操层面的东西。如果你正在做安全检测工程,或者正在尝试把安全运营流程自动化,又或者你是个刚接触 Jenkins 想拿它做点安全相关事情的工程师,这篇内容应该能帮你少走一些弯路。我会先讲整体设计思路,再拆核心细节,然后给实操过程,最后把踩过的坑整理成排查清单。文章会比较长,因为这件事本身就不是三言两语能说清的。
先说结论:自动化检测工程这件事,技术栈不是瓶颈,数据质量才是。没有足够干净、足够结构化、足够有标注的数据,你搭再漂亮的 Jenkins 流水线,跑出来的也只是“自动化地产生垃圾”。
2. 整体设计思路与方案选型拆解
2.1 为什么想到用 Jenkins 做检测工程自动化
先说说动机。检测工程的核心工作流大致是这样的:安全团队根据威胁情报、ATT&CK 战术技术矩阵、内部事件复盘,编写检测规则(Splunk SPL 查询、Sigma 规则、YARA 规则等),然后这些规则需要经过测试、调优、上线、持续维护。问题在于,当规则数量到了几百上千条,纯靠人工管理就非常痛苦——哪条规则覆盖了 ATT&CK 的哪个技术点?哪条规则最近误报率飙升?哪条规则因为日志源变更已经失效了?这些问题靠 Excel 表格根本管不过来。
我们当时的想法很直接:既然软件工程有 CI/CD,那检测工程为什么不能有?Jenkins 作为最成熟的持续集成工具之一,天然适合做这种“代码提交→自动测试→自动部署”的流程。具体来说,我们希望实现:
- 规则以代码形式存储在 Git 仓库里,每次提交触发 Jenkins 流水线
- Jenkins 自动拉取规则,做语法校验、单元测试、ATT&CK 覆盖率比对
- 测试通过后,自动通过 Splunk REST API 把规则推送到 SIEM 环境
- 每次部署生成报告,记录规则变更和覆盖率变化
这个设计在纸面上非常合理。Jenkins 的 Pipeline as Code 能力、丰富的插件生态、环境变量管理机制,都让它可以胜任这个角色。而且 Jenkins 安装与配置成本不高,团队里本来就有一套 Jenkins 在跑应用部署,复用现成基础设施很划算。
2.2 方案架构与关键选型考量
整体架构我画不出图(也不打算画),但可以用文字描述清楚。核心分四层:
第一层是规则仓库层。所有检测规则以 Sigma 格式或原生 SPL 格式存放在 GitLab 仓库中,每条规则附带元数据:规则 ID、作者、创建日期、关联的 ATT&CK 技术编号、日志源依赖、严重级别等。元数据用 YAML front matter 写在规则文件头部,方便程序解析。
第二层是 Jenkins 流水线层。用 Jenkinsfile 定义多阶段流水线:Checkout → Lint → Unit Test → Coverage Analysis → Deploy to Staging → Integration Test → Deploy to Production。每个阶段都有明确的通过/失败条件。Jenkins 可用环境变量在这里扮演关键角色,比如用BUILD_NUMBER标记每次部署版本,用GIT_COMMIT追踪规则变更来源,用WORKSPACE定位工作目录。
第三层是测试数据层。这是整个方案的核心依赖。要做单元测试,你需要有“已知答案”的日志数据——也就是说,你得有一批标注好的日志样本,明确知道哪些是恶意行为、哪些是正常行为,然后用这些数据去验证规则是否能正确命中。理想情况下,这些数据来自历史安全事件、红队演练记录、或公开的测试数据集。
第四层是 SIEM 部署层。通过 Splunk REST API 或 Splunk SDK 实现规则的自动化部署。Splunk 提供了/services/saved/searches接口,可以创建、更新、删除告警规则。Jenkins 在部署阶段调用这些接口,把测试通过的规则推送到目标环境。
选型上,我们对比过几个方案。用 GitLab CI 也可以,但团队对 Jenkins 更熟悉;用 GitHub Actions 也行,但我们的代码仓库在私有 GitLab 上;用 Python 脚本直接跑也不是不行,但缺少 Jenkins 那种成熟的流水线管理和可视化能力。最终选 Jenkins,核心原因是团队已有基础设施 + 环境变量管理成熟 + 插件生态丰富。
2.3 预期收益与现实落差
按照最初的设想,这套流水线上线后应该带来几个明显收益:规则上线周期从平均 3 天缩短到 2 小时;ATT&CK 覆盖率实时可见;规则质量通过自动化测试得到保障;误报率因为有了回归测试而显著下降。
现实是,流水线本身跑起来了,Jenkins 安装与配置没花太多时间,Jenkins 自动部署也实现了。但跑了几周之后我们发现,流水线跑得越顺畅,产出的“通过测试”的规则反而越让人不放心。原因很简单:测试数据不够真实、不够全面、不够有代表性。很多规则在测试数据集上表现完美,一上生产环境就疯狂误报或者完全静默。这就是标题说的“The Data Wasn't There”——数据基础没打好,自动化只是加速了错误的发生。
3. 核心细节解析与实操要点
3.1 Jenkins 流水线的关键配置细节
先讲 Jenkins 这边的实操。Jenkins 安装与配置本身不是难点,用 Docker 跑一个 Jenkins LTS 版本,挂载好卷,装几个必要插件就能用。关键插件包括:Git Plugin(拉代码)、Pipeline Plugin(流水线)、Credentials Binding Plugin(管理 Splunk API 凭证)、HTTP Request Plugin(调用 Splunk API)。
Jenkinsfile 的结构我简化成一个可参考的模板:
pipeline { agent any environment { SPLUNK_HOST = 'splunk-staging.internal' SPLUNK_TOKEN = credentials('splunk-api-token') RULES_DIR = "${WORKSPACE}/detection-rules" } stages { stage('Checkout') { steps { git branch: 'main', url: 'git@gitlab.internal:security/detection-rules.git' echo "Building commit: ${GIT_COMMIT}" echo "Build number: ${BUILD_NUMBER}" } } stage('Lint') { steps { sh ''' pip install sigma-cli yamllint yamllint ${RULES_DIR}/*.yml sigma check ${RULES_DIR}/ ''' } } stage('Unit Test') { steps { sh ''' python3 tests/run_rule_tests.py \ --rules-dir ${RULES_DIR} \ --test-data tests/data/ \ --output reports/unit-test-${BUILD_NUMBER}.json ''' } } stage('ATT&CK Coverage') { steps { sh ''' python3 scripts/coverage_analysis.py \ --rules-dir ${RULES_DIR} \ --output reports/coverage-${BUILD_NUMBER}.json ''' } } stage('Deploy to Staging') { when { branch 'main' } steps { sh ''' python3 scripts/deploy_rules.py \ --host ${SPLUNK_HOST} \ --token ${SPLUNK_TOKEN} \ --rules-dir ${RULES_DIR} \ --env staging ''' } } } post { always { archiveArtifacts artifacts: 'reports/*.json', fingerprint: true } } }这段 Jenkinsfile 里,有几个 Jenkins 可用环境变量值得单独说。WORKSPACE是当前构建的工作目录,所有相对路径都基于它;BUILD_NUMBER是自增的构建编号,用来标记每次部署的版本;GIT_COMMIT是当前构建对应的 Git 提交哈希,用来追溯规则变更。这些变量在调试时非常有用,比如你发现某次部署后规则异常,可以直接用BUILD_NUMBER和GIT_COMMIT定位到具体是哪次提交引入的问题。
注意:Jenkins 的
credentials()函数会把凭证绑定到环境变量,但在sh步骤中直接 echo 凭证会导致泄露。永远不要在日志里打印凭证内容。
3.2 检测规则测试框架的设计难点
测试框架是整个方案里最复杂的部分。我们设计了一个 Python 测试框架,核心逻辑是:加载规则文件,解析出规则中的检测逻辑,然后拿测试数据集去跑,看规则是否按预期命中。
规则测试的基本流程:
- 解析规则文件,提取 SPL 查询或 Sigma 规则逻辑
- 加载对应的测试数据集(JSON 格式的日志样本)
- 把测试数据导入临时 Splunk 索引(或用本地模拟引擎)
- 执行规则查询,获取命中结果
- 比对命中结果与预期结果(测试数据中标注了哪些事件应该被命中)
- 生成测试报告
听起来很清晰,但实际做起来问题一大堆。首先是测试数据的格式问题。Splunk 的日志格式非常灵活,同一个字段在不同日志源里可能叫不同名字。比如源 IP 字段,有的日志叫src_ip,有的叫source_address,有的叫client_ip。规则里写死了字段名,测试数据里用的是另一个名字,测试就失败了——但这不是规则的问题,是数据规范化的问题。
其次是测试数据的标注问题。要验证规则是否正确,你得知道测试数据里哪些事件是“恶意”的、哪些是“正常”的。这个标注工作极其耗时,而且容易出错。我们最初尝试用红队演练的日志做测试数据,但红队演练的日志量太大,标注成本太高。后来退而求其次,用人工构造的小样本数据集,但构造的数据又不够真实,覆盖不了生产环境的各种边界情况。
3.3 ATT&CK 覆盖率分析的实现与局限
ATT&CK 覆盖率分析是另一个核心模块。逻辑很简单:解析所有规则文件中的 ATT&CK 技术编号,去重后与 ATT&CK 矩阵做比对,算出覆盖率。我们用的是 MITRE 官方提供的 ATT&CK STIX 数据,解析出所有技术编号,然后和规则中的编号做交集。
import json from stix2 import MemoryStore def load_attack_techniques(stix_file): store = MemoryStore(stix_file) techniques = store.query([ Filter('type', '=', 'attack-pattern') ]) return {t.external_references[0].external_id: t.name for t in techniques if t.external_references} def analyze_coverage(rules_dir, attack_techniques): covered = set() for rule_file in Path(rules_dir).glob('*.yml'): with open(rule_file) as f: rule = yaml.safe_load(f) for tag in rule.get('tags', []): if tag.startswith('attack.t'): technique_id = tag.replace('attack.', '').upper() covered.add(technique_id) total = len(attack_techniques) covered_count = len(covered & set(attack_techniques.keys())) coverage_pct = covered_count / total * 100 return { 'total_techniques': total, 'covered': covered_count, 'coverage_percentage': round(coverage_pct, 2), 'uncovered': list(set(attack_techniques.keys()) - covered) }这个分析本身没问题,跑出来的覆盖率数字也很直观。但问题在于,覆盖率数字好看不代表检测能力真的强。一条规则可能标记了某个 ATT&CK 技术编号,但实际检测逻辑非常粗糙,误报率极高,或者只能检测该技术下非常特定的一种变体。覆盖率分析只能告诉你“有没有”,不能告诉你“好不好”。
我们后来在覆盖率分析的基础上加了一个“规则质量评分”维度,综合考虑规则的测试通过率、误报率(基于历史告警数据)、日志源依赖的稳定性等因素。但这个评分本身也很粗糙,因为误报率数据依赖于生产环境的告警反馈,而告警反馈又依赖于分析师的人工标注,整个链路太长,数据回流太慢。
3.4 Splunk 自动部署的关键接口与注意事项
Splunk 的自动部署通过 REST API 实现。核心接口是/services/saved/searches,支持 POST(创建)、GET(查询)、DELETE(删除)。部署脚本的逻辑是:读取规则文件,转换成 Splunk 保存搜索的 JSON 格式,然后调用 API 创建或更新。
import requests def deploy_rule(splunk_host, token, rule): url = f"https://{splunk_host}:8089/services/saved/searches" headers = { "Authorization": f"Bearer {token}", "Content-Type": "application/x-www-form-urlencoded" } payload = { "name": rule['name'], "search": rule['search'], "cron_schedule": rule.get('schedule', '*/5 * * * *'), "dispatch.earliest_time": rule.get('earliest_time', '-5m'), "dispatch.latest_time": rule.get('latest_time', 'now'), "alert_type": "number of events", "alert_comparator": "greater than", "alert_threshold": rule.get('threshold', 0), "actions": "email", "action.email.to": rule.get('alert_email', 'soc@internal') } response = requests.post(url, headers=headers, data=payload, verify=False) if response.status_code not in (200, 201): raise Exception(f"Deploy failed: {response.status_code} - {response.text}") return response.json()这里有几个坑要注意。第一,Splunk REST API 默认使用 8089 管理端口,不是 8000 Web 端口,别搞混。第二,verify=False关闭了 SSL 证书验证,生产环境应该配置正确的证书。第三,创建和更新用的是同一个接口,如果规则已存在,POST 会更新而不是报错,但前提是name字段完全匹配。第四,部署后规则不会立即生效,Splunk 需要重新加载配置,可以通过/services/configs/conf-savedsearches/_reload接口触发重载。
提示:在 staging 环境部署测试通过后,不要直接推生产。我们后来加了一个“灰度部署”阶段,先推 10% 的规则到生产,观察 24 小时告警情况,确认无误后再全量部署。
4. 实操过程与核心环节实现
4.1 环境搭建与 Jenkins 初始化配置
环境搭建这部分,我用的是 Docker Compose 方式,因为最省事。Jenkins 官方镜像jenkins/jenkins:lts直接拉下来,挂载两个卷:jenkins_home存配置和构建历史,workspace存构建工作目录。端口映射 8080(Web UI)和 50000(Agent 通信)。
version: '3' services: jenkins: image: jenkins/jenkins:lts container_name: jenkins-detection ports: - "8080:8080" - "50000:50000" volumes: - jenkins_home:/var/jenkins_home - ./workspace:/var/jenkins_home/workspace environment: - JAVA_OPTS=-Djenkins.install.runSetupWizard=false - JENKINS_OPTS=--prefix=/jenkins restart: unless-stopped volumes: jenkins_home:初始化配置步骤:
- 启动容器后,访问
http://localhost:8080/jenkins,用初始密码解锁(密码在容器日志里,或者jenkins_home/secrets/initialAdminPassword文件里) - 安装推荐插件,然后手动补装 Git、Pipeline、Credentials Binding、HTTP Request、Docker Pipeline 这几个
- 创建管理员账号,配置 Jenkins URL
- 在“系统管理→全局工具配置”里配置 JDK、Git、Python 路径
- 在“系统管理→凭证管理”里添加 Splunk API Token 凭证,ID 设为
splunk-api-token - 创建 Pipeline 任务,指向 Git 仓库中的 Jenkinsfile
Jenkins 可用环境变量在配置时就要规划好。除了前面提到的WORKSPACE、BUILD_NUMBER、GIT_COMMIT,还有几个常用的:JOB_NAME(任务名称)、BUILD_URL(构建 URL,用于通知)、GIT_BRANCH(当前分支)。这些变量在流水线脚本里可以直接引用,不需要额外定义。
4.2 规则仓库的结构设计与元数据规范
规则仓库的结构直接决定了后续自动化流程能不能跑通。我们最终确定的结构是这样的:
detection-rules/ ├── rules/ │ ├── windows/ │ │ ├── T1059_command_shell.yml │ │ ├── T1055_process_injection.yml │ │ └── ... │ ├── linux/ │ │ ├── T1059_unix_shell.yml │ │ └── ... │ └── network/ │ ├── T1071_web_protocol.yml │ └── ... ├── tests/ │ ├── data/ │ │ ├── windows_t1059_sample.json │ │ └── ... │ └── run_rule_tests.py ├── scripts/ │ ├── coverage_analysis.py │ └── deploy_rules.py ├── reports/ └── Jenkinsfile每条规则的 YAML 文件包含元数据和检测逻辑:
title: Suspicious Command Shell Execution id: 5f2a1b3c-4d5e-6f7a-8b9c-0d1e2f3a4b5c status: stable description: Detects suspicious command shell execution patterns author: Security Team date: 2024/01/15 tags: - attack.execution - attack.t1059.001 logsource: category: process_creation product: windows detection: selection: EventID: 4688 CommandLine|contains: - 'powershell -enc' - 'cmd /c' - 'wmic process call create' condition: selection falsepositives: - Legitimate admin scripts level: medium这个结构的关键在于tags字段里的 ATT&CK 技术编号,覆盖率分析直接依赖它。logsource字段定义了规则依赖的日志源,部署脚本会根据这个字段检查目标 SIEM 环境是否有对应的日志接入。detection字段是核心检测逻辑,测试框架会解析这个字段并转换成可执行的查询。
4.3 测试数据准备与标注的实操流程
测试数据是整个方案里最耗人力的部分。我们的实操流程是:
- 数据采集:从生产 Splunk 环境导出历史日志,按日志源分类(Windows 安全日志、Sysmon、防火墙日志等)
- 数据脱敏:用脚本替换日志中的真实 IP、用户名、主机名,避免敏感信息泄露
- 数据标注:由安全分析师人工标注每条日志是“恶意”还是“正常”,标注结果写入 JSON 文件的
label字段 - 数据切分:按 7:3 比例切分为训练集和测试集,训练集用于规则调优,测试集用于最终验证
- 数据版本管理:测试数据集也纳入 Git 管理,每次更新记录变更原因
标注这一步是最痛苦的。我们最初尝试让分析师逐条标注,但一天只能标几百条,而一条规则可能需要上千条测试数据才能充分验证。后来改用“半自动标注”:先用现有规则跑一遍,把命中的日志标为“疑似恶意”,未命中的标为“疑似正常”,然后让分析师复核。这样效率提高了不少,但引入了新的问题——如果现有规则本身就有偏差,标注结果也会有偏差。
实操心得:测试数据不在多,在精。我们最后维护了一个约 5000 条日志的核心测试集,覆盖了最常见的 20 个日志源和 50 个 ATT&CK 技术点。这个规模足够验证大部分规则,又不会让标注成本失控。
4.4 流水线运行与部署验证的完整过程
流水线跑起来之后,每次规则提交的完整流程是这样的:
- 开发者在本地编写规则,用
sigma check做基本语法校验 - 提交到 Git 仓库的 feature 分支,触发 Jenkins 流水线
- Jenkins 拉取代码,执行 Lint 阶段,检查 YAML 格式和 Sigma 语法
- 执行单元测试,用测试数据集验证规则命中情况
- 执行覆盖率分析,更新 ATT&CK 覆盖率报告
- 如果所有阶段通过,合并到 main 分支,触发部署流水线
- 部署到 staging 环境,跑集成测试(用 staging 的真实日志验证)
- 集成测试通过后,灰度部署到生产环境
- 观察 24 小时,确认无误后全量部署
这个流程跑通之后,规则上线周期确实缩短了。从提交到生产部署,最快 2 小时就能完成。但问题也随之而来:流水线通过率太高了。几乎 90% 的规则提交都能一次通过所有测试,但上线后真正有效的规则不到 60%。剩下的 40% 要么误报率太高被分析师关掉,要么完全检测不到任何东西。
我们分析后发现,根本原因是测试数据集和生产环境的日志分布差异太大。测试数据集里的日志是精心挑选的,字段规范、格式统一;生产环境的日志来自几十个不同的日志源,字段命名混乱、格式参差不齐、还有大量噪声。规则在测试集上表现完美,一到生产就水土不服。
5. 常见问题与排查技巧实录
5.1 Jenkins 流水线常见故障与排查
问题一:流水线卡在 Checkout 阶段
最常见的原因是 Git 凭证配置错误或网络不通。排查步骤:检查 Jenkins 凭证管理里的 SSH 密钥是否正确;在 Jenkins 容器内手动执行git ls-remote测试连通性;检查 Git 仓库的访问权限是否包含 Jenkins 的部署密钥。
问题二:环境变量在 sh 步骤中为空
Jenkins 的环境变量在environment块中定义后,在sh步骤中应该可以直接引用。如果为空,检查变量名是否拼写错误,或者是否在withEnv块中正确传递。另外注意,credentials()绑定的变量在sh步骤中会自动脱敏,打印出来是****,这是正常行为。
问题三:Splunk API 调用返回 401
凭证问题。检查 API Token 是否过期,检查 Token 是否有创建保存搜索的权限。Splunk 的 Token 权限模型比较细,需要确保 Token 关联的角色有edit_saved_searches和schedule_search权限。
问题四:部署后规则不生效
Splunk 的配置重载有延迟。部署脚本执行完后,需要调用_reload接口或等待 Splunk 自动重载(默认 60 秒)。另外检查规则的cron_schedule是否正确,如果调度时间设置得太长,规则可能还没到执行时间。
5.2 检测规则测试中的典型问题
问题一:规则在测试环境通过,生产环境误报
这是最典型的问题。排查思路:对比测试数据集和生产日志的字段分布,找出差异点;检查规则中的阈值设置是否过于宽松;用生产环境的误报样本反向测试规则,看是否能复现。
问题二:规则完全检测不到任何事件
可能的原因:日志源没有正确接入 Splunk;规则中的字段名与实际日志字段名不匹配;规则的时间窗口设置太窄;Splunk 索引的权限限制导致规则查询不到数据。
问题三:ATT&CK 覆盖率数字虚高
规则标记了 ATT&CK 技术编号,但实际检测逻辑与编号不匹配。排查方法:人工抽查标记了特定技术编号的规则,验证其检测逻辑是否真的覆盖了该技术。我们后来加了一个“规则-技术匹配度”人工复核环节,每季度抽查 20% 的规则。
5.3 数据质量问题的排查清单
数据问题是整个方案的核心瓶颈。我整理了一个排查清单,按优先级排序:
| 问题类型 | 表现 | 排查方法 | 解决思路 |
|---|---|---|---|
| 字段命名不一致 | 规则在测试集命中,生产不命中 | 对比测试集和生产日志的字段名 | 建立字段映射表,规则中使用标准化字段名 |
| 日志格式差异 | 同一日志源不同设备格式不同 | 抽样检查各设备日志格式 | 用 Splunk 的字段提取规则统一格式 |
| 数据标注错误 | 规则测试结果与预期不符 | 人工复核标注样本 | 建立标注复核机制,双人交叉验证 |
| 数据量不足 | 规则测试通过但覆盖场景有限 | 统计测试集的场景覆盖度 | 补充边界场景数据,增加负样本 |
| 数据时效性差 | 规则检测不到新型攻击 | 对比测试集时间范围与当前威胁 | 定期更新测试集,纳入最新威胁样本 |
避坑技巧:在规则提交前,强制要求开发者提供至少 3 个正样本和 3 个负样本。正样本证明规则能命中,负样本证明规则不会误报。这个要求虽然增加了开发者的工作量,但显著提高了规则质量。
5.4 自动化流程的边界与人工介入时机
跑了几个月之后,我们逐渐摸清了自动化流程的边界。以下环节适合自动化:规则语法校验、单元测试、覆盖率统计、部署到 staging、基础集成测试。以下环节必须人工介入:规则逻辑审核、ATT&CK 技术匹配度复核、生产环境灰度观察、误报根因分析、测试数据标注。
自动化不是要取代人,而是把人从重复劳动中解放出来,让人专注于真正需要判断力的工作。我们后来调整了流程,把自动化定位为“辅助工具”而不是“决策者”。规则能不能上线,最终还是要靠安全分析师拍板。
6. 从这次踩坑中沉淀下来的经验
回过头看,这次尝试最大的收获不是搭了一套 Jenkins 流水线,而是深刻理解了“数据基础决定上层建筑”这句话在安全检测工程里的分量。Jenkins 安装与配置、Jenkins 自动部署、CI/CD 流程设计,这些技术层面的东西都有成熟的方案可以借鉴,花时间就能搞定。但数据问题——测试数据的采集、标注、维护、更新——没有任何捷径可走,必须投入真实的人力和时间。
如果让我重新做一次,我会把顺序倒过来:先花 60% 的精力把测试数据集建好,再花 30% 的精力设计规则测试框架,最后花 10% 的精力搭 Jenkins 流水线。而不是像这次一样,先花 70% 的精力搭流水线,最后发现数据根本撑不起来。
另外一点体会是,ATT&CK 覆盖率这个指标要谨慎使用。它适合用来做宏观趋势分析,不适合用来做规则质量的唯一评判标准。一条规则覆盖了某个技术点,不代表它能检测到该技术下的所有攻击变体;反过来,一条规则没有标记 ATT&CK 编号,也不代表它没有检测价值。我们后来在覆盖率报告里加了“规则质量评分”和“生产验证状态”两个维度,让报告更贴近实际情况。
最后分享一个我们后来养成的习惯:每次规则上线后,强制要求分析师在 72 小时内给出反馈——这条规则有没有产生告警?告警是否有效?有没有误报?这个反馈数据回流到测试数据集里,形成闭环。虽然手动反馈效率不高,但这是目前我们找到的最可靠的数据质量提升方式。等反馈数据积累到一定量级,也许可以训练一个模型来自动评估规则质量,但那又是另一个故事了。