式、演算子、その他の構文
このドキュメントでは、式を使用して YARA-L ルールとクエリを作成する際に役立つ情報を提供します。
ブール式
ブール値式はブール型の式です。これには、比較式、関数式、参照リスト式、データテーブル式が含まれます。YARA-L ルールまたはクエリの events セクションと outcome セクションでブール式を使用できます。
比較式
比較式は、2 つの式に比較演算子を適用する式です。式には、イベント フィールド、変数、リテラル、または関数の式を使用できます。
例: 比較式
$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")
参照リストまたはデータテーブル
リファレンス リストまたはデータテーブルは、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
例: データテーブルの構文
// STRING data table $e.target.hostname in %data_table_name.column_name // REGEX data table $e.target.hostname in regex %regex_table_name.column_name // CIDR data table $e.principal.ip in cidr %cidr_table_name.column_name
例: リファレンス リストの構文で 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 リストと互換性があります。
パフォーマンス上の理由から、リファレンス リストとデータテーブルの使用には次の制限があります。
- クエリ内の
inステートメントの最大数(特別な演算子の有無を問わず): 7 regex演算子を含むinステートメントの最大数: 4cidr演算子を含むinステートメントの最大数: 2
論理式
論理演算子 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"
デフォルトでは、優先度の高い順に not、and、or となります。たとえば、演算子 or と and が式で明示的に定義されている場合、「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 が明示的に定義されているため、周囲の述語がグループ化され、最初に評価されます。最後の述語 $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"
Nocase 修飾子
文字列値または正規表現の比較式で大文字と小文字の区別を無視するには、次の例に示すように、式の最後に 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
フィールドの型が列挙値の場合、nocase 調整比は使用できません。次の例は無効であり、コンパイル エラーになります。
$e.metadata.event_type = "NETWORK_DNS" nocase
$e.network.ip_protocol = "TCP" nocase
コメント
クエリでコメントを使用して、詳細情報を指定できます。スラッシュ文字はコメントを示すために使用します。
- 単一行コメントには、2 つのスラッシュ文字(
// comment)を使用します。 - 複数行のコメントの場合は、スラッシュ文字とアスタリスク文字(
/* comment */)を使用します。
リテラル
YARA-L は、負でない整数と浮動小数点数、文字列、ブール値、正規表現のリテラルをサポートしています。リテラルは、クエリ条件で使用される固定値です。YARA-L では、パターン マッチングに正規表現(スラッシュで囲まれたもの)、ロジックにブール値(true/false)など、リテラルに似た他の構造も使用します。
文字列リテラル
文字列リテラルは、二重引用符(")またはバッククォート(`)で囲まれた文字のシーケンスです。文字列の解釈は、使用する引用符の種類によって異なります。
- 二重引用符("hello\tworld"): 通常の文字列に使用します。エスケープ文字を含める必要があります。\t はタブとして解釈されます。
- バッククォート(`hello\tworld`): すべての文字を文字どおりに解釈する場合に使用します。この場合、\t はタブとして解釈されません。
正規表現リテラル
正規表現リテラルには、次の 2 つのオプションがあります。
re.regex()関数を使用せずに正規表現を直接使用する場合は、正規表現リテラルに/regex/を使用します。文字列リテラルを正規表現リテラルとして使用する場合は、
re.regex()関数を使用します。二重引用符文字列リテラルの場合は、バックスラッシュ文字でバックスラッシュ文字をエスケープする必要があります。これは、ややスマートではない処理の仕方です。
次の例は、同等の正規表現を示しています。
re.regex($e.network.email.from, `.*altostrat\.com`)
re.regex($e.network.email.from, ".*altostrat\\.com")
$e.network.email.from = /.*altostrat\.com/
読みやすくするために、正規表現の文字列にはバッククォート文字を使用することをおすすめします。
演算子
| オペレーター | 説明 |
| = | 等しい / 宣言 |
| != | 等しくない |
| < | 未満 |
| <= | 以下 |
| > | 次より大きい |
| >= | 以上 |
変数
YARA-L では、すべての変数で $<variable name> 構文が使用されます。YARA-L では次のタイプの変数を使用できます。
イベント変数
イベント変数は、イベントのグループまたはエンティティ イベントを表します。events セクションで、名前、イベントソース、イベント フィールドを使用して、イベント変数の条件を指定します。
イベントソースは、
udm(正規化されたイベントの場合)とgraph(エンティティ イベントの場合)です。ソースを省略すると、udmがデフォルトのソースとして設定されます。イベント フィールドは、.<field name> のチェーンで表されます(例: $e.field1.field2)。フィールド チェーンは常に最上位のソース(UDM またはエンティティ)から始まります。
一致変数
一致変数は、match セクションで使用され、指定された期間内の共通の値に基づいてイベントをグループ化します。
一意の変数セットのセット(および期間)ごとに 1 行が返されるため、クエリのグループ フィールドになります。クエリが一致を見つけると、一致変数の値が返されます。
各一致変数が表す内容を events セクションで指定します。
プレースホルダ変数
プレースホルダ変数は、UDM イベント フィールドから特定の値をキャプチャして保存し、クエリ全体で参照して使用するために使用されます。これらは、特にマルチイベント クエリで、異なるイベントをリンクするために使用されます。プレースホルダに共通の値(userid や hostname など)を割り当てると、match セクションでこのプレースホルダを使用して、指定した期間内にその値を共有するイベントをグループ化できます。
events セクションでプレースホルダ変数を定義するには、UDM フィールドの値を $ 接頭辞が付いた変数名(例: $targetUser = $e.target.user.userid)に割り当てます。
次のセクションでプレースホルダ変数を定義することもできます。
conditionセクションで一致条件を指定します。outcomeセクション: 計算の実行、指標の定義、一致したイベントからの特定のデータポイントの抽出を行います。matchセクションを使用して、共通の値でイベントをグループ化します。
キーワード
YARA-L では、キーワードは検出クエリの構造とロジックを定義する予約語です。これらは、クエリのさまざまなセクションを指定したり、論理演算や数学演算を実行したり、イベントを照合するための条件を定義したりするために使用されます。これらのキーワードは、クエリ、文字列、変数の識別子として使用できません。
キーワードでは大文字と小文字が区別されません(たとえば、and と AND は同等です)。
YARA-L 2.0 キーワードの主なカテゴリ
このリストは完全ではありませんが、堅牢な検出クエリの構築に YARA-L 2.0 で使用される主なキーワードを網羅しています。
- クエリの定義:
rule: 新しい YARA-L クエリの定義を開始します。private: クエリを非公開として指定し、外部に直接公開されたり、外部からトリガーされたりしないようにします。global: クエリをグローバルとしてマークし、広範囲に適用する必要があることを示します。
- クエリ セクション:
meta: クエリに関する説明情報用のメタデータ セクションを導入します。strings: 文字列パターンが定義されているセクションを示します。condition: クエリ トリガーのブール値ロジックを含むセクションを指定します。events: イベント変数とその条件を指定するセクションを定義します。match: 期間にわたって値を集計するセクションを紹介します。outcome: トリガーされたクエリにコンテキストとスコアリングを追加するセクションを定義します。
- 文字列修飾子:
ascii: 文字列を ASCII テキストとして照合することを指定します。wide: 文字列をワイド(UTF-16)文字として照合することを示します。nocase: 大文字と小文字を区別しない文字列の一致を実行します。fullword: 文字列が完全な単語として一致することを要求します。xor: 一致する前に文字列に XOR 変換を適用します。base64、base64wide: 照合前に Base64 エンコードを適用します。
- 論理演算子:
and、or、not: 条件を組み合わせるための標準のブール値論理演算子。all of、any of: 条件内の複数の式を評価するために使用されます。
- 比較演算子と関係演算子:
at: 文字列照合の正確なオフセットを指定します。contains: 文字列に部分文字列が含まれているかどうかを確認します。startswith、endswith: 文字列が部分文字列で始まるか終わるかを確認します。icontains、istartswith、iendswith、iequals: 大文字と小文字を区別しないバージョン。matches: 正規表現のマッチングに使用されます。
- データ型とサイズ指定子:
int8、uint8、int16、uint16、int32、uint32: 指定されたサイズの整数型。int8be、uint8be、int16be、uint16be、int32be、uint32be: 整数型のビッグ エンディアン バージョン。filesize: 分析対象のファイルのサイズを表します。entrypoint: 実行可能ファイルのエントリ ポイントを指します。
マップ
YARA-L は、一部の UDM フィールドで使用される 構造体とラベルのデータ型のマップをサポートしています。
Struct と Label の両方のデータ型で特定の Key-Value ペアを検索するには、標準のマップ構文を使用します。
- 構造体のフィールドの構文:
$e.udm.additional.fields["pod_name"] = "kube-scheduler" - ラベル フィールドの構文:
$e.metadata.ingestion_labels["MetadataKeyDeletion"] = "startup-script"
例: 地図の有効な使用と無効な使用
次の例は、マップの有効な使用法と無効な使用法を示しています。
地図の有効な使用
イベント セクションで Struct フィールドを使用する:
events: $e.udm.additional.fields["pod_name"] = "kube-scheduler"
結果セクションでラベル フィールドを使用する:
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](https://developers.google.com/protocol-buffers/docs/reference/google.protobuf#struct) データ型の場合、マップ構文は値が文字列であるキーにのみアクセスできます。値が整数などの他のプリミティブ型のキーにアクセスすることはできません。
マップでの重複値の処理
マップアクセスは、特定のキーに関連付けられた単一の値を取得することを目的としています。これは標準的な動作です。ただし、まれに map access のコンテキストが複数の値を誤って指すことがあります。マップ アクセスが複数の値を参照するまれなエッジケースでは、map access は最初の値を決定論的に返します。これは、ラベルに重複したキーがある場合や、ラベルに祖先の繰り返しフィールドがある場合に発生することがあります。
ラベルに重複したキーがある
ラベル構造はマップを表しますが、キーの一意性は強制されません。慣例により、マップには一意のキーが必要です。そのため、Google SecOps では、重複するキーでラベルを設定することはおすすめしません。
例: 重複するキーを含むラベル
次のデータ例で実行すると、クエリテキスト $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"
}
}
}
マップで結果変数にアクセスする
このセクションでは、マップ内の結果変数を文字列としてではなく、元のデータ型(整数、ブール値、これらの型のリストなど)としてアクセスする方法について説明します。この機能を使用すると、クエリ ロジックの柔軟性と精度を高めることができます。
結果データは次のフィールドで確認できます。
- 結果の値は、
variablesフィールドで元の型を保持します。 outcomesフィールドには、下位互換性のためにstringバージョンが保存されます。
これらの結果値にアクセスするには、variables マップを使用して特定の型を取得するか、配列インデックスを使用してシーケンス内の要素にアクセスします。シーケンス内の特定のアイテムにインデックスでアクセスするか、シーケンス全体を選択して各値を個別に評価できます。
構文:
$d.detection.detection.variables[OUTCOME_NAME].TYPE_SUFFIX
シーケンスの構文:
$d.detection.detection.variables[OUTCOME_NAME].SEQUENCE_TYPE_SUFFIX.TYPE_VALS_SUFFIX
例: マップで結果変数にアクセスする
文字列の結果にアクセスする:
$my_string_outcome = $d.detection.detection.variables["outcome_ip"].string_val
この例では、文字列値を直接取得します(たとえば、outcome_ip が単一の文字列の場合、"1.1.1.1")。
整数結果にアクセスする
$my_int_outcome = $d.detection.detection.variables["outcome_port"].int64_value
この例では、整数値(30 など)を取得します。
Int64Sequence を使用して整数のリストにアクセスする
$my_int_list = $d.detection.detection.variables["outcome_ports"].int64_seq.int64_vals
この例では、整数の完全なリストを取得し、繰り返しフィールド([2, 3, 4] など)のようにネスト解除します。
整数のリストから特定の要素にアクセスする
$first_int = $d.detection.detection.variables["outcome_ports"].int64_seq.int64_vals[0]
この例では、リストから最初の整数(2 など)を取得します。
文字列のリスト(StringSequence)にアクセスする
$my_string_list = $d.detection.detection.variables["outcome_ips"].string_seq.string_vals
この例では、文字列の完全なリストを取得し、繰り返しフィールド(["1.1.1.1", "2.2.2.2"] など)のようにネスト解除します。
文字列のリストから特定の要素にアクセスする
$first_ip = $d.detection.detection.variables["outcome_ips"].string_seq.string_vals[0]
この例では、リストから最初の IP アドレス("1.1.1.1" など)を取得します。
variables で使用可能な型接尾辞
サポートされている接尾辞の一覧については、FindingVariable をご覧ください。
さらにサポートが必要な場合 コミュニティ メンバーや Google SecOps のプロフェッショナルから回答を得ることができます。