匹配部分语法
在 YARA-L 2.0 中,match 部分提供了多事件相关性机制。它通过在特定时间边界内关联用户、IP 地址或文件哈希等常见属性,定义将事件分组为单个检测的逻辑。
您可以在以下使用场景中使用 match 部分:
- 在规则中关联两个或多个不同的事件。
- 搜索和信息中心内的汇总数据,例如在特定时间范围内统计登录失败的次数。
定义相关性条件
您可以使用它来定义此相关性的条件,方法是指定以下内容:
分组字段(键):变量(例如
$user或$ip),必须在事件(在events部分中定义)中具有相同的值才能触发匹配。时间限制:分组事件必须在某个时长时间段内发生,才能满足规则或聚合条件。在“规则”中,此参数用于定义检测窗口;在“搜索”和“信息中心”中,此参数用于定义聚合或关联窗口。
比较功能要求
下表详细比较了“规则到搜索”和“信息中心”。
| 功能 | 规则要求 | 搜索和信息中心支持 |
|---|---|---|
| 变量类型 | 必须使用在 events 部分中定义的占位符。 |
支持占位符和直接 UDM 字段。 |
| 时间窗口 | 定义检测边界。 | 定义聚合或相关性分桶。 |
| 语法 | over <number><m/h/d>(例如 10m、2h、1d) |
over <number><m/h/d> |
| 限制 | 最小值:1m / 最大值:48h |
最小值:1m / 最大值:48h |
支持的窗口类型
YARA-L 2.0 使用不同的窗口化行为来确定如何划分时间以及如何对事件进行分组。您可以使用以下支持的时间窗口,按指定的时间粒度对 match 部分中的事件字段和占位符进行分组。
| 支持的窗口类型 | 语法 | 说明 | 常见用例 |
|---|---|---|---|
| 跳 | $key over <duration> |
重叠的时间间隔(默认行为)。 | 多个事件的一般相关性。 |
| 翻滚 | $key by <duration> tumbling |
固定大小、不重叠且连续的时间间隔。 | 以最长 1 小时为单位(例如 $user by 30m)量化活动。 |
| 滑动 | $key over <duration> [before|after] $pivot |
以特定“透视”事件为锚点的时间间隔。 | 严格的依序展示(例如 File Download after Login)。 |
语法示例:
match:
$user, $source_ip over 5m // Groups events by user and IP within a 5-minute window
跳跃窗口
跳跃窗口是多事件规则的默认行为。它会创建重叠的时间间隔,以确保不会错过窗口边界附近发生的事件。
- 语法:
$key over <duration>(例如,$user over 30m) - 使用情形:最适合需要确保捕获特定场景的检测,无论窗口间隔何时开始或结束。
- 支持:支持在搜索和信息中心(例如
count)中进行汇总。
默认情况下,包含 match 部分的 YARA-L 查询使用跳跃窗口来关联一段时间内的多个事件。查询的执行时间范围分为一组固定的重叠跃点窗口。虽然这些窗口的持续时间在 match 部分中指定,但重叠间隔和窗口对齐方式由系统定义,用户无法配置。然后,在每个预定窗口内,事件是相关的。
示例:重叠的跳跃窗口,用于持续相关性分析
以下示例展示了一个在 [1:00, 2:00] 时间范围内运行的查询,其中包含 match 部分 $user over 30m,可能生成的一组重叠跳跃窗口为 [1:00, 1:30]、[1:03, 1:33] 和 [1:06, 1:36]。
rule hop_window_brute_force_example {
meta:
description = "Detects multiple failed logins within a shifting 30-minute window."
severity = "Medium"
events:
$login.metadata.event_type = "USER_LOGIN"
$login.extensions.auth.auth_status = "FAILURE"
$login.principal.user.userid = $user
match:
// This creates the overlapping windows (e.g., 1:00-1:30, 1:03-1:33)
$user over 30m
condition:
// This will trigger if 10 or more failures fall into any single 30m hop
#login >= 10
}
示例:使用跳跃窗口进行多事件关联
以下示例表示大多数多事件规则的默认值。它会捕获在同一大致时间范围内发生的事件。
rule hop_window_example {
meta:
description = "Detect a user with a failed login followed by a success within 30m"
events:
$e1.metadata.event_type = "USER_LOGIN"
$e1.extensions.auth.auth_status = "FAILURE"
$e1.principal.user.userid = $user
$e2.metadata.event_type = "USER_LOGIN"
$e2.extensions.auth.auth_status = "SUCCESS"
$e2.principal.user.userid = $user
match:
$user over 30m // This is a hop window
condition:
$e1 and $e2
}
示例:跳跃窗口比较
为了识别暴力破解尝试,10m 窗口会将所有 USER_LOGIN 失败尝试归为一组。然后,condition 会评估相应 10 分钟时间段内的计数 (#e) 是否超过您的阈值。
rule failed_logins
{
meta:
author = "Security Team"
description = "Detects multiple failed user logins within 10-minute windows."
severity = "HIGH"
events:
$e.metadata.event_type = "USER_LOGIN"
$e.security_result.action = "FAIL"
$user = $e.target.user.userid
match:
$user over 10m
condition:
#e >= 5
}
match 部分查找在 10 分钟 (10m) 时间间隔内在新位置登录失败的用户:
match:
$user over 10m
翻滚窗口
翻滚窗口将数据流划分为固定大小、不重叠且连续的时间间隔。每个数据事件仅分配给一个窗口。这与滑动窗口或跳跃窗口不同,后者可以具有重叠的时间间隔。
- 语法:使用
by运算符 ($key by <duration>),例如$user by 30m。 - 使用场景:最适合用于报告和构建信息中心,以便统计不同时间段内的事件数(例如
"How many alerts per hour?")。 - 搜索和信息中心:经常用于创建不重复计算事件的简洁条形图。
示例:使用滚动窗口进行固定间隔计数
以下示例展示了一个 30 分钟的滚动窗口,其中 1:00:00 到 1:29:59 之间发生的事件会一起处理。然后,系统会单独处理下一组事件(从 1:30:00 到 1:59:59)。
rule tumbling_window_threshold_example {
meta:
description = "Detect more than 50 failed logins from a single IP within a fixed 1-hour block."
severity = "Medium"
events:
$login.metadata.event_type = "USER_LOGIN"
$login.extensions.auth.auth_status = "FAILURE"
$login.principal.ip = $ip
match:
// This creates distinct, 1-hour blocks (e.g., 1:00-1:59, 2:00-2:59)
$ip by 1h
condition:
#login > 50
}
滑动窗口
如果您需要搜索按严格的相对顺序发生的事件(例如,e1发生在 e2 之后最多两分钟内),请使用滑动窗口。与固定窗口不同,滑动窗口由指定 $pivot_event 的每次出现触发,语法如下:
after:窗口从透视事件的时间戳开始,并向前延伸。before:窗口在透视事件的时间戳处结束,并向后延伸。
在查询的 match 部分中指定滑动窗口,如下所示:
<match-var-1>, <match-var-2>, ... over <duration> [before|after] <pivot-event-var>
- 语法:
$key over <duration> before|after $<pivot_event> - 分组键:用于将事件关联在一起的通用字段(例如
$user、$ip)。 - 时长:相对于透视事件的时间偏移量(例如
5m、1h)。 - 应用场景:
- 严格的序列:检测需要按顺序执行的攻击链(例如,先创建用户,然后进行权限升级)。
- 相对时间:查找在“触发”事件(例如,
Process Start事件后 30 秒内发生的Network Connection事件)的特定偏移量内发生的事件。 - 缺席检测:识别在开始事件发生后,必需的“清理”或“心跳”事件何时未能发生(例如,没有相应
End事件的Database Backup Start)。
有效的滑动窗口示例
以下示例展示了有效的滑动窗口:
$var1, $var2 over 5m after $e1
$user over 1h before $e2
$host, $ip over 1h before $e2
示例:使用滑动窗口进行前瞻性相关分析 (after)
以下示例演示了如何检测一系列事件,其中第二个事件必须在主要“触发”事件或透视事件发生后的特定时间范围内发生。这有助于检测快速横向移动或自动后续操作。
rule sliding_window_after_example {
meta:
description = "Detect a network connection occurring within 1 minute after a suspicious process launch."
severity = "High"
events:
$proc.metadata.event_type = "PROCESS_LAUNCH"
$proc.principal.hostname = $host
$net.metadata.event_type = "NETWORK_HTTP"
$net.principal.hostname = $host
match:
// $proc is the pivot; the 1-minute window starts at the $proc timestamp
$host over 1m after $proc
condition:
$proc and $net
}
示例:使用滑动窗口 (before) 的回溯相关性
使用 "before" 滑动窗口来调查导致特定提醒的活动。这通常用于根本原因分析,以确定在检测到严重问题之前立即发生了什么情况。
rule sliding_window_before_example {
meta:
description = "Identify file modifications occurring in the 5 minutes before a ransomware alert."
severity = "Critical"
events:
$file.metadata.event_type = "FILE_MODIFICATION"
$file.principal.hostname = $host
$alert.metadata.event_type = "ANTIVIRUS_DETECTION"
$alert.metadata.product_name = "Premium_AV"
$alert.principal.hostname = $host
match:
// $alert is the pivot; the 5-minute window ends at the $alert timestamp
$host over 5m before $alert
condition:
$file and $alert
}
性能和最佳实践
滑动窗口需要比标准(跳跃)窗口更多的处理能力,因为它们是针对每次出现透视事件进行计算的,可能会导致性能下降。
请遵循以下准则,以确保规则、搜索和信息中心发挥最佳性能:
优先考虑跃点窗口:除非检测逻辑需要特定的事件序列(先是订单 A,然后是订单 B),否则请使用默认跃点窗口。仅在事件序列至关重要或您要搜索缺失的事件时使用滑动窗口。
使用时间戳过滤条件来提升性能:如果您只需要确保一个事件发生在另一个事件之后,那么
events或condition部分中的时间戳比较通常比滑动窗口更高效,例如:
$e1.metadata.event_timestamp.seconds <
$e2.metadata.event_timestamp.seconds
多事件设计:避免为单事件查询使用滑动窗口。滑动窗口专为多事件关联而设计。对于单事件逻辑,请遵循以下准则:
- 使用多个事件变量并更新
condition部分。 - 如果不需要相关性,请完全移除
match部分。 - (可选)考虑添加时间戳过滤条件,而不是使用滑动窗口,例如:
$permission_change.metadata.event_timestamp.seconds < $file_creation.metadata.event_timestamp.seconds
- 使用多个事件变量并更新
了解时间边界
match 部分会根据您的分组键将事件划分为不同的组。指定的时长定义了每个组的时间边界:
- 纳入:只有在窗口内的事件才会传递到
condition评估中,以进行特定匹配。 - 排除:对于相应匹配组,系统会忽略窗口之外的事件,从而防止不相关的事件触发假正例。
match 部分中的零值
Google SecOps 会隐式过滤掉 match 部分中使用的所有占位符的零值("" 表示字符串,0 表示数字,false 表示布尔值,位置 0 中的值表示枚举类型)。
示例:过滤掉零值
以下示例展示了过滤掉零值的查询。
rule ZeroValuePlaceholderExample {
events:
// Because $host is used in the match section, the query behaves
// as if the following predicate was added to the events section:
// $host != ""
$host = $e.principal.hostname
// Because $otherPlaceholder was not used in the match,
// there is no implicit filtering of zero values for $otherPlaceholder.
$otherPlaceholder = $e.principal.ip
match:
$host over 5m
condition:
$e
}不过,如果为函数分配了占位变量,查询不会隐式过滤掉 match 部分中使用的占位变量的零值。
如需停用对零值的隐式过滤,您可以在“选项”部分中使用 allow_zero_values 选项。allow_zero_values 选项仅在“规则”中提供。
示例:允许零值
以下示例展示了不会隐式过滤掉 match 部分中所用占位符的零值的查询:
rule AllowZeroValuesExample {
events:
// Because allow_zero_values is set to true, there is no implicit filtering
// of zero values for $host.
$host = $e.principal.hostname
// Because $otherPlaceholder was not used in the match,
// there is no implicit filtering of zero values for $otherPlaceholder.
$otherPlaceholder = $e.principal.ip
match:
$host over 5m
condition:
$e
options:
allow_zero_values = true
}后续步骤
您可以探索以下资源,继续学习 YARA-L 逻辑,或深入了解高级查询函数:
语法和逻辑
参考和示例
需要更多帮助?获得社区成员和 Google SecOps 专业人士的解答。