本文目录导读:

编写SIEM(安全信息和事件管理)关联规则是安全运营的核心工作,就是将看似孤立的、低等级的告警或日志,通过特定的逻辑组合起来,发现真正的攻击行为。
下面从核心概念、编写步骤、常用模式和最佳实践四个部分来介绍。
核心概念
在深入编写之前,需要理解SIEM关联规则的基本构成,虽然不同厂商(如Splunk, QRadar, ArcSight, Azure Sentinel)语法不同,但逻辑组件相似:
- 数据源/日志流:规则分析的数据来源,Windows安全日志(Event ID 4625)、防火墙流量日志、DNS查询日志。
- 条件/过滤器:筛选出感兴趣的事件。
事件ID == 4625、目标端口 == 3389、源IP地址不属于内网段。 - 时间窗口:关联分析的核心,定义事件必须在多长时间内发生才被认为是相关的。
在5分钟内。 - 聚合与计数:对符合条件的事件进行统计。
同一个源IP在5分钟内登录失败超过10次。 - 关系/序列:定义事件发生的顺序或联系。
A事件发生 -> 紧接着B事件发生,或源IP相同、目标用户相同。 - 动作:规则匹配后执行的操作。生成告警(Critical, High)、执行脚本、更新威胁情报列表。
编写步骤(通用方法论)
一个好的规则不是一蹴而就的,建议遵循以下步骤:
- 确定检测目标:你想发现什么攻击?
- 例子:检测暴力破解RDP(远程桌面协议)攻击。
- 分析攻击行为链:攻击者在真实场景中会留下什么日志?
- 例子:短时间内大量的Windows安全日志 Event ID 4625(登录失败),并最终跟一个Event ID 4624(登录成功)。
- 抽象为逻辑模型:
- 数据源:Windows Security Log。
- 条件:
EventID == 4625LogonType == 10(远程交互登录)。 - 分组:按
Source_Network_Address(源IP) 和Target_User_Name(目标用户) 分组。 - 窗口:
5分钟。 - 阈值:
失败次数 > 10。 - 输出:告警等级高,描述为“从 [源IP] 对 [目标用户] 的可能RDP暴力破解”。
- 编写并测试:先在测试环境用历史日志验证,避免大量误报。
- 调优并上线:调整阈值和排除清单,减少噪声。
- 持续监控与优化:定期审查规则命中率,攻击者会变,规则也要迭代。
常见关联模式与示例(伪代码)
这里使用一种接近Splunk SPL/Cribl/通用逻辑的伪代码来演示,方便理解,你可以根据自己使用的SIEM产品(如Splunk, Azure Sentinel KQL, QRadar AQL)对应调整。
阈值检测(Throttling / Threshold)
最常用,用于检测扫描、爆破、DDoS。
- 逻辑:同一IP在X分钟内,触发了Y次特定事件。
- 示例(检测SSH暴力破解/Splunk SPL风格):
index=linux_secure sourcetype=secure "Failed password for" | stats count by src_ip, user, dest_ip | where count > 15 | eval severity="high", rule_name="SSH_Brute_Force"
缺失事件检测(Missing Event / Non-Event)
检测某个预期事件没有发生,用户登录成功了,却没有生成日志(日志被禁用/绕过)。
- 逻辑:事件A发生后,在窗口内必须出现事件B,未出现则告警。
- 示例(恶意软件下载后未扫描):
// 第一阶段:文件下载 (EventID 11: FileCreate) index=windows Sysmon EventID=11 // 第二阶段:等待5分钟,看是否有EventID=1(扫描进程启动) // 假设有一个lookup表记录可信的扫描器进程这个逻辑在SIEM里通常需要结合“事件管道”来实现,或者用反向逻辑:统计某高危文件下载后,关联文件扫描的行为,如果在时间窗口内没有产生关联,就告警。
时序检测(Temporal / Sequence)
检测事件发生的先后顺序,常用于攻击链。
- 逻辑:事件A -> 事件B -> 事件C,按顺序发生。
- 示例(基于Kerberoasting攻击):
// 步骤1: 查询服务主体名称 (EventID 4769, ServiceName: krbtgt) // 步骤2: 紧接着出现Kerberos TGS请求 (EventID 4769) // 步骤3: 接下来出现大量加密失败的RC4请求 | rename src_ip as attacker_ip | transaction attacker_ip, user maxspan=5m | where mvcount(EventID) >= 3 AND mvcount(mvfilter(match(ServiceName, ".*\\$"))) > 0 // 关键点
地理异常 / 不可能旅行(Geo Anomaly / Impossible Travel)
利用登录的物理位置速度判断账户被盗。
- 逻辑:同一个用户,在几分钟内,从两个地理距离很远的IP登录。
- 示例(Azure Sentinel KQL类型):
SigninLogs | where ResultType == 0 | project UserPrincipalName, IPAddress, Location, TimeGenerated | sort by UserPrincipalName asc, TimeGenerated asc | partition by UserPrincipalName ( // 定义前后两条记录的时间差和地理位置差 // 如果时间差 < 1小时 且 距离 > 1000公里,则告警 )
黑名单/威胁情报匹配(Threat Intelligence Lookup)
将内部日志与外部威胁情报源(如已知C2服务器IP、恶意域名)对比。
- 逻辑:日志中的
目标IP或域名出现在威胁情报列表里。 - 示例(检测与已知C2通信):
index=proxy sourcetype=web proxy dest_ip=* | lookup threat_intel_table ip as dest_ip OUTPUT threat_type, severity | where isnotnull(threat_type) | eval alert_severity="critical"
最佳实践与避坑指南
- 从简单开始:不要试图编写非常复杂的多层嵌套逻辑,先从“单条件阈值”开始,逐步增加维度。
- 关注“时间窗口”:
- 窗口太短:可能错过攻击(网络延迟、日志分批到达)。
- 窗口太长:大量内存消耗,且告警延迟。
- 建议:横向移动、爆破类用1-10分钟;数据渗出、持久化类用1小时到24小时。
- 避免“黄金规则”陷阱:不要写一个规则试图捕捉“所有攻击”,攻击多样性导致单一规则要么漏报要么误报爆炸。
- 必须做“排除清单”:在规则中加入排除条件,如:
source_ip NOT IN [vpn_gateway_list, patch_server_list]user NOT IN [service_account_list]
- 重视日志质量:如果日志字段不标准(如
src_ip和source_ip混用),关联规则会失效,一定要建立统一的日志标准化(Normalization)流程。 - 性能考虑:不要对全量日志做复杂关联,尽量在规则条件中优先过滤掉95%的无关数据(如只关注
EventID=4625,而不是所有日志)。 - 测试与验证:
- 真阳性测试:用红队工具(如Cobalt Strike, Metasploit)模拟攻击,看能否触发。
- 假阳性测试:在历史一个月的数据上运行,看误报率,如果一天误报1000条,没人愿意看。
- 文档化:每个规则必须写清楚:
- 检测目标(发现什么)
- 告警逻辑(图示或伪代码)
- 响应流程(触发后第一步做什么)
- 调优记录(修改了阈值、增加了排除项的原因)
举个例子:编写一个“横向移动(PsExec)”规则
-
攻击行为:攻击者用PsExec在内网其他机器上执行命令。
-
日志特征(Sysmon或Windows Event Log):
- 服务创建:Event ID 7045 (Service Creation) ->
ServiceName包含PSEXESVC。 - 网络连接:Event ID 3 (Network Connect) -> 从高危IP 出站到 445端口(但更推荐直接看服务日志)。
- 进程创建:Event ID 4688 ->
ParentImage包含PSEXESVC.exe。
- 服务创建:Event ID 7045 (Service Creation) ->
-
简化逻辑(伪代码):
index=windows_sysmon // 基础过滤:检测服务创建事件中服务名为PSEXESVC EventID=7045 AND Service_Name="PSEXESVC*" // 或者也可以检测 EventID=4688 且 ParentImage包含PSEXESVC EventID=4688 AND ParentImage="*PSEXESVC*" // 输出时带上源IP和目标计算机名 | eval rule_name="Lateral_Movement_PsExec"
编写SIEM关联规则的核心是将网络安全威胁模型翻译成日志查询语言,关键在于:
- 理解攻击链(这是安全分析能力)
- 熟悉日志字段(这是技术基础)
- 平衡误报与漏报(这是运维经验)
建议从你环境中真实发生过的小型安全事件入手,编写针对性规则,迭代几次后,就能快速上手。