繰り返しフィールド

以下でサポートされています。

統合データモデル(UDM)では、一部のフィールドが繰り返しとしてラベル付けされ、値やその他の種類のメッセージのリストであることを示します。このドキュメントでは、繰り返される UDM フィールドで式、プレースホルダ、配列インデックス、繰り返されるメッセージを使用する方法について説明します。

ブール式と繰り返しフィールド

変更されたブール式と変更されていないブール式は、繰り返しフィールドに対して動作できます。

次のイベントを考えてみましょう。

event_original {
  principal {
    // ip is a repeated field
    ip: [ "192.0.2.1", "192.0.2.2", "192.0.2.3" ]

    hostname: "host"
  }
}

変更された式

繰り返しフィールドの式で any 修飾子と all 修飾子を使用します。

  • any - 繰り返しフィールドの任意の要素が条件を満たす場合は、イベント全体が条件を満たします。次に例を示します。

    • event_originalany $e.principal.ip = "192.0.2.1" を満たします
    • event_originalany $e.repeated_field.field_a = "9.9.9.9" に失敗します
  • all - 繰り返しフィールドのすべての要素が条件を満たす場合は、イベント全体が条件を満たします。次に例を示します。

    • event_originalnet.ip_in_range_cidr(all $e.principal.ip, "192.0.2.0/8") を満たします
    • event_originalall $e.principal.ip = "192.0.2.2" に失敗します

any または all を使用して条件を記述する場合、not で条件を否定するときには、否定演算子を使用する場合と意味が異なる可能性があります。

次に例を示します。

  • not all $e.principal.ip = "192.168.12.16" は、一部の IP アドレスが 192.168.12.16 と一致していないかどうかをチェックします。つまり、このクエリでは、少なくとも 1 つの IP アドレスが 192.168.12.16 と一致しないことが確認されます。
  • all $e.principal.ip != "192.168.12.16" は、すべての IP アドレスが 192.168.12.16 と一致していないかどうかをチェックします。つまり、このクエリでは、192.168.12.16 に一致する IP アドレスがないことが確認されます。

制約:

  • any 演算子と all 演算子は、繰り返しフィールドとのみ互換性があります(スカラー フィールドとは互換性がありません)。
  • anyall を使用して 2 つの繰り返しフィールドを結合することはできません。たとえば、any $e1.principal.ip = $e2.principal.ip は無効です。
  • 参照リストの式では、any 演算子と all 演算子はサポートされていません。

変更されていない式

変更されていない式では、繰り返しフィールドの各要素が個別に処理されます。イベントの繰り返しフィールドに n 個の要素が含まれている場合、クエリはイベントの n 個のコピーに適用されます。ここで、各コピーには繰り返しフィールドのいずれかの要素が含まれます。これらのコピーは一時的なもので、保存されません。

ルールは次のコピーに適用されます。

イベント コピー principal.ip principal.hostname
event_copy_1 "192.0.2.1" "host"
event_copy_2 "192.0.2.2" "host"
event_copy_3 "192.0.2.3" "host"

いずれかのイベントコピーが繰り返しフィールドの変更されていない条件をすべて満たす場合は、イベント全体がすべての条件を満たします。したがって、繰り返しフィールドに複数の条件がある場合、1 つのイベントコピーはそれらすべてを満たす必要があります。次のクエリの例では、上記のデータセットの例を使用してこの動作を示します。

例: 変更されていない式

次のルールは、event_original データセットの例に対して実行すると、1 つの一致を返します。これは、event_copy_1 がすべてのイベントの述語を満たしているためです。

rule repeated_field_1 {
  meta:
  events:
    net.ip_in_range_cidr($e.principal.ip, "192.0.2.0/8") // Checks if IP address matches 192.x.x.x
    $e.principal.ip = "192.0.2.1"
  condition:
    $e
}

次のルールは、event_original データセットの例に対して実行しても一致を返しません。これは、$e.principal.ip にすべてのイベントの述語を満たすイベントコピーがないためです。

rule repeated_field_2 {
  meta:
  events:
    $e.principal.ip = "192.0.2.1"
    $e.principal.ip = "192.0.2.2"
  condition:
    $e
}

繰り返しフィールドの変更された式は、繰り返しフィールドの変更されていない式と互換性があります。これは、要素リストが各イベントコピーで同じであるためです。次のルールを検討します。

rule repeated_field_3 {
  meta:
  events:
    any $e.principal.ip = "192.0.2.1"
    $e.principal.ip = "192.0.2.3"
  condition:
    $e
}

ルールは次のコピーに適用されます。

イベント コピー principal.ip any $e.principal.ip
event_copy_1 "192.0.2.1" ["192.0.2.1", "192.0.2.2", "192.0.2.3"]
event_copy_2 "192.0.2.2" ["192.0.2.1", "192.0.2.2", "192.0.2.3"]
event_copy_3 "192.0.2.3" ["192.0.2.1", "192.0.2.2", "192.0.2.3"]

この場合、すべてのコピーが any $e.principal.ip = "192.0.2.1" を満たしますが、$e.principal.ip = "192.0.2.3" を満たすのは event_copy_3 のみです。その結果、イベント全体が一致します。

これらの式タイプは、次のように考えることもできます。

  • any または all を使用する繰り返しフィールドの式は、event_original のリストに対して作用します。
  • any または all を使用しない繰り返しフィールドの式は、個々の event_copy_n イベントに対して作用します。

プレースホルダと繰り返しフィールド

繰り返しフィールドはプレースホルダの割り当てで機能します。繰り返しフィールドの変更されていない式と同様に、要素ごとにイベントのコピーが作成されます。event_copy の同じ例を使用すると、プレースホルダはイベントのコピーごとに event_copy_n の繰り返しフィールドの値を取得します。ここで、n はイベントのコピー番号です。プレースホルダが match セクションで使用されている場合、複数の一致が発生する可能性があります。

例: 繰り返しフィールドのプレースホルダ

次の例では、1 つの一致が生成されます。`$ip` プレースホルダは `event_copy_1` の `192.0.2.1` と等しく、ルールの述語を満たしています。一致のイベント サンプルには、単一の要素 `event_original` が含まれています。

// Generates 1 match.
rule repeated_field_placeholder1 {
  meta:
  events:
    $ip = $e.principal.ip
    $ip = "192.0.2.1"
    $host = $e.principal.hostname

  match:
    $host over 5m

  condition:
    $e
}

次の例では、3 つの一致が生成されます。$ip プレースホルダは、event_copy_n のコピーごとに異なる値になります。グループ化は、一致セクションにある $ip で行われます。したがって、$ip 一致変数の値がそれぞれ異なる 3 つの一致結果が得られます。各一致には、単一の要素 event_original という同じイベント サンプルがあります。

// Generates 3 matches.
rule repeated_field_placeholder2 {
  meta:
  events:
    $ip = $e.principal.ip
    net.ip_in_range_cidr($ip, "192.0.2.0/8") // Checks if IP matches 192.x.x.x

  match:
    $ip over 5m

  condition:
    $e
}

繰り返しフィールドに割り当てられたプレースホルダを使用する結果

プレースホルダは、リスト全体ではなく、各繰り返しフィールドの各要素に割り当てられます。outcome セクションで使用されている場合は、前のセクション条件を満たす要素のみを使用して結果が計算されます。

次のルールを検討します。

rule outcome_repeated_field_placeholder {
  meta:
  events:
    $ip = $e.principal.ip
    $ip = "192.0.2.1" or $ip = "192.0.2.2"
    $host = $e.principal.hostname

  match:
    $host over 5m

  outcome:
    $o = array_distinct($ip)

  condition:
    $e
}

このルールには 4 つの実行ステージがあります。最初のステージはイベントのコピーです。

イベント コピー $ip $host $e
event_copy_1 "192.0.2.1" "host" event_id
event_copy_2 "192.0.2.2" "host" event_id
event_copy_3 "192.0.2.3" "host" event_id

events セクションでは、フィルタに一致しない行が除外されます。

イベント コピー $ip $host $e
event_copy_1 "192.0.2.1" "host" event_id
event_copy_2 "192.0.2.2" "host" event_id

"192.0.2.3"$ip = "192.0.2.1" or $ip = "192.0.2.2" を満たしていないため、event_copy_3 は除外されます。

match セクションは、一致変数ごとにグループ化し、outcome セクションでは各グループに対して集計を行います。

$host $o $e
"host" ["192.0.2.1", "192.0.2.2"] event_id

$o = array_distinct($ip) は、イベントのコピーステージではなく、前のステージの $ip を使用して計算されます。

最後に、condition セクションで各グループをフィルタします。このルールは $e の存在を確認するだけなので、前の行では 1 つの検出が生成されます。

$o には $e.principal.ip のすべての要素が格納されていません。すべての要素が events セクションのすべての条件を満たすわけではないためです。ただし、イベント サンプルでは event_original が使用されるため、e.principal.ip のすべての要素がイベント サンプルに表示されます。

配列のインデックス登録

繰り返しフィールドに対して配列インデックスを作成できます。n 番目の繰り返しフィールド要素にアクセスするには、標準のリスト構文を使用します(要素は 0 から始まるインデックスです)。範囲外の要素はデフォルト値を返します。

  • $e.principal.ip[0] = "192.168.12.16"
  • $e.principal.ip[999] = "" 要素数が 1,000 個未満の場合は、true と評価されます。

制約:

  • インデックスは、負の値ではない整数値のリテラルでなければなりません。たとえば、$e.principal.ip[-1] は無効です。
  • int 型の値(int に設定されたプレースホルダなど)はカウントされません。
  • 配列インデックスを anyall と組み合わせることはできません。たとえば、any $e.intermediary.ip[0] は無効です。
  • 配列インデックスをマップ構文と組み合わせることはできません。たとえば、$e.additional.fields[0]["key"] は無効です。
  • フィールド パスに複数の繰り返しフィールドが含まれている場合、すべての繰り返しフィールドで配列インデックスを使用する必要があります。たとえば、$e.intermediary.ip[0] は無効です。intermediaryip は両方とも繰り返しフィールドですが、ip のインデックスのみがあるためです。

繰り返しメッセージ

message フィールドが繰り返されると、意図しない効果として一致の可能性が低下します。これを次の例に示します。

次のイベントを考えてみましょう。

event_repeated_message {
  // about is a repeated message field.
  about {
    // ip is a repeated string field.
    ip: [ "192.0.2.1", "192.0.2.2", "192.0.2.3" ]

    hostname: "alice"
  }
  about {
    hostname: "bob"
  }
}

繰り返しフィールドの変更されていない式で説明したように、繰り返しフィールドの各要素に対してイベントの一時コピーが作成されます。次のルールを検討します。

rule repeated_message_1 {
  meta:
  events:
    $e.about.ip = "192.0.2.1"
    $e.about.hostname = "bob"
  condition:
    $e
}

ルールは次のコピーに適用されます。

イベント コピー about.ip about.hostname
event_copy_1 "192.0.2.1" "alice"
event_copy_2 "192.0.2.2" "alice"
event_copy_3 "192.0.2.3" "alice"
event_copy_4 "" "bob"

すべての式を満たすイベントコピーが存在しないため、イベントはルールと一致しません。

繰り返しメッセージと配列インデックス

繰り返しメッセージ フィールドに対して変更されていない式とともに配列インデックスを使用すると、別の予期しない動作が発生する可能性があります。配列インデックスを使用する次のルール例について考えてみましょう。

rule repeated_message_2 {
  meta:
  events:
    $e.about.ip = "192.0.2.1"
    $e.about[1].hostname = "bob"
  condition:
    $e
}

ルールは次のコピーに適用されます。

イベント コピー about.ip about[1].hostname
event_copy_1 "192.0.2.1" "bob"
event_copy_2 "192.0.2.2" "bob"
event_copy_3 "192.0.2.3" "bob"
event_copy_4 "" "bob"

event_copy_1repeated_message_2 のすべての式を満たしているため、イベントはルールに一致します。

ルール repeated_message_1 には配列インデックスがなく、一致が生成されませんでしたが、ルール repeated_message_2 は配列インデックスを使用して一致を生成したため、予期しない動作が発生する可能性があります。

さらにサポートが必要な場合 コミュニティ メンバーや Google SecOps のプロフェッショナルから回答を得ることができます。