YARA-L 2.0 のウィンドウ処理ロジック
このガイドは、セキュリティ エンジニアがクエリに適切なウィンドウ タイプを選択し、「variable not bounded」コンパイラ エラーを回避するのに役立ちます。スライディング ウィンドウからタンブリング ウィンドウに移行すると、ハートビートの欠落やログソースの失敗など、イベントの不在に依存するロジックを構築できます。
始める前に
YARA-L クエリを作成して変更するには、アカウントに次のいずれかのロールがあることを確認してください。
- Detection Engine 管理者 (
roles/chronicle.detectionEngineAdmin) - SecOps 編集者 (
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 タイムスタンプに直接解決される、2 つの汎用的な予約済みキーワードが用意されています。これらのキーワードを使用すると、時間バケットの境界にアクセスできます。
window_start: 時間バケットの開始境界。window_end: 時間バケットの終了境界。
使用上の制約
- 一致要件: これらのキーワードを使用するには、
matchセクションでウィンドウ(byまたはover)を定義する必要があります。 - セクションの制限: これらのキーワードは、
condition、order、outcomeで使用します。eventsセクションでは無効です。 - 名前空間: これらをカスタム変数名(例:
$window_start)として使用しないでください。
ウィンドウ タイプと構文を決定する
この表は、検出ルールに使用するウィンドウ タイプと構文を決定する際のクイック リファレンスとして使用してください。
| シナリオ | 推奨ウィンドウ | 推奨キーワード | 主なメリット |
|---|---|---|---|
| 高頻度の検出 (ブルート フォース攻撃など) | スライディング ウィンドウ(over) |
window_start、window_end |
ローリング期間内にしきい値に達するとすぐにトリガーされます。 |
| 不在/不存在 (ハートビートの欠落など) | タンブリング ウィンドウ(by) |
window_start、window_end |
イベントが 1 つも発生しなくても、固定時間ブロックを評価し、 Variable Not Bounded エラーを防ぎます。 |
| 時系列レポート | スライディングまたはタンブリング | order: window_start asc |
Chronicle UI でのタイムライン分析を容易にするために、アラート出力を標準化します。 |
| 時間制限付きフィルタリング | スライディングまたはタンブリング | condition: window_start > "2026-01-01 00:00:00Z" |
GoogleSQL タイムスタンプの強制変換を使用して、ルール評価を特定の日付に制限します。 |
タイムスタンプ タイプとタイムゾーンを比較する
YARA-L では、window_start と window_end を GoogleSQL タイムスタンプ形式の文字列と直接比較できます。これにより、手動で型キャストを行わずに正確なフィルタリングを実行できます。
注: UDM イベントのタイムスタンプと一致させるには、常に Z 接尾辞("2026-03-17T17:35:00Z" など)を使用して UTC を指定します。
パフォーマンスを向上させるには、タイムスタンプ フィルタを使用します。あるイベントが別のイベントの後に発生したことを確認するだけでよい場合は、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 セクションで指定しますが、重複間隔とウィンドウのアライメントはシステムによって定義されます。その後、イベントはこれらの事前定義されたウィンドウ内で関連付けられます。
例: 継続的な関連付けのための重複するホップ ウィンドウ
次の例は、[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
タンブリング ウィンドウ
注: この機能は、地域によってはすべてのお客様がご利用いただけない場合があります。
タンブリング ウィンドウは、データを固定サイズの重複しない連続した時間間隔に分割します。 各イベントのタイムスタンプは、1 つのウィンドウに正確に収まります。タンブリング ウィンドウ間に重複はありません。これは、時間間隔が重複する可能性があるホップ ウィンドウまたはスライディング ウィンドウとは対照的です。
タンブリング ウィンドウを実装するには、match セクションで by 演算子を使用します。タンブリング ウィンドウは、時間を連続した連続したブロックに分割します。例:
by 1h: 1 時間ごとにウィンドウを作成します(例:[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])。
一般的なユースケース
タンブリング ウィンドウは、次のことを行う必要がある場合に使用します。
- 重複しない個別の時間ブロックでイベントを分析する。
- イベントの発生回数に関係なく、固定時間間隔内で、特定のエンティティ(一致変数で定義)に対して 1 つの検出のみを生成する。
- 固定期間にわたって一意のエンティティをカウントする。
重複排除の動作
タンブリング ウィンドウの主な特徴は、同じ一致変数のセットに対して、各ウィンドウ内の検出をエンジンが処理する方法です。
- ウィンドウごとに 1 つの検出: 一致変数の特定のセットの値(特定の
$useridなど)に対して、エンジンは 1 つのタンブリング ウィンドウに対して最大で 1 つの検出を生成します。 - 最初に到着したものが優先: 特定のウィンドウ内で、一致変数のセットのルール条件を満たす最初のイベントが取り込まれると、検出がトリガーされます。
- 重複排除: 同じウィンドウ インスタンス内で条件に一致する後続のイベントでは、追加の検出は生成されません。
構文
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
例: 検出動作(user = "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の 2 分後までに発生します)。 - 相対タイミング: トリガーの特定のオフセット内で発生するイベントを検索します(例:
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
要件と制限事項
- パフォーマンス: スライディング ウィンドウは、ホップ ウィンドウよりも多くの処理能力を必要とします。イベントの順序が厳密に要求される場合(あるイベントが別のイベントの 5 分以内に発生する必要がある場合など)にのみ使用してください。
- 単一イベント クエリ: 単一イベント ロジックにスライディング ウィンドウを使用しないでください。代わりに、
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ルールは、ウィンドウの中間ではアラートを生成しません。UI の不一致: 検索とダッシュボードでは、
window_startキーワードはTIME_BUCKETフィールドを直接参照します。window_startでフィルタまたはグループ化すると、UI の列ヘッダーにTIME_BUCKETと表示されます。これは UI の表示上の既知の制限事項です。ロジックは有効なままです。
エラーの修復
| エラーコード | 説明 | 修正 |
|---|---|---|
| Variable Not Bounded | ルールで $count = 0 条件で over(スライディング ウィンドウ)を使用しています。 |
ウィンドウ処理キーワードを by(タンブリング ウィンドウ)に変更します。スライディング ウィンドウでは、ウィンドウを固定するためにイベントが存在する必要がありますが、タンブリング ウィンドウでは必要ありません。 |
| UI ヘッダーの不一致 | UI に window_start ではなく TIME_BUCKET が表示されます。 |
修正は必要ありません。キーワードを使用すると、フィルタリングと並べ替えのロジックは引き続き正しく機能します。 |
Unknown Identifier: window_start |
キーワードが使用されていますが、match でウィンドウが定義されていません。 |
ウィンドウ処理ステートメントを match セクションに追加します(例: $hostname by 1h)。 |
イベントでのwindow_start の無効な使用 |
キーワードが events セクションで参照されています。 |
ロジックを condition セクションまたは outcome セクションに移動します。ウィンドウの境界は、イベントが一致フェーズでグループ化された後にのみ計算されます。 |
次のステップ
さらにサポートが必要な場合コミュニティ メンバーや Google SecOps のプロフェッショナルから回答を得ることができます。