Samir Bousseaden

利用高阶检测规则对警报进行优先分流

通过多信号相关性和高阶检测模式提高 SOC 效率。

阅读时间:9 分钟Enablement, Detection Engineering
利用高阶检测规则对警报进行优先分流

在 Elastic,我们在多个数据集、环境和严重程度级别上运行着大量不同的行为检测规则。这些规则大多是原子规则,每条规则都旨在检测特定行为、信号或攻击模式。此外,我们还能从防火墙、EDR、WAF 和其他安全控件等安全集成中摄取和推广外部警报

其结果是,不仅具有强大的可视性,还能发出大量警报。从我们的遥测数据来看,即使只考虑非构件规则每个生产集群每天也会有65 个独特的检测规则产生近8000 个警报。单独分析每个警报既无法扩展,也不符合成本效益。

这就是高级规则发挥作用的地方。

高阶规则不检测单一行为。相反,它们会将一段时间内、跨数据源或共享上下文(如主机、用户、IP 或进程)中的相关警报联系起来。通过将信号归类为有意义的模式,我们可以优先处理真正重要的问题,减少对每个警报进行深入、昂贵分析的需要,无论是手动、自动还是人工智能增强型分析。

在本博客中,我们将介绍在 Elastic 中构建高阶规则的方法,分享实际示例,并重点介绍在此过程中学到的关键经验。

什么是高阶规则?

高级规则 (HOR) 是使用警报作为输入的检测,它可以将警报与其他警报相关联(警报对警报),或将警报与原始事件、指标或上下文遥测等附加数据相结合。

与检测单一行为的原子规则不同,高阶规则可识别信号之间的模式。其目的不是取代基础检测,而是提升更有可能代表真实攻击活动的检测结果组合。在实践中,它们会浮现出可信度更高的发现,并改进分流优先级的确定。高级规则旨在与积木规则一起使用。构件模块规则生成的警报不会出现在默认警报视图中,从而减少了噪音,同时还能提供相关的检测结果。本文中提到的许多基本规则也可以配置为构件规则,这样只有高阶相关性才会浮现出来供分析师审查。

我们的核心观点是,独立的检测结果汇聚在同一个实体上,会增加可信度,而每一个额外的信号都会使活动是真实的而非良性的可能性成倍增加:

1.基于实体的相关性

规则通过共享实体(如主机、用户、源 IP、目标 IP 或流程)将活动关联起来,使分析人员能够快速查看多个发现是否汇聚到同一资产或身份上。

2.跨数据源可见性

某些规则在单一集成内运行(例如,来自 Elastic Defend 或第三方 EDR 的仅端点检测)。还有人有意将端点与网络(PANW、FortiGate、Suricata)、端点与电子邮件或端点与系统指标等跨域信号结合起来,以捕捉多阶段或跨表面的活动。

3.时间和流行意识

时间逻辑起着关键作用。

新观察到的规则会突出显示在定义的回溯窗口(例如五天)内首次出现的特定警报,确保即使是单一的罕见警报也能浮出水面接受审查。

基于普遍性的逻辑(如使用 INLINE STATS)可过滤全球范围内仅在少数主机上出现的警报,有助于减少噪音并强调异常行为。

整套高级规则涵盖仅端点相关性、跨域检测(端点 + 网络、端点 + 电子邮件)、横向移动模式(例如alert_1 host.ip = alert_2 source.ip )、ATT&CK 对齐分组(单一或多战术活动)、新观察到的警报以及警报到事件的相关性(例如与异常 CPU 指标相结合的警报)。下文将介绍这些类别中具有代表性的例子。

相关性和新观察到的高阶规则

在实践中,高风险活动并不总是一成不变的。

有时,妥协会通过多种交汇信号显现出来。有时,它会以从未见过的单一警报形式出现。

为了处理这两种现实情况,我们将高级规则分为三种互补模式:

  • 与共享实体(主机、用户、IP 或进程)相关联的多个警报或事件的关联规则。
  • 新观察到的规则在规定的时间窗口内罕见或首次出现的单一警报。
  • 混合模式将相关性与第一印象逻辑相结合,可进一步提高怀疑度,使特别有趣的活动浮出水面。

相关性规则通过信号密度和多样性提高可信度:当多个独立检测指向同一实体时,真正恶意活动的可能性就会增加。

新观察到的规则处理的是相反的情况,即数量少但新颖性高。它们会根据一段时间内的罕见程度确定警报的优先级,确保首次或非常不寻常的检测不会因为只发生一次而被忽视。

这些方法共同构成了高效、可扩展的分流策略的基础。

让我们深入实例,探索每种模式的差异、优势和权衡。

端点警报关联

实际攻击发现的很大一部分来自端点遥测。它提供了丰富的上下文进程活动、命令行、文件行为和用户操作,使其成为最强大的检测源之一。

同时,终端环境也是动态的。合法软件、管理工具和第三方应用程序(以及最近的 GenAI 端点实用程序🥲)会产生大量警报和误报,需要持续调整。

通过将重点从单个警报转移到同一主机或流程上的多个不同信号,增强了可信度,同时减少了不必要的调查工作,从而有助于解决这一问题。

当出现 3 唯一的 Elastic Defend 行为规则或来自不同功能的警报(例如,一个 shellcode_thread 行为,一个 malicious_file 行为)或来自同一主机的恶意软件警报在 24 小时内超过 2 时,会触发以下 ES|QL 查询:

from logs-endpoint.alerts-* metadata _id
| eval day = DATE_TRUNC(24 hours, @timestamp)
| where event.code in ("malicious_file", "memory_signature",  "shellcode_thread", "behavior") and 
 agent.id is not null and not rule.name in ("Multi.EICAR.Not-a-virus")
| stats Esql.alerts_count = COUNT(*),
        Esql.event_code_distinct_count = count_distinct(event.code),
        Esql.rule_name_distinct_count = COUNT_DISTINCT(rule.name),
        Esql.file_hash_distinct_count = COUNT_DISTINCT(file.hash.sha256),
        Esql.process_entity_id_distinct_count = COUNT_DISTINCT(process.entity_id) by host.id, day
| where (Esql.event_code_distinct_count >= 2 or Esql.rule_name_distinct_count >= 3 or Esql.file_hash_distinct_count >= 2)

为了进一步引起怀疑,我们还可以将属于同一进程树的 Elastic Defend 警报关联起来:

from logs-endpoint.alerts-*
| where event.code in ("malicious_file", "memory_signature", "shellcode_thread", "behavior") and
        agent.id is not null and not rule.name in ("Multi.EICAR.Not-a-virus") and process.Ext.ancestry is not null

// aggregate alerts by process.Ext.ancestry and agent.id
| stats Esql.alerts_count = COUNT(*),
        Esql.rule_name_distinct_count = COUNT_DISTINCT(rule.name),
        Esql.event_code_distinct_count = COUNT_DISTINCT(event.code),
        Esql.process_id_distinct_count = COUNT_DISTINCT(process.entity_id),
        Esql.message_values = VALUES(message),
   ... by process.Ext.ancestry, agent.id

// filter for at least 3 unique process IDs and 2 or more alert types or rule names.
| where Esql.process_id_distinct_count >= 3 and (Esql.rule_name_distinct_count >= 2 or Esql.event_code_distinct_count >= 2)

// keep unique values
| stats Esql.alert_names = values(Esql.message_values),
        Esql.alerts_process_cmdline_values = VALUES(Esql.process_command_line_values),
... by agent.id
| keep Esql.*, agent.id

匹配示例

为了补充我们的覆盖范围,我们还需要寻找稀有原子。下面的 ES|QL 设计为按 10 分钟计划运行,回溯窗口为 5 或 7 天。回溯功能按规则名称汇总整个窗口内的所有警报,计算首次出现时间。最后一个过滤器 (Esql.recent <= 10) 确保只有首次出现时间在当前 10 分钟执行窗口内的规则才会浮出水面,从而有效地检测到规则在回溯期内首次触发的时刻。这样就能发现罕见的误报和隐蔽行为,否则这些行为可能会在大量数据中消失:

from logs-endpoint.alerts-*
| WHERE event.code == "behavior" and rule.name is not null
| STATS Esql.alerts_count = count(*),
        Esql.first_time_seen = MIN(@timestamp),
        Esql.last_time_seen = MAX(@timestamp),
        Esql.agents_distinct_count = COUNT_DISTINCT(agent.id),
        Esql.process_executable = VALUES(process.executable),
        Esql.process_parent_executable = VALUES(process.parent.executable),
        Esql.process_command_line = VALUES(process.command_line),
        Esql.process_hash_sha256 = VALUES(process.hash.sha256),
        Esql.host_id_values = VALUES(host.id),
        Esql.user_name = VALUES(user.name) by rule.name
// first time seen in the last 5 days - defined in the rule schedule Additional look-back time
| eval Esql.recent = DATE_DIFF("minute", Esql.first_time_seen, now())
// first time seen is within 10m of the rule execution time
| where Esql.recent <= 10 and Esql.agents_distinct_count == 1 and Esql.alerts_count <= 10 and (Esql.last_time_seen == Esql.first_time_seen)
// Move single values to their corresponding ECS fields for alerts exclusion
| eval host.id = mv_min(Esql.host_id_values)
| keep host.id, rule.name, Esql.*

同样的逻辑也适用于来自其他第三方 EDR 的外部警报

终端与网络警报相关性

一种强大的检测方法是将端点警报与网络警报关联起来。这有助于回答关键问题:

哪个进程触发了这个网络警报?

仅靠网络警报往往缺乏进程上下文,如哪个用户或可执行文件启动了活动。通过将网络警报与端点遥测(EDR 数据)相结合,您可以通过以下方式丰富警报内容:

  • 进程名称和哈希值
  • 命令行和父进程
  • 用户和设备信息

以下查询将任何 Elastic Defend 警报与来自网络安全设备(如 Palo Alto Networks (PANW) 和 Fortinet FortiGate)的可疑事件关联起来。连接键是 IP 地址:对于网络警报,它是source.ip ;对于终端警报,它是host.ip 。查询使用COALESCE 将这些字段归一化为一个字段,这样就能在同一实体使用不同字段名称的数据源之间建立关联。这可能表明该主机已被入侵,并触发了多数据源警报。

FROM logs-* metadata _id
| WHERE 
 (event.module == "endpoint" and event.dataset == "endpoint.alerts") or
 (event.dataset == "panw.panos" and event.action in ("virus_detected", "wildfire_virus_detected", "c2_communication", ...)) or
 (event.dataset == "fortinet_fortigate.log" and (...)) or
 (event.dataset == "suricata.eve" and message in ("Command and Control Traffic", "Potentially Bad Traffic", ...))
| eval 
      fw_alert_source_ip = CASE(event.dataset in ("panw.panos", "fortinet_fortigate.log"), source.ip, null),
      elastic_defend_alert_host_ip = CASE(event.module == "endpoint" and event.dataset == "endpoint.alerts", host.ip, null)
| eval Esql.source_ip = COALESCE(fw_alert_source_ip, elastic_defend_alert_host_ip)
| where Esql.source_ip is not null
| stats Esql.alerts_count = COUNT(*),
        Esql.event_module_distinct_count = COUNT_DISTINCT(event.module),
        Esql.message_values_distinct_count = COUNT_DISTINCT(message),
        ... by Esql.source_ip
| where Esql.event_module_distinct_count >= 2 AND Esql.message_values_distinct_count >= 2
| eval concat_module_values = MV_CONCAT(Esql.event_module_values, ",")
| where concat_module_values like "*endpoint*"

将 Elastic Defend 和 Fortigate 警报相关联的匹配示例,其中 FortiGate 警报的 source.ip 等于 Elastic Defend 端点警报的 host.ip :

以下 EQL 查询将 Suricata 警报与 Elastic Defend 网络事件相关联,以提供源进程和主机的上下文:

sequence by source.port, source.ip, destination.ip with maxspan=5s
// Suricata severithy 3 corresponds to information alerts, which are excluded to reduce noise
[network where event.dataset == "suricata.eve" and event.kind == "alert" and  event.severity != 3 and source.ip != null and destination.ip != null]
[network where event.module == "endpoint" and event.action in  ("disconnect_received", "connection_attempted")]

从 Elastic Defend 事件中确认 Suricata 警报并将其链接到目标网络服务器进程 nginx 的匹配示例,确认网络入侵企图:

利用可观察性实现端点安全

将可观测性遥测数据与安全警报相关联是一种强大的检测策略。

XZUtils 后门事件表明,与安全相关的异常情况可能首先表现为性能下降,而不是传统的安全警报。在这种情况下,SSH 守护进程中的异常行为导致了更深入的调查,并最终发现了恶意代码。

这突出了一个重要原则:运行异常可能是入侵的早期迹象。

利用弹性代理,可以收集 CPU 和内存利用率等系统指标以及安全遥测数据。通过按进程或主机将异常资源峰值与 SIEM 警报相关联,我们可以提高检测的可信度,更早地发现高风险活动。

例如,ES|QL 关联规则可以识别出一个持续占用 70% CPU 的进程,该进程同时也是 Elastic Defend 的加密程序内存签名警报的来源。每个信号的严重程度可能是低度或中度。它们相互关联,代表着高可信度的恶意活动。

我们开发了超过 30 种高级检测,涵盖各种类型的关系。虽然我们无法在此涵盖所有规则,但下面的链接提供了足够的背景信息,使这些规则适合您的环境:

端点警报:
按代理发出多个弹性防御警报
来自单个进程树的多个弹性防御警报
按主机分列的多个罕见弹性防御行为规则
新观察到的弹性防御行为警报
按主机分列的多个外部 EDR 警报

端点和网络:
新发现的 Palo Alto 网络警报
新发现的高严重性 Suricata 警报
来自异常进程的 FortiGate SOCKS 流量
PANW 和 Elastic Defend - 命令和控制相关性
弹性防御和网络安全警报相关性
Suricata 和 Elastic Defend 网络相关性

由 MITRE ATT&CK 通用:
按主机分列的不同 ATT&CK 策略中的警报
同一 ATT 中的多个警报&按主机分列的 CK 策略

通用多集成相关性:
按源地址显示来自多个集成的警报
按目的地地址显示来自多个集成的警报
按用户名查看来自多个集成的警报
新观察到的高严重性检测警报

侧向移动相关性:
来自受损主机的可疑横向移动
来自新观察到的源地址的横向移动警报
来自新观察到的用户的横向移动警报

可观察性和安全相关性:
对 CPU 出现峰值的进程发出检测警报
一台主机出现多个 CPU 突增警报
新观察到的高 CPU 使用率进程

机器学习相关性:
按影响者领域分类的多个机器学习警报

其他相关想法:
通过 Wiz 按资产查找多个漏洞
弹性防御和电子邮件警报相关性
可疑的 Kerberos 验证票请求
通过源地址访问多个云机密

这些示例说明了端点、网络和可观测性之间的警报关联如何丰富上下文、加快调查速度并提高检测可信度。我们正在积极扩大这一领域的覆盖范围,以支持更多的相关情景。

您可以通过筛选标签值 "规则类型 "来启用它们:高级规则:

在 15 天的时间里,警报次数保持在可接受的范围内(每天约 30 次)。对最初的异常值进行有针对性的调整,预计可将其减少到每天约 20 个警报,并显著提高整体信号质量。

考虑和权衡

高阶规则会带来潜在的调度延迟。由于它们会查询警报索引,因此基本警报触发与相关性浮现之间存在固有的延迟。应调整规则调度间隔和环回窗口,以平衡及时性和性能成本。此外,HOR 的质量直接取决于基点检测的质量。有噪声的原子规则会将假阳性串联到引用它的每个相关性中。我们建议在启用从属高级规则之前,积极调整基础规则。最后,对广义索引模式(如logs-*) 的规模会很昂贵。在大容量环境中,将索引模式范围扩展到特定数据集或使用数据视图可以显著降低查询成本。

结论

高阶规则对于确定警报分流的优先次序以及管理警报量以实现自动化和人工智能驱动的分析***来说至关重要。当与实体风险评分相结合时,高阶规则可直接反馈到主机和用户风险档案中,从而创建一个量化优先级层,进一步减轻人工分流负担。在我们的生产测试中,大多数检测都能产生中低警报音量,因此在实际应用中非常实用。虽然最初可能会出现少量噪声规则或误报,但在原子规则层面上排除这些规则后,很快就能得到一组稳健的高价值相关性规则。

要最大限度地发挥它们的功效,两种操作方法至关重要。首先,确保输入警报使用能准确反映噪音和实际影响的严重程度,清理和规范严重程度是建立有意义的相关性的基础。第二,从小处入手,慎重扩展:避免试图关联所有可能的警报信号。排除固有的嘈杂策略(如发现),降低低严重性信号的优先级,摒弃对相关结果影响过大的规则。

如果应用得当,高阶规则可简化调查,提高检测准确性,并显著提高现代安全操作的效率和可信度。

分享这篇文章