式、演算子、その他の構成要素
このドキュメントでは、式を使用して 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 // Regular expression 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 // Regular expression 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ステートメントの最大数(特殊演算子の有無にかかわらず): 10 regex演算子を使用したinステートメントの最大数: 5cidr演算子を使用したinステートメントの最大数: 5
論理式
論理 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 を使用して暗黙的に結合されます。その結果、評価の順序が変わります。
論理式でのデータテーブル検索
events セクション内でデータテーブル検索(in %list 構文)を使用する場合、次の構文上の制約が適用されます。
型の排他性: 同じ論理ブロック内で、標準フィールドの比較(
$field = "value"など)とデータテーブル検索を混在させることはできません。演算子の制限: データテーブル検索は、
OR演算子を使用して他のデータテーブル検索と結合することのみが可能です。これらの式ではAND演算子はサポートされていません。ORを使用したイベント変数の排他性:OR演算子を使用してデータテーブル検索を結合する場合、OR式内のすべての検索は同じイベント変数のフィールドを参照する必要があります。たとえば、($e.user in %table1 OR $e.group in %table2)は有効です。ただし、($e.user in %table OR $g.user in %table)などの式はサポートされていません。これは、OR条件で異なるイベント変数($eや$gなど)を検索する場合、共通の等価アンカーがないため、コンパイラは実行時にRULE ERROR: error processing ruleで失敗します。
例: 構文エラーによる無効な結果
// Invalid: Mixing a field comparison with a data table lookup
($field = "value" OR $field in %list)
// Invalid: Using AND with data table lookups
($field_A in %list_A AND $field_B in %list_B)
例: 有効な例
// Valid: Multiple data table lookups joined by OR
($field in %list_A OR $field in %list_B)
例: 無効な変数間の OR
// Invalid: OR condition across different event variables
($e.user in %table OR $g.user in %table)
ロジックで標準フィールド チェックとデータテーブル検索の両方が必要な場合は、events セクション内で個別の独立した述語として定義する必要があります。
列挙型
演算子は列挙型で使用できます。ルールに適用して、パフォーマンスを簡素化し、最適化できます(リファレンス リストの代わりに演算子を使用します)。
次の例では、「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
コメント
クエリでコメントを使用して、詳細情報を提供できます。スラッシュ文字を使用してコメントを示します。
- 1 行のコメントの場合は、2 つのスラッシュ文字(
// comment)を使用します。 - 複数行のコメントの場合は、1 つのスラッシュ文字とアスタリスク文字(
/* 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 で変数を使用する
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セクションでmatch条件を指定します。outcomeセクションで、計算の実行、指標の定義、一致したイベントからの特定のデータポイントの抽出を行います。matchセクションで、共通の値でイベントをグループ化します。
関数からプレースホルダへの割り当て
YARA-L では、関数からプレースホルダへの割り当ては、UDM イベントデータを変換し、ルール全体で使用できるように結果を保存するプロセスです。 このアクションを使用すると、events セクションで計算やデータ操作を実行し、match、condition、および outcome セクションでその結果を参照できます。
主なコンポーネントは次のとおりです。
- 関数: 特定のイベント フィールドに対して計算やデータ変換(文字列操作や数学など)を行う組み込みオペレーション。
- プレースホルダ変数: コンテナとして機能する、
$接頭辞が付いたユーザー定義変数($user、$ipなど)。イベントから直接抽出された値、または関数の出力によって生成された値を保存します。 - 割り当て: 関数の出力をプレースホルダ変数にリンクし、変換されたデータを検出ロジックの残りの部分でアクセスできるようにするロジック。
制限事項
関数からプレースホルダへの割り当てを使用する場合、次の 2 つの制限があります。
すべてのプレースホルダを、イベント フィールドを含む式に割り当てる必要があります。
有効な例
$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.関数呼び出しは、いずれか 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)
キーワードを使用してクエリを定義する
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 マップのサポート
YARA-L は、一部の UDM フィールドで使用される Struct データ型と Label データ型のマップをサポートしています。
Struct データ型と Label データ型の両方で特定の Key-Value ペアを検索するには、標準のマップ構文を使用します。
- Struct フィールドの構文:
$e.udm.additional.fields["pod_name"] = "kube-scheduler" - Label フィールドの構文:
$e.metadata.ingestion_labels["MetadataKeyDeletion"] = "startup-script"
例: マップの有効な使用と無効な使用
次の例は、マップの有効な使用と無効な使用を示しています。
マップの有効な使用
events セクションで Struct フィールドを使用する:
events: $e.udm.additional.fields["pod_name"] = "kube-scheduler"
outcome セクションで Label フィールドを使用する:
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
この例では、文字列値を直接取得します("1.1.1.1" が
outcome_ip が単一の文字列の場合はなど)。
整数の結果にアクセスする
$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 のプロフェッショナルから回答を得ることができます。