应用 YARA-L 2.0 开窗逻辑
本指南可帮助安全工程师为查询选择正确的窗口类型,以避免出现“变量未绑定”编译器错误。从滑动窗口过渡到滚动窗口后,您可以构建依赖于事件缺失的逻辑,例如缺少心跳或日志源失败。
准备工作
确认您的账号具有以下某个角色,以便创建和修改 YARA-L 查询:
- Detection Engine Admin (
roles/chronicle.detectionEngineAdmin) - SecOps Editor (
roles/chronicle.editor)
支持的窗口类型
YARA-L 2.0 使用不同的窗口化行为来确定如何对时间进行切分以及如何将事件分组在一起。您可以使用以下支持的时间窗口,按指定的时间粒度将 match 部分中的事件字段和占位符分组:
| 支持的窗口类型 | 语法 | 说明 | 常见用例 |
|---|---|---|---|
| 跳 | $key over <duration> |
创建固定的重叠时间间隔。系统会定义重叠和对齐,以捕获边界附近的事件。 | 多个事件的一般相关性,无论确切的开始时间如何。 |
| 翻滚 | $key by <duration> |
将数据分段为固定大小的连续非重叠块。独立于事件到达时间进行评估。 | 量化固定时间段内的活动(例如 $user by 30m)或检测事件是否缺失。 |
| 滑动 | $key over <duration> [before|after] $pivot |
将窗口锚定到特定的 "pivot" 事件。需要存在透视点才能触发回溯或前瞻。 |
严格的序列,其中事件顺序至关重要(例如 File Download after Login)。 |
了解 window_start 和 window_end 逻辑
Google Security Operations 提供两个通用预留关键字,可直接解析为 GoogleSQL 时间戳,以便在查询中使用。您可以使用以下关键字来访问时间段的边界:
window_start:时间段的开始边界。window_end:时间段的结束边界。
使用限制
- 匹配要求:您必须在
match部分中定义窗口(by或over),才能使用这些关键字。 - 部分限制:在
condition、order或outcome中使用这些关键字。在events部分中,这些网址无效。 - 命名空间:请勿将这些用作自定义变量名称(例如
$window_start)。
确定窗口类型和语法
在确定检测规则要使用的窗口类型和语法时,可将此表作为快速参考。
| 场景 | 建议的窗口 | 推荐的关键字 | 主要优势 |
|---|---|---|---|
| 高频检测(例如暴力破解攻击) | 滑动窗口 (over) |
window_start,window_end |
在滚动周期内达到阈值时立即触发。 |
| 缺失/不存在(例如,缺少心跳) | 翻滚窗口 (by) |
window_start,window_end |
即使没有发生任何事件,也会评估固定时间块,从而避免出现“变量不受限”错误。 |
| 按时间顺序报告 | 滑动或翻滚 | order: window_start asc |
标准化了提醒输出,以便在 Chronicle 界面中更轻松地进行时间轴分析。 |
| 有时限性的过滤 | 滑动或翻滚 | condition: window_start > "2026-01-01 00:00:00Z" |
使用 GoogleSQL 时间戳强制转换将规则评估限制为特定日期。 |
比较时间戳类型和时区
YARA-L 支持直接将 window_start 和 window_end 与 GoogleSQL 时间戳格式的字符串进行比较。这样一来,您无需手动进行类型转换即可执行精确过滤。
注意:请始终使用 Z 后缀(例如 "2026-03-17T17:35:00Z")指定世界协调时间 (UTC),以便与 UDM 事件时间戳保持一致。
使用时间戳过滤条件可提高性能。如果您只需要确认一个事件发生在另一个事件之后,通常情况下,condition 部分中的时间戳比较会更高效:$e1.metadata.event_timestamp.seconds < $e2.metadata.event_timestamp.seconds。
详细了解 match 部分语法和 condition 部分语法。
示例:window_end 和 window_start
window_end < "2026-01-01T12:30:00Z"(日期、时间和 UTC 后缀)window_start != "2026-01-01 15:00:00+00"(含世界协调时间 [UTC] 偏移量)
如果比较失败,请验证您的字符串是否符合 GoogleSQL 标准时间戳格式。
跳跃窗口
跃点窗口会创建重叠的时间间隔,这样就不会错过窗口边界附近发生的事件。
- 应用场景:最适合需要捕获特定场景的检测,无论窗口间隔的确切开始时间或结束时间如何。
- 支持:支持在搜索和信息中心内进行汇总。
包含 match 部分的 YARA-L 查询使用跳跃窗口来关联一段时间内的多个事件。系统会将查询执行的时间范围划分为一组固定的重叠跃点窗口。虽然您可以在 match 部分中指定这些窗口的时长,但系统会定义重叠间隔和窗口对齐方式。然后,在每个预定窗口内,事件是相关的。
详细了解 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
}
搜索
metadata.event_type = "USER_LOGIN"
security_result.action = "FAIL"
principal.user.userid = $user
match:
// This creates the overlapping windows (e.g., 1:00-1:30, 1:03-1:33)
$user over 30m
```
信息中心
metadata.event_type = "USER_LOGIN"
security_result.action = "FAIL"
principal.user.userid = $user
match:
// This creates the overlapping windows (e.g., 1:00-1:30, 1:03-1:33)
$user over 30m
示例:使用跳跃窗口进行多事件关联
以下示例会捕获在同一大致时间范围内发生的事件:
规则
rule hop_window_example {
meta:
description = "Detect a user with a failed login followed by a success within 30m"
events:
// Event 1: Capture failed login attempts
$fail.metadata.event_type = "USER_LOGIN"
$fail.security_result.action = "FAIL"
$fail.principal.user.userid = $user
// Event 2: Capture successful login attempts
$success.metadata.event_type = "USER_LOGIN"
$success.security_result.action = "ALLOW"
$success.principal.user.userid = $user
match:
// Correlate events for the SAME $user within a rolling 30-minute window.
$user over 30m
condition:
// Ensure both a failed ($fail) and a successful ($success) login event occurred for the same user within the 30m window.
$fail and $success
}
搜索
// Event 1: Capture failed login attempts
metadata.event_type = "USER_LOGIN"
security_result.action = "FAIL"
principal.user.userid = $user // Assign user ID to a placeholder
// Event 2: Capture successful login attempts
metadata.event_type = "USER_LOGIN"
security_result.action = "ALLOW"
principal.user.userid = $user // Link to the same user placeholder
match:
// Correlate events for the SAME $user within a rolling 30-minute window.
$user over 30m
信息中心
// Event 1: Capture failed login attempts
metadata.event_type = "USER_LOGIN"
security_result.action = "FAIL"
principal.user.userid = $user // Assign user ID to a placeholder
// Event 2: Capture successful login attempts
metadata.event_type = "USER_LOGIN"
security_result.action = "ALLOW"
principal.user.userid = $user // Link to the same user placeholder
match:
// Correlate events for the SAME $user within a rolling 30-minute window.
$user over 30m
示例:跳跃窗口比较
为了识别暴力破解尝试,10m 窗口会将所有 USER_LOGIN 失败分组。然后,该条件会评估相应 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
}
搜索
metadata.event_type = "USER_LOGIN"
security_result.action = "FAIL"
$user = target.user.userid
match:
$user over 10m
信息中心
metadata.event_type = "USER_LOGIN"
security_result.action = "FAIL"
$user = target.user.userid
match:
$user over 10m
翻滚窗口
注意:此功能仅适用于部分区域的部分客户。
翻滚窗口将数据分段为固定大小、不重叠且连续的时间间隔。每个事件的时间戳都只属于一个窗口。翻滚窗口之间没有重叠。这与可以具有重叠时间间隔的跳跃窗口或滑动窗口形成对比。
如需实现翻滚窗口,请在 match 部分中使用 by 运算符。翻滚窗口将时间划分为连续的背靠背时间块,例如:
by 1h:为每个小时创建窗口(例如[00:00:00-00:59:59]、[01:00:00-01:59:59])。by 10m:为每个 10 分钟的时间间隔创建窗口(例如[00:00:00-00:09:59]、[00:10:00-00:19:59])。
常见使用场景
在以下情况下,您需要使用滚动窗口:
- 分析不同且不重叠的时间段内的事件。
- 在每个固定时间间隔内,无论事件发生多少次,都只针对给定的实体(由匹配变量定义)生成一次检测结果。
- 统计固定时间段内的唯一实体数量。
去重行为
滚动窗口的一个关键特征是,对于同一组匹配变量,引擎如何处理每个窗口内的检测结果:
- 每个窗口一次检测:对于匹配变量的给定值集(例如,特定的
$userid),引擎最多会为任何单个翻滚窗口生成一次检测。 - 先到先得:在特定时间范围内,最先纳入的满足相应匹配变量集规则条件的事件会触发检测。
- 去重:在同一窗口实例中,任何后续事件如果符合相应条件,都不会生成额外的检测结果。
语法
match 部分的语法为:match: $variable by <duration>
$variable是您要匹配的占位符变量。duration是一个数字,后跟一个时间单位:m(分钟)、h(小时)、d(天)。- 指定最短 1 分钟,最长 72 小时或 3 天。
示例:固定间隔分组
以下规则按 1 小时内不重叠的时间段对登录进行分组。$userid
规则
rule TumblingWindowExample {
meta:
description = "Example using a 1-hour tumbling window"
events:
$e.metadata.event_type = "USER_LOGIN"
$e.principal.user.userid = $userid
match:
$userid by 1h
condition:
$e
}
搜索
metadata.event_type = "USER_LOGIN"
principal.user.userid = $userid
match:
$userid by 1h
信息中心
metadata.event_type = "USER_LOGIN"
principal.user.userid = $userid
match:
$userid by 1h
示例:检测行为(用户 =“Alex”)
- 事件 1:Alex 在 00:30 登录。这属于
[00:00:00-00:59:59]窗口。引擎会针对此窗口为 Alex 生成检测结果。 - 事件 2:另一位用户“Taylor”在 00:45 登录。这也属于
[00:00:00-00:59:59],但由于$userid不同,引擎会为 Taylor 单独生成一个检测结果。 - 事件 3:Alex 在 00:40 再次登录。这仍在
[00:00:00-00:59:59]期限内。由于系统已检测到 Alex,因此此事件会被去重。系统不会生成新的检测结果。 - 事件 4:Alex 在 01:20 登录。这属于下一个窗口,即
[01:00:00-01:59:59]。引擎会为 Alex 生成新的检测结果。
尽管 Alex 的事件 1 和事件 4 发生时间相差不到 1 小时,但由于事件 4 跨越了固定窗口边界,因此它们属于不同的检测。
为缺席检测配置滚动窗口
如需在数量为零时发出提醒并避免编译器故障,请完成以下步骤:
- 确定检测目标。确定您要搜索的是高频活动还是缺乏活动。
- 选择
window关键字。使用over表示频次,使用by表示缺席。 - 参考窗口边界。使用
window_start和window_end关键字来引用时间段的具体边界。
背景信息:使用 outcome: $ext_window_end = window_end 可在提醒元数据中包含错过的心跳的确切结束时间。
示例:使用元数据检测缺失的心跳
借助滚动窗口,您可以针对零计数发出提醒,这有助于您在搜索缺少活动时避免编译器失败。
规则
rule missing_heartbeat_detection {
meta:
description = "Alert when a system fails to check in within a 24h block"
events:
$e.metadata.event_type = "STATUS_UPDATE"
$host = $e.principal.hostname
match:
$host by 24h // Tumbling window lets you detect zero counts
outcome:
$event_count = count($e.metadata.id)
$missing_window_start = window_start
$missing_window_end = window_end
condition:
$event_count = 0 and window_start > "2026-01-01T12:30:00Z"
}
搜索
metadata.event_type = "STATUS_UPDATE"
$host = principal.hostname
match:
$host by 24h // Tumbling window lets you detect zero counts
outcome:
$event_count = count(metadata.id)
$missing_window_start = window_start
$missing_window_end = window_end
信息中心
metadata.event_type = "STATUS_UPDATE"
$host = principal.hostname
match:
$host by 24h // Tumbling window lets you detect zero counts
outcome:
$event_count = count(metadata.id)
$missing_window_start = window_start
$missing_window_end = window_end
滑动窗口
滑动窗口锚定到特定的透视事件,并向前 (after) 或向后 (before) 查看。
常见使用场景
如果事件序列至关重要,请使用滑动窗口:
- 严格的序列:检测攻击链(例如,
e1在e2发生后最多两分钟内发生)。 - 相对时间:查找在触发器特定偏移量内发生的事件(例如,在
Process Start发生后 30 秒内发生的Network Connection)。 - 缺席检测:识别在开始事件发生后,必需的“清理”或“心跳”事件何时未能发生。
语法
match: <grouping_keys> over <duration> [before|after] <$pivot_event>
| 组件 | 说明 | 示例 |
|---|---|---|
| 分组键 | 用于将事件关联在一起的常见字段。 | $host,$user |
| 时长 | 相对于透视事件的时间偏移值。 | 5m、1h、30s |
| 方向 | 窗口是向前还是向后扩展。 | after,before |
| 转换事件 | 用于锚定窗口的事件变量。 | $proc,$alert |
以下是有效的滑动窗口示例:
$var1, $var2 over 5m after $e1$user over 1h before $e2$host, $ip over 1h before $e2
要求和限制
- 性能:滑动窗口比跳跃窗口需要更多的处理能力。仅在严格要求事件顺序时使用它们(例如,一个事件必须在另一个事件发生后的五分钟内发生)。
- 单事件查询:请勿将滑动窗口用于单事件逻辑。请改用
condition部分中的多个事件变量。
示例:前瞻性相关性 (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
}
搜索
搜索不支持 after。
信息中心
信息中心不支持 after。
示例:回顾性相关性 (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
}
搜索
搜索不支持 before。
信息中心
信息中心不支持 before。
问题排查
您可以通过本部分了解 YARA-L 中的延迟时间、限制和常见窗口化问题的修复方法。
延迟和限制
使用滚动窗口 (
by) 的规则仅在固定时间块结束时触发。例如,如果规则的频次为match: $user by 24h,则只有在 24 小时的时间窗口完全过去后,系统才会评估该规则。提醒延迟时间:使用
by(滚动)的规则仅在固定时间块结束后触发。by 24h规则不会在窗口中间发出提醒。界面不一致:在“搜索”和“信息中心”中,
window_start关键字直接指向TIME_BUCKET字段。当您按window_start进行过滤或分组时,界面中的列标题会显示为TIME_BUCKET。这是一个已知的界面显示限制;您的逻辑仍然有效。
错误修复
| 错误代码 | 说明 | 修复 |
|---|---|---|
| 变量不受限 | 规则使用 over(滑动窗口)和 $count = 0 条件。 |
将窗口化关键字更改为 by(翻滚窗口)。滑动窗口需要存在一个事件来锚定窗口,而翻滚窗口则不需要。 |
| 界面标头不一致 | 用户在界面中看到的是 TIME_BUCKET,而不是 window_start。 |
无需修正。过滤和排序逻辑仍可使用关键字正常运行。 |
未知标识符:window_start |
使用了关键字,但在 match 中未定义窗口。 |
向 match 部分添加开窗声明(例如 $hostname by 1h)。 |
在活动中无效使用 window_start |
该关键字在 events 部分中引用。 |
将逻辑移至 condition 或 outcome 部分。只有在匹配阶段对事件进行分组后,才会计算窗口边界。 |