在第一部分中,我们介绍了 Detection-as-Code(检测即代码),涵盖了其核心概念和优势,以及现代威胁检测实践中必不可少的检测开发生命周期(Detection Development Life Cycle,DDLC)。
在实践检测即代码系列的第二部分中,我们将探讨设计检测开发、存储和部署仓库的基本要素。我们将深入了解多个设置方面,包括 Git 平台选择、分支策略、仓库结构、检测结构、分类体系以及内容包。这些都是在设计仓库时必然会遇到的核心元素,提前进行深入思考至关重要,这样可以避免后续不必要的重构工作,确保我们的工作尽可能井然有序且结构化。
但需要提前说明的是,这些原则、方法论和设计元素应当作为可调整的蓝图使用,以满足团队的个性化需求。适用于专门从事检测工程的大型团队的方法,可能并不适合承担混合角色和职责的小型团队。你的最终目标应该是将这些元素融入到内部流程中,为检测工程的日常工作提供结构化框架并提升效率。务必警惕过度工程化,因为这可能会消耗资源却无法带来显著价值。
选择 Git 平台
实施检测即代码方法的第一步是选择 Git 平台。你可以选择 GitHub、GitLab、AWS CodeCommit、Azure DevOps 或其他平台,具体取决于组织的首选技术栈。在本博客系列中,我们将提供托管在 Azure DevOps 上的仓库示例。
标准化检测结构
下一步是标准化存储在仓库中的检测规则。在检测即代码的框架下,标准化指的是在检测库中强制执行统一的结构和格式。遵循预定义的约定集合,将帮助我们更高效地维护和搜索检测库。
使用 YAML 或 JSON 来存储检测规则是一种久经考验的方法。这些数据序列化格式具有结构化、人类可读以及与 CI/CD 良好集成的优势。此外,许多平台都支持直接以 JSON、YAML 甚至 XML 格式导出规则。
检测规则可用的元数据字段因平台而异。一些平台允许存储标签和注释,而其他平台仅限于标题和描述字段。如果需要支持多个平台,这种可用字段的不一致性可能会产生问题。在这种情况下,在检测规则旁边维护专用的元数据文件可能是一种有益的方法。为了获得关于元数据文件应包含哪些信息的参考(以便检测规则得到充分记录),可以参考 Sigma Specification [1](这是一个供应商无关的检测格式)或 Palantir 的 Alerting and Detection Strategy Framework [2]。你可以采用并扩展其中一个,或者创建自己的标准。无论选择哪个,我们建议至少包括以下字段:
id: # A unique identifier for the detection.
title: # A brief title for the detection.
description: # A comprehensive description of the detection.
level: # Severity of the detection (low, medium, high).
version: # The version of the detection that we are on.
references: # References to the source(s) that the detection was derived from e.g. blogs, papers, presentations, tweets.
-
data_sources: # The data source on which the detection relies.
-category: # The category of the log source e.g. dns, network, os.
vendor: # The vendor e.g. cisco, microsoft.
product: # The product e.g. asa, windows.
service: # The service e.g. traffic_logs, security_event, antivirus.
event_id: # The event ID used e.g. ASA-3-201008, 4688
blindspots: # Recognized shortcomings of the detection.
-
known_false_positives:# A list of known false positives that may occur.
-
investigation_steps: # Investigation steps that the analyst can follow to investigate an alert generated by this detection.
-
tags: # Taxonomies or notable things about the detection.
-tactic.$tactic # MITRE ATT&CK tactics.
-technique.tXXXX.XXX# MITRE ATT&CK (sub)techniques.
-group.gxxx # MITRE ATT&CK adversary group name.
-software.sxxx # MITRE ATT&CK software name.
-car.XXXX-XX-XXX # MITRE Cyber Analytics IDs.
-cve.xxxx-xxxxxx # CVE IDs.
-notable.$entity # Notables about the detection e.g. name of lolbin.
一个示例如下:
利用分类体系
分类体系提供了一种结构化的方式来将检测规则分类和组织成逻辑组。这增强了检测库的可搜索性,并通过将其映射到已知框架(如 MITRE ATT&CK 或 CAR)来为每个检测的目标和范围提供上下文。可以使用的一些分类体系示例包括:
-
类别: application、cloud、dns、network、ids、os、proxy… -
MITRE ATT&CK: tactic.defense_evasion、technique.t1548、group.g1046、software.s002… -
MITRE CARs: car.2013-01-002… -
CVEs: cve.2021-44228… -
Notable 实体: notable.rundll32、notable.regsvr32、notable.registry_run、notable.registry_run_once…
在上面的示例中,分类体系被用作标签或作为 data_sources 字段的一部分。
利用内容包
内容包是捆绑在一起的相关检测规则集合。它们帮助检测工程团队维护和部署一组针对特定威胁或技术的检测能力到适当的环境中。内容包对于托管安全服务提供商(MSSPs)特别有用,因为根据每个环境中可用的技术或提供商与客户之间的服务级别协议(SLA),需要不同的检测能力。当需要对新检测规则或现有检测规则的更新部署进行更精细控制时,内部 SOC 也可以从使用内容包中受益。
一个内容包可能包括标题、内容包重点的描述、版本号以及检测库中检测规则的相对路径(我们将在下一节中描述)。
{
"name": "Detections for Azure",
"description": "A collection of detections for Azure",
"version": "1.0.0",
"detections": [
"cloud/azure/azure_ad_azure_discovery_using_offensive_tools",
"cloud/azure/azure_ad_mfa_denied_phone_app_reported_fraud",
...
]
}
构建仓库结构
仓库的结构至关重要,因为它提供了一致性并简化了在检测库中的导航。Sigma 仓库 [3] 是结构化组织的优秀示例,你可以直接采用它或对其进行调整和扩展以更好地满足需求。无论如何,我们将描述在我们的案例中该结构可能是什么样子。
仓库中的项目应组织到逻辑文件夹中,例如用于规则的 detections/,用于检测测试的 tests/,以及用于部署和验证脚本或工作流的 pipelines/。
根据库的规模和覆盖范围,你可以考虑将它们进一步组织到子目录中——例如 os/windows、os/linux、network/palo_alto、network/vendor_agnostic。
detections/
│ ├── cloud/
│ ├── dns/
│ ├── endpoint/
│ ├── ids/
│ ├── os/
│ ├── network/
│ ├── proxy/
│ └── vpn/
已退役的检测规则,即那些已停止使用且不应部署在监控环境中的检测规则,也应该存储在自己的目录中(例如 _retired)。建议将已退役的检测规则保存在单独的目录中,而不是删除它们,尽管这可能与 Git 的预期用途和最佳实践相悖,因为了解哪些方法无效与了解哪些方法有效同样有价值,无论是对当前团队成员还是未来加入的成员都是如此。
detections/
│ ├── _retired/
│ │ └── ... (停用的检测规则)
每个检测规则应该被存储为一个单独的文件,使用一致的命名约定以便于跟踪和版本控制。如果你正在跨多个平台维护检测逻辑,将它们分组在 detections/下的父目录中是有帮助的,如下所示:
detections/
│ ├── network/
│ │ └── vendor_agnostic/
│ │ └── detection_1/
│ │ ├── detection_1_meta.yml
│ │ ├── detection_1_sentinel.json
│ │ ├── detection_1_elastic.json
一些 SIEM 使用过滤器的概念来描述一组可以在多个规则中重复使用的条件(例如 QRadar 中的 Building Blocks)。此外,规则可能要求以特定方式解析日志,以便能够利用特定字段进行检测。如果你的环境中存在这两种情况中的任何一种,这些可重用的组件应该存储在自己的单独文件夹中,例如 parsers/或 filters/。
最后,如果你计划以类似于许多 SIEM 供应商所做的方式将检测规则打包交付,你应该创建一个相应的 content_packs/目录。
上述结构的整体可视化表示如下:
content_packs/
│ ├── content_pack_1.json
│ ├── content_pack_2.json
│ └── ... (分组的检测包以供交付)
detections/
│ ├── _retired/
│ │ └── ... (停用的检测规则)
│ ├── application/
│ ├── cloud/
│ ├── dns/
│ ├── endpoint/
│ ├── ids/
│ ├── os/
│ │ ├── windows/
│ │ │ └── ... (Windows 检测规则)
│ │ └── linux/
| | | └── ... (Linux 检测规则)
│ ├── network/
│ │ ├── palo_alto/
│ │ └── vendor_agnostic/
│ │ └── detection_1/
│ │ ├── detection_1_meta.yml
│ │ ├── detection_1_sentinel.json
│ │ ├── detection_1_elastic.json
│ ├── proxy/
│ └── vpn/
parsers/
│ └── ... (解析器组件)
filters/
│ └── ... (过滤器组件)
pipelines/
│ ├── scripts/
│ │ └── ... (管道脚本)
| ├── schemas/
| | └── ... (检测规则模式)
│ ├── pipeline1.yaml
| └── pipeline2.yaml
tests/
│ └── ... (检测规则验证测试)
README.md
选择分支策略
一旦我们选择了仓库平台并设计了检测的结构和格式,最后一步就是决定分支策略。在软件工程中,分支策略对于有效的协作和版本控制至关重要,它允许团队成员同时处理不同的任务而不会产生冲突。它将开发中的代码与稳定的代码分开,并确保只有经过测试和审查的代码才能进入生产环境。当我们实践检测即代码时,这些相同的原则是有益的并且可以应用。
在这种情况下,分支策略涉及:
-
何时以及为何创建分支- 你会为每个开发的检测创建一个新分支,还是为每个需要修复的 bug 创建一个新分支? -
分支命名约定- 你在创建分支时会使用什么模式或前缀,例如 'dev-'、'detection-'、'bugfix-' 或工单号? -
如何以及何时合并分支- 你何时将检测合并回主分支?在每个检测开发之后?在通过 QA 之后? -
分支与环境的映射- 不同的分支将如何对应你组织中的不同部署环境?你会有专门的测试或开发环境吗?
有几种模型可供选择,你可以根据团队规模、团队成员的经验水平、对角色的投入程度、可用资源、部署需求、开发节奏和组织类型等因素进行选择。没有绝对的正确和错误的选择——你应该选择最适合你需求的策略。然而,每种策略都有其优缺点,可能更适合某些团队。
在 NVISO,我们一直成功地使用 GitHub Flow,但我们会讨论一些其他可用的选项,以便你做出最适合团队开发风格和需求的选择。
Trunk-Based 开发
Trunk-based [4][5] 开发是一种策略,工程师直接提交到主分支(通常称为 'trunk'),或者更频繁地合并较小的、短生命周期的分支(例如每天多次)。这些分支几乎总是一个人的产物。发布可以从主分支进行,也可以从不会合并回主分支的短期发布分支进行。应该使用分支命名约定,通常包括 'detection-' 或 'bug-' 等前缀。
Trunk-based 开发简单且复杂度低,使团队易于采用。它能够快速交付检测,并通过频繁提交到主分支来最小化合并冲突。然而,它需要强大的验证和测试管道来确保质量,因为直接提交的方法可能会增加生产错误的风险。该模型最适合小型或有经验的团队,尤其是当有强大的自动化测试和 CI/CD 管道时。
GitHub Flow
GitHub Flow [6][7] 是一种专注于持续交付的策略。主分支作为最新、稳定的检测代码的中心点,它应该始终是可部署的。分支可以具有较长的生命周期(存活数周),并且应该为每个更改创建一个分支。分支应该根据正在处理的任务命名,例如 "detection/brute-force-rules" 或 "bug-fix/threshold-tuning"。Pull requests 由同行审查,然后合并到主分支,同时应该使用自动化验证管道。部署可以在将更改合并到主分支后自动进行。
这种方法提供了简单性和低复杂度,使其易于采用,并且非常适合在 CI/CD 环境中快速交付检测。然而,它需要努力设置验证管道,并且缺乏专门的暂存或测试环境,增加了彻底审查的需求。它最适合具有强大自动化测试和 CI/CD 实践的小型、有经验的团队,在快节奏的开发周期中运作。
尽管 Trunk-Based和 GitHub Flow乍一看可能有点相似,但它们有一些区别 [8]。分支(短生命周期 vs 长生命周期)和合并频率(频繁 vs 较长)是核心区别,这也使它们适合不同的开发风格。
Gitflow
Gitflow [9] 是最结构化的分支策略之一,它利用多个分支,如 main、hotfix、release、dev 和 feature。必须为此使用分支命名约定以保持一致性,否则很容易失去对所有更改的跟踪。关于检测工程,这是你如何适应它的方式:
该策略为开发、测试和发布提供了清晰且结构化的流程,通过分离生产和开发代码来确保稳定性,并允许将更改分组到计划发布中。它最适合由供应商交付的内容,其中可靠性是关键。其复杂性对于经验不足的用户来说可能具有挑战性,管理多个分支可能会减慢检测交付速度,使其不太适合快节奏的 CI/CD 环境。
环境分支
环境分支 [10] 是对于拥有专用暂存环境的团队的一种选择,其中镜像了生产或测试数据。这种方法通常被选择是因为在这种情况下感觉更自然,并提供了一种使用真实生产数据安全测试检测的方法。虽然有各种适应方式,但它通常包括 dev、staging 和 main 分支。新功能,或者在我们的案例中是检测,是在从 dev 派生的分支中开发的。
这种方法易于采用,并提供了开发、暂存和生产环境之间的清晰分离,确保在部署前进行彻底测试。它非常适合对警报处理有严格程序的组织和拥有专用暂存环境的团队。然而,它也容易出现分支漂移和随着时间的推移复杂的合并,这会增加维护工作并减慢发布周期。
自定义策略
如前所述,没有正确和错误的选择。选择适合团队需求的分支策略。你可以根据流程、工作方式、团队的经验以及协作和隔离任务的能力,定义自己的分支策略。
总结
在实践检测即代码系列的第二部分中,我们讨论了设计检测仓库,并探讨了不同方面,如选择 Git 平台、建议仓库结构、标准化检测格式、引入内容包的概念以及决定分支策略。
本系列的下一篇博客将介绍使用 CI 工作流来验证检测和仓库结构。
参考文献
[1] https://github.com/SigmaHQ/sigma-specification/blob/main/specification/sigma-rules-specification.md#title
[2]https://blog.palantir.com/alerting-and-detection-strategy-framework-52dc33722df2
[3]https://github.com/SigmaHQ/sigma-specification/blob/main/appendix/sigma-taxonomy-appendix.md#application-folder
[4]https://trunkbaseddevelopment.com/#trunk-based-development-for-smaller-teams
[5]https://martinfowler.com/articles/branching-patterns.html#Trunk-basedDevelopment
[6]https://docs.github.com/en/get-started/using-github/github-flow
[7]https://martinfowler.com/articles/branching-patterns.html#GithubFlow
[8]https://www.opsatscale.com/articles/Git-branching-strategies-comparison/
[9]https://medium.com/novai-devops-101/understanding-gitflow-a-simple-guide-to-git-branching-strategy-4f079c12edb9
[10] https://dev.to/karmpatel/git-branching-strategies-a-comprehensive-guide-24kh#github-flow
翻译自: Detection Engineering Practicing Detection-as-Code – Repository – Part 2
免责声明:本博客文章仅用于教育和研究目的。提供的所有技术和代码示例旨在帮助防御者理解攻击手法并提高安全态势。请勿使用此信息访问或干扰您不拥有或没有明确测试权限的系统。未经授权的使用可能违反法律和道德准则。作者对因应用所讨论概念而导致的任何误用或损害不承担任何责任。

