YARA-L 2.0 言語の構文

このセクションでは、YARA-L 構文の主な要素について説明します。YARA-L 2.0 言語の概要もご覧ください。

ルールの構造

YARA-L 2.0 では、変数の宣言、定義、用途を次の順序で指定する必要があります。

  1. メタ
  2. イベント
  3. 一致(省略可)
  4. outcome(省略可)
  5. 条件
  6. options(省略可能)

次の図は、ルールの一般的な構造を示しています。

rule <rule Name>
{
    meta:
    // Stores arbitrary key-value pairs of rule details, such as who wrote
    // it, what it detects on, version control, etc.

  events:
    // Conditions to filter events and the relationship between events.

  match:
    // Values to return when matches are found.

  outcome:
    // Additional information extracted from each detection.

  condition:
    // Condition to check events and the variables used to find matches.

  options:
    // Options to turn on or off while executing this rule.
}

メタセクションの構文

Meta セクションは複数の行で構成され、各行は Key-Value ペアを定義します。キー部分は引用符で囲まない文字列に、値の部分は引用符で囲まれた文字列にする必要があります。

<key> = "<value>"

有効な meta セクション行の例を次に示します。 none meta: author = "Chronicle" severity = "HIGH"

events セクションの構文

events セクションに述語のリストを表示して、次の項目を指定します。

  • 変数の宣言
  • イベント変数のフィルタ
  • イベント変数の結合

変数の宣言

変数を宣言する場合は、次の構文を使用します。

  • <EVENT_FIELD> = <VAR>
  • <VAR> = <EVENT_FIELD>

次の例に示すように、どちらも同等です。

  • $e.source.hostname = $hostname
  • $userid = $e.principal.user.userid

この宣言は、この変数がイベント変数に指定されたフィールドを表すことを示します。イベント フィールドが繰り返しフィールドの場合、一致変数は配列内の任意の値を表すことができます。 1 つの一致変数またはプレースホルダ変数に複数のイベント フィールドを割り当てることもできます。これは推移的な結合条件です。

たとえば、次のようになります。

  • $e1.source.ip = $ip
  • $e2.target.ip = $ip

これは次と同等です。

  • $e1.source.ip = $ip
  • $e1.source.ip = $e2.target.ip

変数を使用する場合、変数宣言でその変数を宣言する必要があります。変数が宣言なしで使用されていると、コンパイル エラーとみなされます。

イベント変数のフィルタ

1 つのイベント変数を操作するブール式はフィルタと見なされます。

イベント変数の結合

ルールで使用するすべてのイベント変数は、次のいずれかの方法で他のすべてのイベント変数と結合する必要があります。

  • 2 つの結合されたイベント変数のイベント フィールドを直接比較する(例: $e1.field = $e2.field)。式に算術を含めることはできません。

  • イベント フィールドのみを含む推移的結合によって間接的に結合する(「推移的結合」の定義については、変数の宣言をご覧ください)。式に算術を含めることはできません。

たとえば、ルールで $e1、$e2、$e3 が使用されているとすると、以降の events セクションは有効です。

events:
  $e1.principal.hostname = $e2.src.hostname // $e1 joins with $e2
  $e2.principal.ip = $e3.src.ip // $e2 joins with $e3
events:
  // $e1 joins with $e2 via function to event comparison
  re.capture($e1.src.hostname, ".*") = $e2.target.hostname
events:
  // $e1 joins with $e2 via an `or` expression
  $e1.principal.hostname = $e2.src.hostname
  or $e1.principal.hostname = $e2.target.hostname
  or $e1.principal.hostname = $e2.principal.hostname
events:
  // all of $e1, $e2 and $e3 are transitively joined via the placeholder variable $ip
  $e1.src.ip = $ip
  $e2.target.ip = $ip
  $e3.about.ip = $ip
events:
  // $e1 and $e2 are transitively joined via function to event comparison
  re.capture($e2.principal.application, ".*") = $app
  $e1.principal.hostname = $app

ただし、以下は無効な events セクションの例です。

events:
  // Event to arithmetic comparison is an invalid join condition for $e1 and $e2.
  $e1.principal.port = $e2.src.port + 1
events:
  $e1.src.ip = $ip
  $e2.target.ip = $ip
  $e3.about.ip = "192.1.2.0" //$e3 is not joined with $e1 or $e2.
events:
  $e1.src.port = $port

  // Arithmetic to placeholder comparison is an invalid transitive join condition.
  $e2.principal.port + 800 = $port

一致セクションの構文

一致条件を確認する前に、match セクションでグループ イベントの一致変数を一覧表示します。これらのフィールドは、一致するたびに返されます。

  • 各一致変数が表す内容を events セクションで指定します。
  • over キーワードに続くイベントを相関させる期間を指定します。期間外のイベントは無視されます。
  • 期間を指定するには、次の構文 <number><m/h/d> を使用します。

    m/h/d は、それぞれ分、時、日を表します。

  • 指定できる最小時間は 1 分です。

  • 指定できる最大時間は 48 時間です。

有効な match の例を次に示します。

$var1, $var2 over 5m

このステートメントは、ルールが一致した場合に $var1$var2events セクションで定義)を返します。指定する時間は 5 分です。間隔が 5 分を超えるイベントは相関されないため、ルールで無視されます。

有効な match セクションの別の例を示します。

$user over 1h

次のステートメントは、ルールが一致した場合に $user を返します。指定する期間は 1 時間です。1 時間を超えるイベントは相関されません。これらのイベントは、ルールで検出対象と見なされません。

有効な match セクションの別の例を示します。

$source_ip, $target_ip, $hostname over 2m

次のステートメントは、ルールが一致した場合に $source_ip$target_ip$hostname を返します。指定する期間は 2 分です。間隔が 2 分を超えるイベントは相関されません。これらのイベントは、ルールで検出対象と見なされません。

次の例は、無効な match セクションを示しています。

  • var1, var2 over 5m // invalid variable name
  • $user 1h // missing keyword

一致セクションでのゼロ値の処理

ルールエンジンは、一致セクションで使用されているすべてのプレースホルダのゼロ値を暗黙的に除外します(文字列の場合は ""、数値の場合は 0、ブール値の場合は false列挙型の場合は位置 0 の値です)。次の例では、ゼロ値を除外するルールを示します。

rule ZeroValuePlaceholderExample {
  meta:
  events:
    // Because $host is used in the match section, the rule 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 section,
    // there is no implicit filtering of zero values for $otherPlaceholder.
    $otherPlaceholder = $e.principal.ip

  match:
    $host over 5m

  condition:
    $e
}

ただし、プレースホルダが関数に割り当てられている場合、一致セクションで使用されているプレースホルダのゼロ値がルールによって暗黙的に除外されません。次の例では、ゼロ値を除外するルールを示します。

rule ZeroValueFunctionPlaceholder {
  meta:
  events:
    // Even though $ph is used in the match section, there is no
    // implicit filtering of zero values for $ph, because $ph is assigned to a function.
    $ph = re.capture($e.principal.hostname, "some-regex")

  match:
    $ph over 5m

  condition:
    $e
}

ゼロ値の暗黙的なフィルタリングを無効にするには、オプション セクションallow_zero_values オプションを使用します。

ホップ ウィンドウ

デフォルトでは、一致セクションを含む YARA-L 2.0 ルールは、ホップ ウィンドウを使用して評価されます。ルールの実行時間範囲は、match ウィンドウで指定された期間を含む、重複するホップ ウィンドウのセットに分割されます。その後、イベントは各ホップ ウィンドウ内で関連付けられます。

たとえば、時間範囲 [1:00, 2:00] に対して実行されるルールで、30mmatch セクションがある場合、次のような重複するホップ ウィンドウのセットが発生する可能性があります。[1:00, 1:30]、[1:03, 1:33]、[1:06, 1:36] などです。これらのウィンドウは、複数のイベントを関連付けるために使用されます。

スライディング ウィンドウ

ホップ ウィンドウの使用は、特定の順序で発生するイベントを検索する効果的な方法ではありません(たとえば、e1e2 から最大 2 分後に発生します)。イベント e1 の発生とイベント e2 の発生は、生成された同じホップ ウィンドウに属する場合にのみ相関されます。

このようなイベント シーケンスを検索するには、スライディング ウィンドウを使用すると効果的です。match セクションで指定された期間のスライディング ウィンドウは、指定されたピボット イベント変数の開始時または終了時に生成されます。次に、各スライディング ウィンドウ内でイベントが相互に関連付けられます。これにより、特定の順序で発生するイベントを検索できます(たとえば、e1e2 から 2 分後までに発生します)。イベント e1 がイベント e2 の後のスライディング ウィンドウ期間内に発生した場合、イベント e1 の発生とイベント e2 の発生は相関します。

ルールの match セクションで、スライディング ウィンドウを次のように指定します。

<match-var-1>, <match-var-2>, ... over <duration> before|after <pivot-event-var>

ピボット イベント変数は、スライディング ウィンドウに基づくイベント変数です。before キーワードを使用する場合、スライディング ウィンドウが生成され、ピボット イベントが発生するたびに終了します。after キーワードを使用する場合、ピボット イベントが発生するたびにスライディング ウィンドウが生成されます。

有効なスライディング ウィンドウの使用方法の例を次に示します。

  • $var1, $var2 over 5m after $e1
  • $user over 1h before $e2

スライディング ウィンドウのルールの例をご覧ください。

スライディング ウィンドウは複数のイベントを検出するように設計されているため、単一イベントルールにはスライディング ウィンドウを使用しないことをおすすめします。いずれかのルールがこのカテゴリに当てはまる場合は、次のいずれかの回避策をおすすめします。

  • 複数のイベント変数を使用するようにルールを変換します。ルールで複数のイベントの発生が必要な場合は、条件セクションを更新します。
    • 必要に応じて、スライディング ウィンドウを使用する代わりにタイムスタンプ フィルタを追加することを検討してください。例: $permission_change.metadata.event_timestamp.seconds < $file_creation.metadata.event_timestamp.seconds
  • スライディング ウィンドウを削除します。

結果セクションの構文

outcome セクションでは、任意の名前で最大 20 個の結果変数を定義できます。これらの結果は、ルールによって生成された検出に保存されます。各検出は、結果に対して異なる値を持つ場合があります。

結果名 $risk_score は特別なものです。オプションでこの名前を使用して結果を定義できます。定義する場合は、整数型または浮動型にする必要があります。入力すると、ルール検出から発生したアラートの Enterprise Insights ビューrisk_score が表示されます。

ルールの結果セクションに $risk_score 変数を含めない場合、次のいずれかのデフォルト値が設定されます。

  • ルールがアラートを生成するように構成されている場合、$risk_score は 40 に設定されます。
  • ルールがアラートを生成するように構成されていない場合、$risk_score は 15 に設定されます。

$risk_score の値は security_result.risk_score UDM フィールドに格納されます。

結果変数のデータ型

各結果変数には異なるデータ型を含めることができます。このデータ型は計算に使用される式によって決まります。次の結果データ型がサポートされています。

  • 整数
  • 浮動小数点数
  • string
  • 整数のリスト
  • 浮動小数点数のリスト
  • 文字列のリスト

条件付きロジック

条件付きロジックを使用して、結果の値を計算できます。条件は次の構文パターンを使用して指定します。

if(BOOL_CLAUSE, THEN_CLAUSE)
if(BOOL_CLAUSE, THEN_CLAUSE, ELSE_CLAUSE)

条件式は、「BOOL_CLAUSE が true の場合は、THEN_CLAUSE を返し、それ以外の場合は ELSE_CLAUSE を返す」と読むことができます。

BOOL_CLAUSE は、ブール値に評価される必要があります。BOOL_CLAUSE 式は、events セクションの式と同様の形式を取ります。たとえば、次のものが含まれます。

  • 比較演算子を使用した UDM フィールド名。例:

    if($context.graph.entity.user.title = "Vendor", 100, 0)

  • プレースホルダ変数(events セクション内で定義したものなど)。例:

    if($severity = "HIGH", 100, 0)

  • outcome セクションで定義された別の結果変数。例:

    if($risk_score > 20, "HIGH", "LOW")

  • ブール値を返す関数。例:

    if(re.regex($e.network.email.from, `.*altostrat.com`), 100, 0)

  • リファレンス リストからの検索。例:

    if($u.principal.hostname in %my_reference_list_name, 100, 0)

  • 集計比較。例:

    if(count($login.metadata.event_timestamp.seconds) > 5, 100, 0)

THEN_CLAUSE と ELSE_CLAUSE は同じデータ型である必要があります。整数、浮動小数点数、文字列がサポートされています。

データ型が整数または浮動小数点の場合は、ELSE_CLAUSE を省略できます。省略すると、ELSE_CLAUSE は 0 と評価されます。次に例を示します。

`if($e.field = "a", 5)` is equivalent to `if($e.field = "a", 5, 0)`

データ型が文字列の場合、または THEN_CLAUSE がプレースホルダ変数または結果変数の場合は、ELSE_CLAUSE を指定する必要があります。

算術演算

ルールの outcome セクションと events セクションで、数学演算を使用して整数データ型または浮動小数点データ型を計算できます。Chronicle は、計算の最上位の演算子として、加算、減算、乗算、除算、係数をサポートしています。

次のスニペットは、outcome セクションでの計算例です。

outcome:
  $risk_score = max(100 + if($severity = "HIGH", 10, 5) - if($severity = "LOW", 20, 0))

各オペランドと算術式全体が正しく集計されている限り、次のタイプのオペランドに対して数学演算を使用できます(集計をご覧ください)。

  • 数値イベント フィールド
  • events セクションで定義されている数値プレースホルダ変数
  • outcome セクションで定義された結果変数
  • 整数または浮動小数点数を返す関数
  • 整数または浮動小数点数を返す集計

浮動小数点数ではモジュラスは使用できません。

結果のプレースホルダ変数

結果変数を計算するときに、ルールのイベント セクションで定義されたプレースホルダ変数を使用できます。この例では、ルールのイベント セクションで $email_sent_bytes が定義されていると仮定します。

単一イベントの例:

// No match section, so this is a single-event rule.

outcome:
  // Use placeholder directly as an outcome value.
  $my_outcome = $email_sent_bytes

  // Use placeholder in a conditional.
  $other_outcome = if($file_size > 1024, "SEVERE", "MODERATE")

condition:
  $e

マルチイベントの例:

match:
  // This is a multi event rule with a match section.
  $hostname over 5m

outcome:
  // Use placeholder directly in an aggregation function.
  $max_email_size = max($email_sent_bytes)

  // Use placeholder in a mathematical computation.
  $total_bytes_exfiltrated = sum(
    1024
    + $email_sent_bytes
    + $file_event.principal.file.size
  )

condition:
  $email_event and $file_event

結果割り当て式の結果変数

結果変数は、events セクションで定義されたプレースホルダ変数と同様に、他の結果変数を導出するために使用できます。$ トークンの後に変数名を付けた別の結果変数を割り当てる際に、結果変数を参照できます。結果変数は、ルールテキストで参照する前に定義する必要があります。割り当て式で使用する場合、結果変数は集計できません(集計をご覧ください)。

次の例では、結果変数 $risk_score は、結果変数 $event_count から値を取得します。

マルチイベントの例:

match:
  // This is a multi event rule with a match section.
  $hostname over 5m

outcome:
  // Aggregates all timestamp on login events in the 5 minute match window.
  $event_count = count($login.metadata.event_timestamp.seconds)

  // $event_count cannot be aggregated again.
  $risk_score = if($event_count > 5, "SEVERE", "MODERATE")

  // This is the equivalent of the 2 outcomes above combined.
  $risk_score2 = if(count($login.metadata.event_timestamp.seconds) > 5, "SEVERE", "MODERATE")

condition:
  $e

結果変数は、結果の割り当ての右側にある任意のタイプの式で使用できます。ただし、次の式を除きます。

  • 集約
  • Arrays.length() 関数の呼び出し
  • any 修飾子または all 修飾子を使用する場合

集約

繰り返しイベント フィールドは、スカラーではない値です。つまり、1 つの変数が複数の値を指します。たとえば、イベント フィールド変数 $e.target.ip は繰り返しフィールドであり、0 個、1 個または複数の IP 値を持つことができます。スカラーではない値です。一方、イベント フィールド変数 $e.principal.hostname は繰り返しフィールドではなく、1 つの値(すなわちスカラー値)を持ちます。

同様に、一致ウィンドウのあるルールの結果セクションで使用される繰り返しイベント フィールドと繰り返しイベント フィールドはいずれも非スカラー値です。たとえば、次のルールは、一致セクションを使用してイベントをグループ化し、結果セクションの繰り返しでないイベント フィールドを参照しています。

rule OutcomeAndMatchWindow{
  ...
  match:
    $userid over 5m
  outcome:
    $hostnames = array($e.principal.hostname)
  ...
}

ルールが実行される 5 分間のウィンドウには、0 個、1 個または複数のイベントが含まれる場合があります。結果セクションは、一致ウィンドウ内のすべてのイベントに対して機能します。結果セクション内で参照されるイベント フィールド変数は、一致ウィンドウ内の各イベントのフィールドの 0、1、または複数の値を指すことができます。前のルールでは、5 分のウィンドウに 5 つの $e イベントが含まれている場合、結果セクションの $e.principal.hostname は 5 つの異なるホスト名を指します。したがって、イベント フィールド変数 $e.principal.hostname は、このルールの結果セクションではスカラー以外の値になります。

結果変数は常に 1 つのスカラー値を生成する必要があるため、結果の割り当てが依存するスカラー以外の値を集計して、単一のスカラー値を生成する必要があります。結果セクションでは、以下はスカラーではない値であり、集計する必要があります。

  • ルールで一致セクションを使用する場合のイベント フィールド(繰り返しまたは繰り返しでない)
  • ルールで一致セクションを使用する場合のイベントのプレースホルダ(繰り返しまたは繰り返しでない)
  • ルールで一致セクションを使用しない場合の繰り返しイベント フィールド
  • ルールで一致セクションが使用されない場合に繰り返されるイベント プレースホルダ

一致セクションを使用しないルールの集計には、スカラー イベント フィールド、スカラー イベント プレースホルダ、定数をラップできます。ただし、ほとんどの集計でラップされた値が生成されるため、不要です。例外は、スカラー値を配列に変換するために使用できる array() 集計です。

結果変数は集計と同様に扱われます。別の結果の割り当てで参照されたときに再集計することはできません。

次の集計関数を使用できます。

  • max(): 可能性のあるすべての値の最大値を出力します。整数と浮動小数点数でのみ使用できます。
  • min(): 可能性のあるすべての値の最小値を出力します。整数と浮動小数点数でのみ使用できます。
  • sum(): 可能性のあるすべての値の和を出力します。整数と浮動小数点数でのみ使用できます。
  • count_distinct(): 可能性のあるすべての値を収集し、可能性のある値の一意の値の数を出力します。
  • count(): count_distinct() のように動作しますが、可能性のある値の一意でない値の数を返します。
  • array_distinct(): 可能性のあるすべての一意の値を収集し、これらの値のリストを出力します。Distinct 値のリストを 25 個のランダムな要素に切り詰めます。一意のリストを取得するための重複除去が最初に適用され、次に切り捨てが適用されます。
  • array(): array_distinct() のように動作しますが、一意でない値のリストを返します。また、値のリストを 25 個のランダムな要素に切り詰めます。

集計関数は、複数のイベントが存在することを指定する condition セクションがルールに含まれている場合に重要です。集計関数は、検出を生成したすべてのイベントに対して動作するためです。

たとえば、outcome セクションと condition セクションに以下が含まれているとします。

outcome:
  $asset_id_count = count($event.principal.asset_id)
  $asset_id_distinct_count = count_distinct($event.principal.asset_id)

  $asset_id_list = array($event.principal.asset_id)
  $asset_id_distinct_list = array_distinct($event.principal.asset_id)

condition:
  #event > 1

条件セクションでは、検出ごとに複数の event が必要であるため、集計関数は複数のイベントで動作します。次のイベントで 1 つの検出が生成されたとします。

event:
  // UDM event 1
  asset_id="asset-a"

event:
  // UDM event 2
  asset_id="asset-b"

event:
  // UDM event 3
  asset_id="asset-b"

結果の値は次のようになります。

  • $asset_id_count = 3
  • $asset_id_distinct_count = 2
  • $asset_id_list = ["asset-a", "asset-b", "asset-b"]
  • $asset_id_distinct_list = ["asset-a", "asset-b"]

結果セクションを使用する際の注意事項:

その他の注意事項と制限事項:

  • outcome セクションでは、events セクションまたは outcome セクションでまだ定義されていない新しいプレースホルダ変数を参照できません。
  • outcome セクションでは、events セクションで定義されていないイベント変数を使用できません。
  • イベント フィールドが属するイベント変数が events セクションですでに定義されている場合、outcome セクションでは、events セクションで使用されていないイベント フィールドを使用できます。
  • outcome セクションで、events セクションですでに関連付けられているイベント変数のみを関連付けることができます。相関は、異なるイベント変数の 2 つのイベント フィールドが等しい場合に発生します。

YARA-L 2.0 の概要の結果セクションを使用して例を確認できます。 結果セクションの検出の重複除去の詳細については、コンテキストアウェア分析の作成をご覧ください。

条件セクションの構文

  • events セクションで定義されているイベントとプレースホルダに一致する条件を指定する。詳しくは、次のセクションのイベントとプレースホルダの条件をご覧ください。
  • (省略可)and キーワードを使用して、outcome セクションで定義された結果変数を使用して一致条件を指定します。詳細については、次の結果条件をご覧ください。

カウント文字

# 文字は condition セクションの特殊文字です。イベント名またはプレースホルダ変数名の前で使用する場合は、すべての events セクション条件を満たす固有のイベントまたは値の数を表します。

たとえば、#c > 1 は、変数 c が複数回出現する必要があることを意味します。

値文字

$ 文字は condition セクションの特殊文字です。結果変数名の前で使用する場合は、その結果の値を表します。

イベント名またはプレースホルダ変数名の前で使用する場合は($event など)、#event > 0 を表します。

イベントとプレースホルダの条件

イベントとプレースホルダ変数の条件述語を一覧表示します。キーワード and または or に結合されます。キーワード and は任意の条件間で使用できますが、キーワード or は、ルールのイベント変数が 1 つしかない場合にのみ使用できます。

同じイベントでの 2 つのプレースホルダ間で or を使用する有効な例:

rule ValidConditionOr {
  meta:
  events:
      $e.metadata.event_type = "NETWORK_CONNECTION"

      // Note that all placeholders use the same event variable.
      $ph = $e.principal.user.userid  // Define a placeholder variable to put in match section.
      $ph2 = $e.principal.ip  // Define a second placeholder variable to put in condition section.
      $ph3 = $e.principal.hostname  // Define a third placeholder variable to put in condition section.

  match:
    $ph over 5m

  condition:
    $ph2 or $ph3
}

異なるイベントの 2 つの条件間で or を使用する無効な例:

rule InvalidConditionOr {
  meta:
  events:
      $e.metadata.event_type = "NETWORK_CONNECTION"
      $e2.graph.metadata.entity_type = "FILE"
      $e2.graph.entity.hostname  = $e.principal.hostname

      $ph = $e.principal.user.userid  // Define a placeholder variable to put in match section.

  match:
    $ph over 5m

  condition:
    $e or $e2 // This line will cause an error because there is an or between events.
}

制限付き条件と制限なし条件

次の条件は制限付きの条件です。関連付けられたイベント変数を強制的に存在するようにします。つまり、検出によりイベントが少なくとも 1 回出現する必要があります。

  • $var // equivalent to #var > 0
  • #var > n // where n >= 0
  • #var >= m // where m > 0

次の条件は制限なし条件です。関連付けられたイベント変数が存在しないようにします。つまり、検出でイベントの発生が発生せず、イベント変数のフィールドへの参照がゼロ値になる可能性もあります。制限なし条件を使用すると、一定期間内にイベントの不在を検出できます。たとえば、10 分以内に緩和イベントがない脅威イベントなどです。制限なし条件を使用するルールは、不在ルールと呼ばれます。

  • !$var // equivalent to #var = 0
  • #var >= 0
  • #var < n // where n > 0
  • #var <= m // where m >= 0

不在の場合の要件

不在ルールをコンパイルするには、次の要件を満たす必要があります。

  1. 少なくとも 1 つの UDM イベントに制限付き条件が必要です(つまり、1 つ以上の UDM イベントが存在する必要があります)。
  2. プレースホルダに制限なしの条件がある場合は、少なくとも 1 つの制限付き UDM イベントに関連付ける必要があります。
  3. エンティティに制限条件なしの場合は、少なくとも 1 つの制限付き UDM イベントに関連付けられている必要があります。

条件セクションを省略した次のルールを考慮します。

rule NonexistenceExample {
  meta:
  events:
      $u1.metadata.event_type = "NETWORK_CONNECTION" // $u1 is a UDM event.
      $u2.metadata.event_type = "NETWORK_CONNECTION" // $u2 is a UDM event.
      $e1.graph.metadata.entity_type = "FILE"        // $e1 is an Entity.
      $e2.graph.metadata.entity_type = "FILE"        // $e2 is an Entity.

      $user = $u1.principal.user.userid // Match variable is required for Multi-Event Rule.

      // Placeholder Associations:
      //   u1        u2
      //   |  \    /
      // port   ip
      //   |       \
      //   e1        e2
      $u1.target.port = $port
      $e1.graph.entity.port = $port
      $u1.principal.ip = $ip
      $u2.target.ip = $ip
      $e2.graph.entity.ip = $ip

      // UDM-Entity Associations:
      // u1 - u2
      // |  \  |
      // e1   e2
      $u1.metadata.event_type = $u2.metadata.event_type
      $e1.graph.entity.hostname = $u1.principal.hostname
      $e2.graph.entity.hostname = $u1.target.hostname
      $e2.graph.entity.hostname = $u2.principal.hostname

  match:
    $user over 5m

  condition:
      <condition_section>
}

<condition_section> の有効な例は次のとおりです。

  • $u1 and !$u2 and $e1 and $e2
    • すべての UDM イベントとエンティティが条件セクションに含まれる。
    • 少なくとも 1 つの UDM イベントが制限付きになっている。
  • $u1 and !$u2 and $e1 and !$e2
    • $e2 は制限なしです。これは、制限付きの $u1 に関連付けられているため許可されます。$e2$u1 に関連付けられていない場合、これは無効です。
  • #port > 50 and #ip = 0
    • 条件セクションに UDM イベントとエンティティが存在しません。ただし、既存のプレースホルダは、すべての UDM イベントとエンティティに対応しています。
    • $ip$u1$u2 の両方に割り当てられ、#ip = 0 は制限なし条件です。ただし、制限付き条件は制限なし条件よりも強力です。$port$u1 に割り当てられ、#port > 50 は制限付き条件であるため、$u1 は引き続き制限されます。

<condition_section> の無効な例を次に示します。

  • $u1 and $e1
    • [イベント] セクションに表示されるすべての UDM イベントとエンティティは、[条件] セクションに表示される必要があります(または、[条件] に表示されるプレースホルダが割り当てられている必要があります)。
  • $u1, $u2, $e1, $u2, #port > 50
    • 条件の区切り文字としてカンマは使用できません。
  • !$u1 and !$u2 and $e1 and $e2
    • 少なくとも 1 つの UDM イベントが制限されるという最初の要件に違反します。
  • ($u1 or #port < 50) and $u2 and $e1 and $e2
    • or キーワードは、制限なし条件ではサポートされていません。
  • ($u1 or $u2) and $e1 and $e2
    • or キーワードは、異なるイベント変数間ではサポートされません。
  • not $u1 and $u2 and $e1 and $e2
    • not キーワードは、イベントとプレースホルダの条件には使用できません。
  • #port < 50 and #ip = 0
    • 既存のプレースホルダは、すべての UDM イベントとエンティティに対応しています。ただし、すべての条件は無制限です。つまり、どの UDM イベントは制限されておらず、ルールのコンパイルは失敗します。

結果条件

出力変数の条件述語を一覧表示します。キーワード and または or と結合、またはキーワード not が前に付加されています。

結果変数のタイプに応じて、結果条件を異なる方法で指定します。

  • 整数: 演算子 =, >, >=, <, <=, != を使用して整数リテラルと比較します。次に例を示します。

    $risk_score > 10

  • float: 演算子 =, >, >=, <, <=, != を使用して float リテラルと比較します。次に例を示します。

    $risk_score <= 5.5

  • 文字列: = または != の文字列リテラルと比較します。次に例を示します。

    $severity = "HIGH"

  • 整数または配列のリスト: arrays.contains 関数を使用して条件を指定します。次に例を示します。

    arrays.contains($event_ids, "id_1234")

ルール分類

一致セクションのあるルールで結果条件を指定すると、そのルールがルール割り当てのマルチイベントルールとして分類されます。 単一イベントとマルチイベントの分類について詳しくは、単一イベントルールマルチイベントルールをご覧ください。

options セクションの構文

options セクションでは、ルールのオプションを指定できます。オプション セクションの指定方法の例を次に示します。

rule RuleOptionsExample {
  // Other rule sections

  options:
    allow_zero_values = true
}

構文 key = value を使用してオプションを指定できます。ここで、key は事前定義されたオプション名、value は以下のオプションで指定されているように、オプションの有効な値にする必要があります。

allow_zero_values

このオプションの有効な値は truefalse で、このオプションが有効かどうかが決まります。デフォルト値は false です。ルールで指定されていない場合、このオプションは無効になります。

この設定を有効にするには、ルールのオプション セクションに「allow_zero_values = true」を追加します。これにより、一致セクションでのゼロ値の処理で説明されているように、一致セクションで使用されているプレースホルダのゼロ値がルールで暗黙的に除外されなくなります。

Boolean Expressions

ブール値式はブール型の式です。

比較

条件として使用する単純なバイナリ式には、次の構文を使用します。

  • <EXPR> <OP> <EXPR>

式は、イベント フィールド、変数、リテラル、または関数の式のいずれかです。

例:

  • $e.source.hostname = "host1234"
  • $e.source.port < 1024
  • 1024 < $e.source.port
  • $e1.source.hostname != $e2.target.hostname
  • $e1.metadata.collected_timestamp.seconds > $e2.metadata.collected_timestamp.seconds
  • $port >= 25
  • $host = $e2.target.hostname
  • "google-test" = strings.concat($e.principal.hostname, "-test")
  • "email@google.org" = re.replace($e.network.email.from, "com", "org")

両側がリテラルの場合は、コンパイル エラーとみなされます。

関数

一部の関数式はブール値を返します。この値は、events セクションの個別の述語として使用できます。該当する関数は次のとおりです。

  • re.regex()
  • net.ip_in_range_cidr()

次に例を示します。

  • re.regex($e.principal.hostname, `.*\.google\.com`)
  • net.ip_in_range_cidr($e.principal.ip, "192.0.2.0/24")

リスト式の参照

イベント セクションでは、リファレンス リストを使用できます。詳細については、リファレンス リストをご覧ください。

論理式

論理 and と論理 or の演算子は、次の例に示すように events セクションで使用できます。

  • $e.metadata.event_type = "NETWORK_DNS" or $e.metadata.event_type = "NETWORK_DHCP"
  • ($e.metadata.event_type = "NETWORK_DNS" and $e.principal.ip = "192.0.2.12") or ($e.metadata.event_type = "NETWORK_DHCP" and $e.principal.mac = "AB:CD:01:10:EF:22")
  • not $e.metadata.event_type = "NETWORK_DNS"

デフォルトでは、優先度の高い順に notandor となります。

たとえば、演算子 orand が式で明示的に定義されている場合、「a or b and c」は「a or (b and c)」と評価されます。

events セクションで、演算子が明示的に定義されていない場合は、and 演算子を使用して述語が結合されます。

and 演算子が式に暗黙的に含まれている場合は、評価の順序が異なる場合があります。

たとえば、or が明示的に定義されている次の比較式について考えてみます。and 演算子は暗黙的に含まれています。

$e1.field = "bat"
or $e1.field = "baz"
$e2.field = "bar"

この例は次のように解釈されます。

($e1.field = "bat" or $e1.field = "baz")
and ($e2.field = "bar")

or は明示的に定義されているため、or を囲む述語が最初にグループ化されて評価されます。最後の述語 $e2.field = "bar" は、and を使用して暗黙的に結合されます。 その結果、評価の順序が変化します。

列挙型

列挙型では、演算子を使用できます。ルールに適用して、パフォーマンスを簡素化し、最適化できます(参照リストの代わりに演算子を使用します)。

次の例では、「USER_UNCATEGORIZED」と「USER_RESOURCE_DELETION」は 15000 と 15014 に対応しているため、ルールはリストされているすべてのイベントを検索します。

$e.metadata.event_type >= "USER_CATEGORIZED" and $e.metadata.event_type <= "USER_RESOURCE_DELETION"

イベントのリスト

  • USER_RESOURCE_DELETION
  • USER_RESOURCE_UPDATE_CONTENT
  • USER_RESOURCE_UPDATE_PERMISSIONS
  • USER_STATS
  • USER_UNCATEGORIZED

Nocase の修飾子

文字列値または正規表現の比較式がある場合は、式の最後に nocase を追加することで大文字と小文字の区別を無視できます。

  • $e.principal.hostname != "http-server" nocase
  • $e1.principal.hostname = $e2.target.hostname nocase
  • $e.principal.hostname = /dns-server-[0-9]+/ nocase
  • re.regex($e.target.hostname, `client-[0-9]+`) nocase

フィールドの型が列挙値の場合、これは使用できません。次の例は無効であり、コンパイル エラーになります。

  • $e.metadata.event_type = "NETWORK_DNS" nocase
  • $e.network.ip_protocol = "TCP" nocase

繰り返しフィールド

統合データモデル(UDM)では、一部のフィールドが繰り返しとしてラベル付けされ、値やその他の種類のメッセージのリストであることを示します。

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

繰り返しフィールドを操作するブール式には次の 2 種類があります。

  1. 変更
  2. 変更なし

次のイベントについて考えてみましょう。

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 修飾子を使用する目的と方法について説明します。

任意

繰り返しフィールドの任意の要素が条件を満たす場合は、イベント全体が条件を満たしています。

  • event_originalany $e.principal.ip = "192.0.2.1" を満たします。
  • event_originalany $e.repeated_field.field_a = "9.9.9.9 に失敗します。
すべて

繰り返しフィールドのすべての要素が条件を満たす場合は、イベント全体が条件を満たしています。

  • 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"

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

次のルールは、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 任意の $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_1192.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 に設定されている)はカウントされません。
  • 配列インデックスを any または all と組み合わせることはできません。たとえば、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 が配列インデックスを使用して一致を生成していたため、予期しない動作が発生する可能性があります。

コメント

C の場合と同様、コメントは 2 つのスラッシュ文字(// comment)により指定します。コメントが複数行にわたる場合は、スラッシュ アスタリスク(/* comment */)を使用してコメントアウトします。

リテラル

負でない整数と浮動小数点数、文字列、ブール値、正規表現のリテラルがサポートされています。

文字列リテラルと正規表現リテラル

YARA-L 2.0 で文字列を囲むには、次のいずれかの引用符を使用します。ただし、引用符で囲まれたテキストは、使用する引用符に応じて解釈が異なります。

  1. 二重引用符(")- 通常の文字列に使用します。エスケープ文字を含める必要があります。
    たとえば、「hello\tworld」の場合、\t はタブとして解釈されます。

  2. バッククォート(`)- すべての文字を文字どおりに解釈するために使用します。
    たとえば、「hello\tworld」の場合、\t はタブとして解釈されません。

正規表現には 2 つのオプションがあります。

re.regex() 関数を使用せずに正規表現を直接使用する場合は、正規表現リテラルに /regex/ を使用します。

re.regex() 関数を使用する場合は、文字列リテラルを正規表現リテラルとして使用することもできます。二重引用符文字列リテラルの場合は、バックスラッシュ文字でバックスラッシュ文字をエスケープする必要があります。これは、ややスマートではない処理の仕方です。

たとえば、次の 2 つの式は等価です。

  • re.regex($e.network.email.from, `.*altostrat\.com`)
  • re.regex($e.network.email.from, ".*altostrat\\.com")
  • $e.network.email.from = /.*altostrat\.com/

読みやすくするために、正規表現の文字列にはバッククォート文字を使用することをおすすめします。

演算子

YARA-L では次の演算子を使用できます。

オペレーター 説明
= 等しい / 宣言
!= 等しくない
< 次より小さい
<= 以下
> 次より大きい
>= 以上

変数

YARA-L 2.0 では、すべての変数が $<variable name> として表されます。

次のタイプの変数を定義できます。

  • イベント変数 — イベントのグループを正規化された形式(UDM)またはエンティティ イベントで表します。events セクションで、イベント変数の条件を指定します。名前、イベントソース、イベント フィールドを使用して、イベント変数を指定します。許可されるソースは、udm(正規化されたイベントの場合)と graph(エンティティ イベントの場合)です。ソースを省略すると、udm がデフォルトのソースとして設定されます。イベント フィールドは、.<field name> のチェーンで表されます(例: $e.field1.field2)。イベント フィールド チェーンは常に最上位のソース(UDM またはエンティティ)から始まります。

  • 一致変数 - match セクションで宣言します。一致変数は、一意の変数セットのセット(および期間)ごとに 1 行が返されるため、クエリのグループ フィールドになります。ルールが一致を見つけると、一致変数の値が返されます。各一致変数が表す内容を events セクションで指定します。

  • プレースホルダ変数 - events セクションで宣言および定義します。プレースホルダ変数は、match 変数に似ています。ただし、condition セクションでプレースホルダ変数を使用して、一致条件を指定できます。

推移結合条件を使用して、イベント フィールド間の関係を宣言するために、一致変数とプレースホルダ変数を使用します(詳細については、events セクションの構文をご覧ください)。

Keywords

YARA-L 2.0 のキーワードでは大文字と小文字が区別されません。たとえば、andAND は同じです。変数名はキーワードと競合しないようにしてください。たとえば、$AND$outcome は無効です。

検出エンジンルールのキーワードは次のとおりです。rulemetamatchovereventsconditionoutcomeoptionsandornotnocaseinregexcidrbeforeafterallanyifmaxminsumarrayarray_distinctcountcount_distinctis null

マップ

YARA-L では、構造体とラベルのマップへのアクセスがサポートされています。

構造体とラベル

一部の UDM フィールドは、構造体ラベルデータ型を使用します。

構造体とラベルの両方で特定の Key-Value ペアを検索するには、標準のマップ構文を使用します。

// A Struct field.
$e.udm.additional.fields["pod_name"] = "kube-scheduler"
// A Label field.
$e.metadata.ingestion_labels["MetadataKeyDeletion"] = "startup-script"

マップアクセスは常に文字列を返します。

サポート対象のケース

イベントと結果セクション
// Using a Struct field in the events section
events:
  $e.udm.additional.fields["pod_name"] = "kube-scheduler"

// Using a Label field in the outcome section
outcome:
  $value = array_distinct($e.metadata.ingestion_labels["MetadataKeyDeletion"])
マップ値のプレースホルダへの割り当て
$placeholder = $u1.metadata.ingestion_labels["MetadataKeyDeletion"]
結合条件でのマップ フィールドの使用
// using a Struct field in a join condition between two udm events $u1 and $u2
$u1.metadata.event_type = $u2.udm.additional.fields["pod_name"]

サポート対象外のケース

次の場合、マップはサポートされません。

キーワード any または all とマップの組み合わせ

たとえば、「all $e.udm.additional.fields["pod_name"] = "kube-scheduler"」はサポートされていません。

その他の型の値

マップ構文は文字列値のみを返すことができます。Struct データ型の場合、マップ構文は値が文字列であるキーにのみアクセスできます。値が整数などの他のプリミティブ型であるキーにアクセスすることはできません。

重複値の処理

マップアクセスは常に単一の値を返します。マップアクセスが複数の値を参照できるという一般的ではないエッジケースでは、マップアクセスが決定論的に最初の値を返します。

これは、次のいずれかの場合に発生します。

  • ラベルに重複するキーがあります。

    ラベル構造はマップを表しますが、キーの一意性は強制されません。慣例により、マップには一意のキーが必要であるため、Chronicle では、ラベルに重複するキーを入力することはおすすめしません。

    次のデータの例に対してルールテキスト $e.metadata.ingestion_labels["dupe-key"] を実行すると、最初の有効な値である val1 が返されます。

    // Disrecommended usage of label with a duplicate key:
    event {
      metadata{
        ingestion_labels{
          key: "dupe-key"
          value: "val1" // This is the first possible value for "dupe-key"
        }
        ingestion_labels{
          key: "dupe-key"
          value: "val2"
        }
      }
    }
    
  • ラベルには祖先繰り返しフィールドがあります。

    繰り返しフィールドには、子フィールドとしてラベルが含まれる場合があります。最上位の繰り返しフィールドの 2 つの異なるエントリに、同じキーを持つラベルが含まれている場合があります。ルールテキスト $e.security_result.rule_labels["key"] は、次のデータ例を対象とすると、最初の可能な値 val3 を返します。

    event {
      // security_result is a repeated field.
      security_result {
        threat_name: "threat1"
        rule_labels {
          key: "key"
          value: "val3" // This is the first possible value for "key"
        }
      }
      security_result {
        threat_name: "threat2"
        rule_labels {
          key: "key"
          value: "val4"
        }
      }
    }
    

関数

このセクションでは、Chronicle が Detection Engine でサポートする YARA-L 2.0 関数について説明します。

これらの関数は、ルール内の次の領域で使用できます。

arrays.length

arrays.length(repeatedField)

説明

繰り返しフィールド要素の数を返します。

パラメータのデータ型

LIST

戻り値の型

NUMBER

コードサンプル

例 1

繰り返しフィールド要素の数を返します。

arrays.length($e.principal.ip) = 2
例 2

複数の繰り返しフィールドがパスに沿っている場合、繰り返しフィールド要素の総数を返します。

arrays.length($e.intermediary.ip) = 3

math.abs

math.abs(numericExpression)

説明

整数または浮動小数点式の絶対値を返します。

パラメータのデータ型

NUMBER

戻り値の型

NUMBER

コードサンプル

例 1

この例では、イベントが指定された時刻の前か後かに関係なく、指定された時刻(Unix エポックからの秒数)から 5 分以上経過した場合に True を返します。math.abs の呼び出しは、複数の変数またはプレースホルダに依存することはできません。たとえば、次の例の 1643687343 のハードコードされた時刻値を $e2.metadata.event_timestamp.seconds に置き換えることはできません。

300 < math.abs($e1.metadata.event_timestamp.seconds - 1643687343)

指標

指標関数は、大量の履歴データを集計できます。これは、結果セクションで metrics.functionName() を使用してルールで使用できます。

詳細については、YARA-L Metrics をご覧ください。

net.ip_in_range_cidr

net.ip_in_range_cidr(ipAddress, subnetworkRange)

説明

指定された IP アドレスが指定されたサブネットワーク内にある場合に true を返します。

YARA-L を使用すると、net.ip_in_range_cidr() ステートメントを使用するサブネットワーク内のすべての IP アドレスにわたり UDM イベントを検索できます。IPv4 と IPv6 の両方がサポートされています。

IP アドレスの範囲を検索するには、IP UDM フィールドと CIDR 範囲を指定します。YARA-L は、単一および繰り返しの IP アドレス フィールドの両方を処理できます。

IP アドレスの範囲を検索するには、ip UDM フィールドとクラスレス ドメイン間ルーティング(CIDR)範囲を指定します。YARA-L は、単一および繰り返しの IP アドレス フィールドの両方を処理できます。

パラメータのデータ型

STRING, STRING

戻り値の型

BOOL

コードサンプル

例 1

IPv4 の例:

net.ip_in_range_cidr($e.principal.ip, "192.0.2.0/24")
例 2

IPv6 の例:

net.ip_in_range_cidr($e.network.dhcp.yiaddr, "2001:db8::/32")

net.ip_in_range_cidr() ステートメントを使用したルールの例については、サンプルのルールとして IP アドレスの範囲内の単一イベントをご覧ください。

re.regex

YARA-L 2.0 では、次のいずれかの構文を使用して正規表現の一致を定義できます。

  • YARA 構文の使用 - イベントに関連します。この構文の一般的な表現は次のとおりです。none $e.field = /regex/
  • YARA-L 構文の使用 - 次のパラメータを受け取る関数として使用します。
    • 正規表現が適用されるフィールド。
    • 文字列として指定された正規表現。文字列の後に nocase 修飾子を使用すると、検索で大文字小文字の区別が無視されるよう指定できます。この構文の一般的な表現は次のとおりです。none re.regex($e.field, `regex`)

説明

指定した正規表現に一致する部分文字列が文字列に含まれている場合、この関数は true を返します。正規表現の先頭または末尾に .* を追加する必要はありません。

メモ
  • 文字列と完全に一致する場合、またはプレフィックスまたはサフィックスのみと一致する場合は、正規表現に ^(開始)と $(終了)のアンカー文字を含めます。たとえば、/^full$/"full" と正確に一致しますが、/full/"fullest""lawfull""joyfully" と一致します。
  • UDM フィールドに改行文字が含まれている場合、regexp は UDM フィールドの最初の行にのみ一致します。完全な UDM フィールド マッチングを適用するには、(?s) を正規表現に追加します。たとえば、/.*allUDM.*//(?s).*allUDM.*/ に置き換えます。

パラメータのデータ型

STRING, STRING

パラメータ式のタイプ

ANY, ANY

戻り値の型

BOOL

コードサンプル

例 1
// Equivalent to $e.principal.hostname = /google/
re.regex($e.principal.hostname, "google")

re.capture

re.capture(stringText, regex)

説明

引数で指定された正規表現パターンを使用して、文字列からデータをキャプチャ(抽出)します。

この関数は次の 2 つの引数を取ります。

  • stringText: 検索する元の文字列。
  • regex: 検索するパターンを示す正規表現。

正規表現では、0 または 1 つのキャプチャ グループをかっこで囲むことができます。正規表現にキャプチャ グループがない場合、この関数は最初に一致した部分文字列を返します。正規表現に 1 つのキャプチャ グループが含まれている場合、キャプチャ グループの最初の一致部分文字列が返されます。2 つ以上のキャプチャ グループを定義すると、コンパイラ エラーが返されます。

パラメータのデータ型

STRING, STRING

戻り値の型

STRING

コードサンプル

例 1

この例では、$e.principal.hostname に「aaa1bbaa2」が含まれている場合、この関数によって最初のインスタンスが返されるため、次の式になります。この例にはキャプチャ グループはありません。

"aaa1" = re.capture($e.principal.hostname, "a+[1-9]")
例 2

この例は、メール内の @ 記号より後ろのすべての部分を取得します。$e.network.email.from フィールドが test@google.com の場合、この例では google.com を返します。次の例には、キャプチャ グループが 1 つ含まれています。

"google.com" = re.capture($e.network.email.from , "@(.*)")
例 3

正規表現がテキスト内の部分文字列と一致しない場合、この関数は空の文字列を返します。空の文字列を除外することで、一致しないイベントを省略できます。これは、不等式で re.capture() を使用している場合に特に重要です。

// Exclude the empty string to omit events where no match occurs.
"" != re.capture($e.network.email.from , "@(.*)")

// Exclude a specific string with an inequality.
"google.com" != re.capture($e.network.email.from , "@(.*)")

re.replace

re.replace(stringText, replaceRegex, replacementText)

説明

正規表現の置き換えを行います。

この関数は次の 3 つの引数を取ります。

  • stringText: 元の文字列。
  • replaceRegex: 検索するパターンを示す正規表現。
  • replacementText: 各一致に挿入するテキスト。

元の文字列 stringText から派生した新しい文字列を返します。ここでは、replaceRegex のパターンに一致するすべての部分文字列が、replacementText に置き換えられます。replacementText 内でバックスラッシュでエスケープされた数字(\1\9)を使用して、対応する括弧で囲まれたグループと一致するテキストを replaceRegex パターン内に挿入できます。一致するテキスト全体を参照するには、\0 を使用します。

この関数は、重複しない一致を置き換えるもので、最初に見つかったものを優先的に置き換えます。たとえば、re.replace("banana", "ana", "111") は文字列「b111na」を返します。

パラメータのデータ型

STRING, STRING, STRING

戻り値の型

STRING

コードサンプル

例 1

この例では、メール内の @ 記号の後のすべての部分をキャプチャし、comorg に置き換えて結果を返します。ネストされた関数が使用されることに注意してください。

"email@google.org" = re.replace($e.network.email.from, "com", "org")
例 2

この例では、replacementText 引数でバックスラッシュでエスケープされた数字を使用して、replaceRegex パターンとの一致を参照します。

"test1.com.google" = re.replace(
                       $e.principal.hostname, // holds "test1.test2.google.com"
                       "test2\.([a-z]*)\.([a-z]*)",
                       "\\2.\\1"  // \\1 holds "google", \\2 holds "com"
                     )
例 3

空の文字列と re.replace() を扱う際は、次の点に注意してください。

replaceRegex として空の文字列を使用。

// In the function call below, if $e.principal.hostname contains "name",
// the result is: 1n1a1m1e1, because an empty string is found next to
// every character in `stringText`.
re.replace($e.principal.hostname, "", "1")

空の文字列を置き換えるには、"^$"replaceRegex として使用します。

// In the function call below, if $e.principal.hostname contains the empty
// string, "", the result is: "none".
re.replace($e.principal.hostname, "^$", "none")

strings.base64_decode

strings.base64_decode(encodedString)

説明

エンコードされた文字列の Base64 デコードされたバージョンを含む文字列を返します。

この関数は、Base64 でエンコードされた 1 つの文字列を引数として受け取ります。encodedString が Base64 でエンコードされた有効な文字列でない場合、この関数は encodedString を変更せずに返します。

パラメータのデータ型

STRING

戻り値の型

STRING

コードサンプル

例 1
"test" = strings.base64_decode($e.principal.domain.name)

strings.coalesce

strings.coalesce(a, b, c, ...)

説明

この関数は、引数を無制限に取り、空の文字列と評価されない最初の式の値を返します(例: 「ゼロ以外の値」)。すべての引数が空の文字列と評価された場合、関数呼び出しは空の文字列を返します。

引数には、リテラル、イベント フィールド、関数呼び出しを使用できます。すべての引数は STRING 型でなければなりません。引数がイベント フィールドの場合、属性は同じイベントからのものである必要があります。

パラメータのデータ型

STRING

戻り値の型

STRING

コードサンプル

例 1

次の例には、引数として文字列変数が含まれています。(1)$e.network.email.fromsuspicious@gmail.com であるか、(2)$e.network.email.from が空かつ$e.network.email.tosuspicious@gmail.com の場合、条件は true と評価されます。

"suspicious@gmail.com" = strings.coalesce($e.network.email.from, $e.network.email.to)
例 2

次の例では、3 個を超える引数を使用して coalesce 関数を呼び出します。この条件は、イベント $e の最初の null 以外の IP アドレスを、リファレンス リスト ip_watchlist の値と比較します。この呼び出しで引数が結合される順序は、ルール条件で引数が列挙されている順序と同じです。

  1. $e.principal.ip が最初に評価されます。
  2. $e.src.ip が評価されます。
  3. $e.target.ip が評価されます。
  4. 最後に、以前の ip フィールドが設定されていない場合、文字列「No IP」がデフォルト値として返されます。
strings.coalesce($e.principal.ip, $e.src.ip, $e.target.ip, "No IP") in %ip_watchlist
例 3

次の例では、イベント $e1 とイベント $e2principal.hostname を結合しようとしています。引数が異なるイベント変数であるため、コンパイラ エラーが返されます。

// returns a compiler error
"test" = strings.coalesce($e1.principal.hostname, $e2.principal.hostname)

strings.concat

strings.concat(a, b, c, ...)

説明

無制限の数のアイテムを連結した値を返します。各アイテムは、文字列、整数、または浮動小数点数です。

引数がイベント フィールドの場合、属性は同じイベントからのものである必要があります。

パラメータのデータ型

STRINGFLOATINT

戻り値の型

STRING

コードサンプル

例 1

次の例には、引数として文字列変数と整数変数が含まれています。principal.hostnameprincipal.port はどちらも、同じイベント $e からのもので、文字列を返すために連結されます。

"google:80" = strings.concat($e.principal.hostname, ":", $e.principal.port)
例 2

次の例には、引数として文字列変数と文字列リテラルが含まれています。

"google-test" = strings.concat($e.principal.hostname, "-test") // Matches the event when $e.principal.hostname = "google"
例 3

次の例には、引数として文字列変数と浮動リテラルが含まれています。文字列として表現される場合、整数である浮動小数点は小数点のない形式になります(たとえば、1.0 は「1」と表されます)。また、10 進 16 桁を超える浮動小数点は小数点以下 16 桁に切り捨てられます。

"google2.5" = strings.concat($e.principal.hostname, 2.5)
例 4

次の例には、引数として文字列変数、文字列リテラル、整数変数、浮動小数点リテラルが含まれています。すべての変数は、同じイベント $e からのもので、リテラルに連結されて文字列を返します。

"google-test802.5" = strings.concat($e.principal.hostname, "-test", $e.principal.port, 2.5)
例 5

次の例では、イベント $e1 の principal.port とイベント $e2principal.hostname を連結しようとしています。引数が異なるイベント変数であるため、コンパイラ エラーが返されます。

// Will not compile
"test" = strings.concat($e1.principal.port, $e2.principal.hostname)

strings.to_lower

strings.to_lower(stringText)

説明

この関数は入力文字列を受け取り、すべての文字を小文字に変更してから文字列を返します。

パラメータのデータ型

STRING

戻り値の型

STRING

コードサンプル

例 1

次の例では、true が返されます。

"test@google.com" = strings.to_lower($e.network.email.to)

strings.to_upper

strings.to_upper(stringText)

説明

この関数は入力文字列を受け取り、すべての文字を大文字に変更してから文字列を返します。

パラメータのデータ型

STRING

戻り値の型

STRING

コードサンプル

例 1

次の例では、true が返されます。

"TEST@GOOGLE.COM" = strings.to_upper($e.network.email.to)

timestamp.current_seconds

timestamp.current_seconds()

説明

現在の時刻を Unix 秒数で表す整数を返します。これは検出のタイムスタンプとほぼ同じで、ルールが実行されるタイミングに基づきます。

パラメータのデータ型

NONE

戻り値の型

INT

コードサンプル

例 1

次の例は、証明書が 24 時間を超えて期限切れになった場合に true を返します。現在の Unix 秒を減算して、不等価演算子を使用して比較することで、時間差を計算します。

86400 < timestamp.current_seconds() - $e.network.tls.certificate.not_after

timestamp.get_date

timestamp.get_date(unix_seconds [, time_zone])

説明

この関数は、タイムスタンプが存在する日付を表す YYYY-MM-DD 形式の文字列を返します。

  • unix_seconds は、$e.metadata.event_timestamp.seconds などの Unix エポックからの経過秒数を表す整数か、その値を含むプレースホルダです。
  • time_zone は省略可能で、time_zone を表す文字列です。省略した場合、デフォルトは「GMT」です。文字列リテラルを使用してタイムゾーンを指定できます。次のオプションがあります。
    • TZ データベース名(「America/Los_Angeles」など)。詳しくは、このページの「TZ データベース名」列をご覧ください。
    • (+|-)H[H][:M[M]] 形式の UTC からのタイムゾーン オフセット(例: 「-08:00」)。

以下に、有効な time_zone 指定子の例を示します。これらは、時間抽出関数に 2 番目の引数として渡すことができます。

"America/Los_Angeles", or "-08:00". ("PST" is not supported)
"America/New_York", or "-05:00". ("EST" is not supported)
"Europe/London"
"UTC"
"GMT"

パラメータのデータ型

INTSTRING

戻り値の型

STRING

コードサンプル

例 1

この例では、time_zone 引数が省略されているため、デフォルトの「GMT」になります。

$ts = $e.metadata.collected_timestamp.seconds

timestamp.get_date($ts) = "2024-02-19"
例 2

この例では、文字列リテラルを使用して time_zone を定義しています。

$ts = $e.metadata.collected_timestamp.seconds

timestamp.get_date($ts, "America/Los_Angeles") = "2024-02-20"

timestamp.get_minute

timestamp.get_minute(unix_seconds [, time_zone])

説明

この関数は、分を表す [0, 59] の範囲の整数を返します。

  • unix_seconds は、$e.metadata.event_timestamp.seconds などの Unix エポックからの経過秒数を表す整数か、その値を含むプレースホルダです。
  • time_zone は省略可能で、タイムゾーンを表す文字列です。省略した場合、デフォルトは「GMT」です。文字列リテラルを使用してタイムゾーンを指定できます。次のオプションがあります。
    • TZ データベース名(「America/Los_Angeles」など)。詳しくは、このページの「TZ データベース名」列をご覧ください。
    • (+|-)H[H][:M[M]] 形式の UTC からのタイムゾーン オフセット(例: 「-08:00」)。

有効な time_zone 指定子の例を次に示します。これは、時間抽出関数に 2 番目の引数として渡すことができます。

"America/Los_Angeles", or "-08:00". ("PST" is not supported)
"America/New_York", or "-05:00". ("EST" is not supported)
"Europe/London"
"UTC"
"GMT"

パラメータのデータ型

INTSTRING

戻り値の型

INT

コードサンプル

例 1

この例では、time_zone 引数が省略されているため、デフォルトの「GMT」になります。

$ts = $e.metadata.collected_timestamp.seconds

timestamp.get_hour($ts) = 15
例 2

この例では、文字列リテラルを使用して time_zone を定義しています。

$ts = $e.metadata.collected_timestamp.seconds

timestamp.get_hour($ts, "America/Los_Angeles") = 15

timestamp.get_hour

timestamp.get_hour(unix_seconds [, time_zone])

説明

この関数は、時間を表す [0, 23] の範囲の整数を返します。

  • unix_seconds は、$e.metadata.event_timestamp.seconds などの Unix エポックからの経過秒数を表す整数か、その値を含むプレースホルダです。
  • time_zone は省略可能で、タイムゾーンを表す文字列です。省略した場合、デフォルトは「GMT」です。文字列リテラルを使用してタイムゾーンを指定できます。次のオプションがあります。
    • TZ データベース名(「America/Los_Angeles」など)。詳しくは、このページの「TZ データベース名」列をご覧ください。
    • (+|-)H[H][:M[M]] 形式の UTC からのタイムゾーン オフセット(例: 「-08:00」)。

有効な time_zone 指定子の例を次に示します。これは、時間抽出関数に 2 番目の引数として渡すことができます。

"America/Los_Angeles", or "-08:00". ("PST" is not supported)
"America/New_York", or "-05:00". ("EST" is not supported)
"Europe/London"
"UTC"
"GMT"

パラメータのデータ型

INTSTRING

戻り値の型

INT

コードサンプル

例 1

この例では、time_zone 引数が省略されているため、デフォルトの「GMT」になります。

$ts = $e.metadata.collected_timestamp.seconds

timestamp.get_hour($ts) = 15
例 2

この例では、文字列リテラルを使用して time_zone を定義しています。

$ts = $e.metadata.collected_timestamp.seconds

timestamp.get_hour($ts, "America/Los_Angeles") = 15

timestamp.get_day_of_week

timestamp.get_day_of_week(unix_seconds [, time_zone])

説明

この関数は、日曜日から始まる曜日を表す [1, 7] の範囲の整数を返します。たとえば、1 = 日曜日、2 = 月曜日です。

  • unix_seconds は、$e.metadata.event_timestamp.seconds などの Unix エポックからの経過秒数を表す整数か、その値を含むプレースホルダです。
  • time_zone は省略可能で、time_zone を表す文字列です。省略した場合、デフォルトは「GMT」です。文字列リテラルを使用してタイムゾーンを指定できます。次のオプションがあります。
    • TZ データベース名(「America/Los_Angeles」など)。詳しくは、このページの「TZ データベース名」列をご覧ください。
    • (+|-)H[H][:M[M]] 形式の UTC からのタイムゾーン オフセット(例: 「-08:00」)。

以下に、有効な time_zone 指定子の例を示します。これらは、時間抽出関数に 2 番目の引数として渡すことができます。

"America/Los_Angeles", or "-08:00". ("PST" is not supported)
"America/New_York", or "-05:00". ("EST" is not supported)
"Europe/London"
"UTC"
"GMT"

パラメータのデータ型

INTSTRING

戻り値の型

INT

コードサンプル

例 1

この例では、time_zone 引数が省略されているため、デフォルトの「GMT」になります。

$ts = $e.metadata.collected_timestamp.seconds

timestamp.get_day_of_week($ts) = 6
例 2

この例では、文字列リテラルを使用して time_zone を定義しています。

$ts = $e.metadata.collected_timestamp.seconds

timestamp.get_day_of_week($ts, "America/Los_Angeles") = 6

timestamp.get_week

timestamp.get_week(unix_seconds [, time_zone])

説明

この関数は、1 年の中の週を表す [0, 53] の範囲の整数を返します。週は日曜日から始まります。年の最初の日曜日より前の日付は 0 週目です。

  • unix_seconds は、$e.metadata.event_timestamp.seconds などの Unix エポックからの経過秒数を表す整数か、その値を含むプレースホルダです。
  • time_zone は省略可能で、タイムゾーンを表す文字列です。省略した場合、デフォルトは「GMT」です。文字列リテラルを使用してタイムゾーンを指定できます。次のオプションがあります。
    • TZ データベース名(「America/Los_Angeles」など)。詳しくは、このページの「TZ データベース名」列をご覧ください。
    • (+|-)H[H][:M[M]] 形式の UTC からのタイムゾーン オフセット(例: 「-08:00」)。

有効な time_zone 指定子の例を次に示します。これは、時間抽出関数に 2 番目の引数として渡すことができます。

"America/Los_Angeles", or "-08:00". ("PST" is not supported)
"America/New_York", or "-05:00". ("EST" is not supported)
"Europe/London"
"UTC"
"GMT"

パラメータのデータ型

INTSTRING

戻り値の型

INT

コードサンプル

例 1

この例では、time_zone 引数が省略されているため、デフォルトの「GMT」になります。

$ts = $e.metadata.collected_timestamp.seconds

timestamp.get_week($ts) = 0
例 2

この例では、文字列リテラルを使用して time_zone を定義しています。

$ts = $e.metadata.collected_timestamp.seconds

timestamp.get_week($ts, "America/Los_Angeles") = 0

関数からプレースホルダの割り当て

関数呼び出しの結果を events セクションのプレースホルダに割り当てることができます。例:

$placeholder = strings.concat($e.principal.hostname, "my-string").

その後、matchconditionoutcome セクションでプレースホルダ変数を使用できます。 ただし、関数からプレースホルダの割り当てには 2 つの制限があります。

  1. プレースホルダの割り当てに対する機能内のプレースホルダはすべて、イベント フィールドを含む式に割り当てる必要があります。たとえば、次の例は有効です。

    $ph1 = $e.principal.hostname
    $ph2 = $e.src.hostname
    
    // Both $ph1 and $ph2 have been assigned to an expression containing an event field.
    $ph1 = strings.concat($ph2, ".com")
    
    $ph1 = $e.network.email.from
    $ph2 = strings.concat($e.principal.hostname, "@gmail.com")
    
    // Both $ph1 and $ph2 have been assigned to an expression containing an event field.
    $ph1 = strings.to_lower($ph2)
    

    ただし、次の例は無効です。

    $ph1 = strings.concat($e.principal.hostname, "foo")
    $ph2 = strings.concat($ph1, "bar") // $ph2 has NOT been assigned to an expression containing an event field.
    
  2. 関数呼び出しは、いずれか 1 つのイベントに依存する必要があります。ただし、同じイベントからの複数のフィールドが関数呼び出し引数で使用される場合があります。 たとえば、以下は有効です。

    $ph = strings.concat($event.principal.hostname, "string2")

    $ph = strings.concat($event.principal.hostname, $event.src.hostname)

    ただし、以下は無効です。

    $ph = strings.concat("string1", "string2")

    $ph = strings.concat($event.principal.hostname, $anotherEvent.src.hostname)

リファレンス リストの構文

リファレンス リストの動作とリファレンス リストの構文の詳細については、リファレンス リストのページをご覧ください。

リファレンス リストは、events または outcome セクションで使用できます。ルールで、さまざまな種類のリファレンス リストを使用する構文は次のとおりです。

// STRING reference list
$e.principal.hostname in %string_reference_list

// REGEX reference list
$e.principal.hostname in regex %regex_reference_list

// CIDR reference list
$e.principal.ip in cidr %cidr_reference_list

次の例に示すように、リファレンスリストで not 演算子と nocase 演算子を使用することもできます。

// Exclude events whose hostnames match substrings in my_regex_list.
not $e.principal.hostname in regex %my_regex_list

// Event hostnames must match at least 1 string in my_string_list (case insensitive).
$e.principal.hostname in %my_string_list nocase

nocase 演算子は STRING リストおよび REGEX リストと互換性があります。

パフォーマンス上の理由から、Detection Engine では、リファレンス リストの使用が制限されています。

  • 特別な演算子の有無にかかわらず、ルール内の in ステートメントの最大数: 7
  • regex 演算子を使用した in ステートメントの最大数: 4
  • cidr 演算子を使用した in ステートメントの最大数: 2

型チェック

インターフェース内でルールを作成する際に、Chronicle は YARA-L 構文に対して型チェックを行います。表示される型チェックエラーは、ルールが意図したとおりに機能するように修正する際に活用できます。

無効な述語の例を以下に示します。

// $e.target.port is of type integer which cannot be compared to a string.
$e.target.port = "80"

// "LOGIN" is not a valid event_type enum value.
$e.metadata.event_type = "LOGIN"

検出イベントのサンプリング

マルチイベント ルールの検出には、検出の原因となったイベントに関するコンテキストを提供するイベント サンプルが含まれています。ルールで定義されているイベント変数ごとに、イベントサンプルの上限は 10 個です。たとえば、ルールで 2 つのイベント変数を定義している場合、各検出は最大 20 個のイベント サンプルを持つことができます。この制限は、各イベント変数に個別に適用されます。この検出で、1 つのイベント変数に 2 つの該当するイベントがあり、もう 1 つのイベント変数に 15 個の該当するイベントがある場合、結果の検出には 12 個のイベント サンプル(2 + 10)が含まれます。

上限を超えるイベント サンプルは検出から除外されます。

検出の原因となったイベントの詳細情報が必要な場合は、結果セクションの集計を使用して、検出の詳細情報を出力できます。

UI で検出を表示している場合は、検出のすべてのイベント サンプルをダウンロードできます。詳しくは、イベントをダウンロードするをご覧ください。