应用 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 天。

示例:固定间隔分组

以下规则按 $userid 将登录信息分组到 1 小时的不重叠窗口中。

规则

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 跨越了固定时间窗口边界,因此它们属于不同的检测。

为缺席检测配置翻滚窗口

如需在数量为零时发出提醒并避免编译器故障,请完成以下步骤:

  1. 确定检测目标。确定您是搜索高频活动还是缺乏活动。
  2. 选择window关键字。使用 over 表示频次,使用 by 表示缺席。
  3. 参考窗口边界。使用 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 部分。窗口边界仅在匹配阶段对事件进行分组后计算。

后续步骤

需要更多帮助?获得社区成员和 Google SecOps 专业人士的解答。