SIEM关联规则引擎如何编写

wen 网络安全 3

本文目录导读:

SIEM关联规则引擎如何编写

  1. 核心概念
  2. 编写步骤(通用方法论)
  3. 常见关联模式与示例(伪代码)
  4. 最佳实践与避坑指南
  5. 举个例子:编写一个“横向移动(PsExec)”规则

编写SIEM(安全信息和事件管理)关联规则是安全运营的核心工作,就是将看似孤立的、低等级的告警或日志,通过特定的逻辑组合起来,发现真正的攻击行为。

下面从核心概念编写步骤常用模式最佳实践四个部分来介绍。

核心概念

在深入编写之前,需要理解SIEM关联规则的基本构成,虽然不同厂商(如Splunk, QRadar, ArcSight, Azure Sentinel)语法不同,但逻辑组件相似:

  1. 数据源/日志流:规则分析的数据来源,Windows安全日志(Event ID 4625)、防火墙流量日志、DNS查询日志。
  2. 条件/过滤器:筛选出感兴趣的事件。事件ID == 4625目标端口 == 3389源IP地址不属于内网段
  3. 时间窗口:关联分析的核心,定义事件必须在多长时间内发生才被认为是相关的。在5分钟内
  4. 聚合与计数:对符合条件的事件进行统计。同一个源IP在5分钟内登录失败超过10次
  5. 关系/序列:定义事件发生的顺序或联系。A事件发生 -> 紧接着B事件发生,或源IP相同目标用户相同
  6. 动作:规则匹配后执行的操作。生成告警(Critical, High)、执行脚本更新威胁情报列表

编写步骤(通用方法论)

一个好的规则不是一蹴而就的,建议遵循以下步骤:

  1. 确定检测目标:你想发现什么攻击?
    • 例子:检测暴力破解RDP(远程桌面协议)攻击。
  2. 分析攻击行为链:攻击者在真实场景中会留下什么日志?
    • 例子:短时间内大量的Windows安全日志 Event ID 4625(登录失败),并最终跟一个Event ID 4624(登录成功)。
  3. 抽象为逻辑模型
    • 数据源:Windows Security Log。
    • 条件EventID == 4625 LogonType == 10(远程交互登录)。
    • 分组:按 Source_Network_Address(源IP) 和 Target_User_Name(目标用户) 分组。
    • 窗口5分钟
    • 阈值失败次数 > 10
    • 输出:告警等级高,描述为“从 [源IP] 对 [目标用户] 的可能RDP暴力破解”。
  4. 编写并测试:先在测试环境用历史日志验证,避免大量误报。
  5. 调优并上线:调整阈值和排除清单,减少噪声。
  6. 持续监控与优化:定期审查规则命中率,攻击者会变,规则也要迭代。

常见关联模式与示例(伪代码)

这里使用一种接近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. 从简单开始:不要试图编写非常复杂的多层嵌套逻辑,先从“单条件阈值”开始,逐步增加维度。
  2. 关注“时间窗口”
    • 窗口太短:可能错过攻击(网络延迟、日志分批到达)。
    • 窗口太长:大量内存消耗,且告警延迟。
    • 建议:横向移动、爆破类用1-10分钟;数据渗出、持久化类用1小时到24小时。
  3. 避免“黄金规则”陷阱:不要写一个规则试图捕捉“所有攻击”,攻击多样性导致单一规则要么漏报要么误报爆炸。
  4. 必须做“排除清单”:在规则中加入排除条件,如:
    • source_ip NOT IN [vpn_gateway_list, patch_server_list]
    • user NOT IN [service_account_list]
  5. 重视日志质量:如果日志字段不标准(如src_ipsource_ip混用),关联规则会失效,一定要建立统一的日志标准化(Normalization)流程。
  6. 性能考虑:不要对全量日志做复杂关联,尽量在规则条件中优先过滤掉95%的无关数据(如只关注EventID=4625,而不是所有日志)。
  7. 测试与验证
    • 真阳性测试:用红队工具(如Cobalt Strike, Metasploit)模拟攻击,看能否触发。
    • 假阳性测试:在历史一个月的数据上运行,看误报率,如果一天误报1000条,没人愿意看。
  8. 文档化:每个规则必须写清楚:
    • 检测目标(发现什么)
    • 告警逻辑(图示或伪代码)
    • 响应流程(触发后第一步做什么)
    • 调优记录(修改了阈值、增加了排除项的原因)

举个例子:编写一个“横向移动(PsExec)”规则

  • 攻击行为:攻击者用PsExec在内网其他机器上执行命令。

  • 日志特征(Sysmon或Windows Event Log):

    1. 服务创建:Event ID 7045 (Service Creation) -> ServiceName 包含 PSEXESVC
    2. 网络连接:Event ID 3 (Network Connect) -> 从高危IP 出站到 445端口(但更推荐直接看服务日志)。
    3. 进程创建:Event ID 4688 -> ParentImage 包含 PSEXESVC.exe
  • 简化逻辑(伪代码)

    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关联规则的核心是将网络安全威胁模型翻译成日志查询语言,关键在于:

  • 理解攻击链(这是安全分析能力)
  • 熟悉日志字段(这是技术基础)
  • 平衡误报与漏报(这是运维经验)

建议从你环境中真实发生过的小型安全事件入手,编写针对性规则,迭代几次后,就能快速上手。

抱歉,评论功能暂时关闭!