EQL構文リファレンス

基本構文

EQLクエリには、イベントカテゴリと一致条件が必要です。whereキーワードがそれらを接続します。

Eql

  1. event_category where condition

イベントカテゴリは、イベントカテゴリフィールドのインデックス付き値です。デフォルトでは、EQL検索APIは、Elastic Common Schema (ECS)からevent.categoryフィールドを使用します。APIのevent_category_fieldパラメータを使用して、別のイベントカテゴリフィールドを指定できます。

たとえば、次のEQLクエリは、イベントカテゴリがprocessで、process.namesvchost.exeのイベントに一致します:

Eql

  1. process where process.name == "svchost.exe"

任意のイベントカテゴリに一致

任意のカテゴリのイベントに一致させるには、anyキーワードを使用します。また、anyキーワードを使用して、イベントカテゴリフィールドがないドキュメントを検索することもできます。

たとえば、次のEQLクエリは、network.protocolフィールド値がhttpの任意のドキュメントに一致します:

Eql

  1. any where network.protocol == "http"

イベントカテゴリをエスケープ

イベントカテゴリをエスケープするには、囲む二重引用符(")または三重の囲む二重引用符(""")を使用します。

  • 特殊文字(ハイフン-やドット.など)を含む
  • スペースを含む
  • 数字で始まる

Eql

  1. ".my.event.category"
  2. "my-event-category"
  3. "my event category"
  4. "6eventcategory"
  5. """.my.event.category"""
  6. """my-event-category"""
  7. """my event category"""
  8. """6eventcategory"""

フィールド名をエスケープ

フィールド名をエスケープするには、囲むバックティック(`)を使用します。

  • ハイフン(-)を含む
  • スペースを含む
  • 数字で始まる

Eql

フィールド名内のバックティック(`)をエスケープするには、二重バックティック(``)を使用します。

Eql

  1. my`field -> `my``field`

条件

条件は、イベントが一致しなければならない1つ以上の基準で構成されます。これらの基準を指定し、次の演算子を使用して組み合わせることができます。ほとんどのEQL演算子はデフォルトで大文字と小文字を区別します。

比較演算子

Eql

  1. < <= == : != >= >
  • <(未満)
  • 演算子の左側の値が右側の値より小さい場合、trueを返します。それ以外の場合はfalseを返します。
  • <=(以下または等しい)
  • 演算子の左側の値が右側の値以下の場合、trueを返します。それ以外の場合はfalseを返します。
  • ==(等しい、大文字と小文字を区別)
  • 演算子の左側と右側の値が等しい場合、trueを返します。それ以外の場合はfalseを返します。ワイルドカードはサポートされていません。
  • :(等しい、大文字と小文字を区別しない)
  • 演算子の左側と右側の文字列が等しい場合、trueを返します。それ以外の場合はfalseを返します。文字列の比較にのみ使用できます。ワイルドカードリストルックアップをサポートします。
  • !=(等しくない、大文字と小文字を区別)
  • 演算子の左側と右側の値が等しくない場合、trueを返します。それ以外の場合はfalseを返します。ワイルドカードはサポートされていません。
  • >=(以上または等しい)
  • 演算子の左側の値が右側の値以上の場合、trueを返します。それ以外の場合はfalseを返します。文字列を比較する場合、演算子は大文字と小文字を区別する辞書式順序を使用します。
  • >(より大きい)
  • 演算子の左側の値が右側の値より大きい場合、trueを返します。それ以外の場合はfalseを返します。
  1. ### パターン比較キーワード
  2. #### Eql
  3. ``````eql
  4. my_field like "VALUE*" // case-sensitive wildcard matching
  5. my_field like~ "value*" // case-insensitive wildcard matching
  6. my_field regex "VALUE[^Z].?" // case-sensitive regex matching
  7. my_field regex~ "value[^z].?" // case-insensitive regex matching
  8. `
  • like(大文字と小文字を区別)
  • キーワードの左側の文字列が右側のワイルドカードパターンに一致する場合、trueを返します。リストルックアップをサポートします。文字列の比較にのみ使用できます。大文字と小文字を区別しない一致にはlike~を使用します。
  • regex(大文字と小文字を区別)
  • キーワードの左側の文字列が右側の正規表現に一致する場合、trueを返します。サポートされている正規表現構文については、正規表現構文を参照してください。リストルックアップをサポートします。文字列の比較にのみ使用できます。大文字と小文字を区別しない一致にはregex~を使用します。

比較の制限

比較を連鎖させることはできません。代わりに、比較の間に論理演算子を使用してください。たとえば、foo < bar <= bazはサポートされていません。ただし、foo < bar and bar <= bazとして式を書き換えることができます。これはサポートされています。

フィールドを別のフィールドと比較することもできません。たとえフィールドが関数を使用して変更されていてもです。

次のEQLクエリは、process.parent_nameフィールド値を静的値fooと比較します。この比較はサポートされています。

ただし、クエリはprocess.parent.nameフィールド値をprocess.nameフィールドと比較します。この比較はサポートされておらず、クエリ全体にエラーを返します。

Eql

  1. process where process.parent.name == "foo" and process.parent.name == process.name

代わりに、process.parent.nameフィールドとprocess.nameフィールドの両方を静的値と比較するようにクエリを書き換えることができます。

Eql

  1. process where process.parent.name == "foo" and process.name == "foo"

論理演算子

Eql

  1. and or not
  • and
  • 左側と右側の条件の両方がtrueを返す場合にのみ、trueを返します。それ以外の場合はfalseを返します。
  • or
  • 左側または右側の条件のいずれかがtrueの場合、trueを返します。それ以外の場合はfalseを返します。
  • not
  • 右側の条件がfalseの場合、trueを返します。

ルックアップ演算子

Eql

  1. my_field in ("Value-1", "VALUE2", "VAL3") // case-sensitive
  2. my_field in~ ("value-1", "value2", "val3") // case-insensitive
  3. my_field not in ("Value-1", "VALUE2", "VAL3") // case-sensitive
  4. my_field not in~ ("value-1", "value2", "val3") // case-insensitive
  5. my_field : ("value-1", "value2", "val3") // case-insensitive
  6. my_field like ("Value-*", "VALUE2", "VAL?") // case-sensitive
  7. my_field like~ ("value-*", "value2", "val?") // case-insensitive
  8. my_field regex ("[vV]alue-[0-9]", "VALUE[^2].?", "VAL3") // case-sensitive
  9. my_field regex~ ("value-[0-9]", "value[^2].?", "val3") // case-insensitive
  • in(大文字と小文字を区別)
  • 値が提供されたリストに含まれている場合、trueを返します。大文字と小文字を区別しない一致にはin~を使用します。
  • not in(大文字と小文字を区別)
  • 値が提供されたリストに含まれていない場合、trueを返します。大文字と小文字を区別しない一致にはnot in~を使用します。
  • :(大文字と小文字を区別しない)
  • 文字列が提供されたリストに含まれている場合、trueを返します。文字列の比較にのみ使用できます。
  • like(大文字と小文字を区別)
  • 文字列が提供されたリスト内のワイルドカードパターンに一致する場合、trueを返します。文字列の比較にのみ使用できます。大文字と小文字を区別しない一致にはlike~を使用します。
  • regex(大文字と小文字を区別)
  • 文字列が提供されたリスト内の正規表現パターンに一致する場合、trueを返します。サポートされている正規表現構文については、正規表現構文を参照してください。文字列の比較にのみ使用できます。大文字と小文字を区別しない一致にはregex~を使用します。

数学演算子

Eql

  1. + - * / %
  • +(加算)
  • 演算子の左側と右側の値を加算します。
  • -(減算)
  • 演算子の右側の値を左側の値から減算します。
  • *(乗算)
  • 演算子の左側と右側の値を乗算します。
  • /(除算)
  • 演算子の左側の値を右側の値で割ります。

    もし被除数と除数の両方が整数の場合、除算(\)操作は返される浮動小数点数を最も近い整数に切り捨てます。切り捨てを避けるには、被除数または除数のいずれかを浮動小数点数に変換します。

    process.args_countフィールドは、プロセス引数のカウントを含むlong整数フィールドです。
    ユーザーは、次のEQLクエリがprocess.args_count値が4のイベントにのみ一致することを期待するかもしれません。

Eql

  1. process where ( 4 / process.args_count ) == 1

しかし、EQLクエリは、process.args_count値が3または4のイベントに一致します。

  1. `````process.args_count`````値が`````4`````のイベントにのみ一致させるには、被除数または除数のいずれかを浮動小数点数に変換します。
  2. 次のEQLクエリは、整数`````4`````を同等の浮動小数点数`````4.0`````に変更します。
  3. #### Eql
  4. ``````eql
  5. process where ( 4.0 / process.args_count ) == 1
  6. `
  • %(剰余)
  • 演算子の左側の値を右側の値で割ります。余りのみを返します。

任意の条件に一致

イベントカテゴリのみに基づいてイベントに一致させるには、where true条件を使用します。

たとえば、次のEQLクエリは、任意のfileイベントに一致します:

Eql

  1. file where true

任意のイベントに一致させるには、anyキーワードをwhere true条件と組み合わせることができます:

Eql

  1. any where true

オプションフィールド

デフォルトでは、EQLクエリには、検索しているデータセットに存在するフィールドのみを含めることができます。フィールドは、明示的動的、またはランタイムマッピングがある場合にデータセットに存在します。EQLクエリに存在しないフィールドが含まれている場合、エラーが返されます。

データセットにフィールドが存在するかどうかわからない場合は、?演算子を使用してフィールドをオプションとしてマークします。オプションフィールドが存在しない場合、クエリはエラーを返すのではなく、nullで置き換えます。

次のクエリでは、user.idフィールドがオプションです。

Eql

  1. network where ?user.id != null
  1. #### Eql
  2. ``````eql
  3. network where null != null
  4. `

この場合、クエリはイベントに一致しません。

フィールドが存在するか確認

フィールドの値が存在するイベントに一致させるには、nullを使用して!=演算子を使用してフィールドを比較します:

Eql

  1. ?my_field != null

フィールド値が存在しないイベントに一致させるには、nullを使用して==演算子を使用してフィールドを比較します:

Eql

  1. ?my_field == null

文字列

文字列は二重引用符(")で囲まれます。

Eql

  1. "hello world"

単一引用符(')で囲まれた文字列はサポートされていません。

文字列内のエスケープ文字

文字列内で使用される場合、キャリッジリターンや二重引用符(")などの特殊文字は、前のバックスラッシュ(\)でエスケープする必要があります。

Eql

  1. "example \r of \" escaped \n characters"
エスケープシーケンス リテラル文字
\n 改行(ラインフィード)
\r キャリッジリターン
\t タブ
\\ バックスラッシュ(\
\" 二重引用符("

16進数の\u{XXXXXXXX}エスケープシーケンスを使用してUnicode文字をエスケープできます。16進数の値は2〜8文字で、大文字と小文字を区別しません。8文字未満の値はゼロパディングされます。これらのエスケープシーケンスを使用して、非表示または右から左(RTL)文字を文字列に含めることができます。たとえば、右から左マーク(RLM)\u{200f}\u{200F}、または\u{0000200f}としてエスケープできます。

単一引用符(')文字は将来の使用のために予約されています。リテラル文字列にエスケープされた単一引用符(\')を使用することはできません。代わりにエスケープされた二重引用符(\")を使用してください。

生文字列

生文字列は、バックスラッシュ(\)などの特殊文字をリテラル文字として扱います。生文字列は三重の二重引用符(""")で囲まれます。

Eql

  1. """Raw string with a literal double quote " and blackslash \ included"""

生文字列には三重の二重引用符(""")を含めることはできません。代わりに、\"エスケープシーケンスを使用した通常の文字列を使用してください。

Eql

  1. "String containing \"\"\" three double quotes"

ワイルドカード

  1. #### Eql
  2. ``````eql
  3. my_field : "doc*" // Matches "doc", "docs", or "document" but not "DOS"
  4. my_field : "*doc" // Matches "adoc" or "asciidoc"
  5. my_field : "d*c" // Matches "doc" or "disc"
  6. my_field like "DOC*" // Matches "DOC", "DOCS", "DOCs", or "DOCUMENT" but not "DOS"
  7. my_field like "D*C" // Matches "DOC", "DISC", or "DisC"
  8. `
  1. #### Eql
  2. ``````eql
  3. my_field : "doc?" // Matches "docs" but not "doc", "document", or "DOS"
  4. my_field : "?doc" // Matches "adoc" but not "asciidoc"
  5. my_field : "d?c" // Matches "doc" but not "disc"
  6. my_field like "DOC?" // Matches "DOCS" or "DOCs" but not "DOC", "DOCUMENT", or "DOS"
  7. my_field like "D?c" // Matches "DOC" but not "DISC"
  8. `
  1. #### Eql
  2. ``````eql
  3. my_field : ("doc*", "f*o", "ba?", "qux")
  4. my_field like ("Doc*", "F*O", "BA?", "QUX")
  5. `

シーケンス

EQLシーケンスを使用して、順序付けられたイベントの系列を記述し、一致させることができます。シーケンス内の各項目は、イベントカテゴリとイベント条件であり、角括弧([ ])で囲まれています。イベントは、最も最近のイベントが最後にリストされるように、昇順の時間順にリストされます。

Eql

  1. sequence
  2. [ event_category_1 where condition_1 ]
  3. [ event_category_2 where condition_2 ]
  4. ...

次のEQLシーケンスクエリは、この順序付けられたイベントの系列に一致します:

  • 1. イベントで開始:
    • fileのイベントカテゴリ
    • file.extensionexe
  • 2. processのイベントに続く

Eql

  1. sequence
  2. [ file where file.extension == "exe" ]
  3. [ process where true ]

maxspanステートメントを使用

with maxspanを使用して、シーケンスを指定された時間範囲に制約できます。一致するシーケンス内のすべてのイベントは、最初のイベントのタイムスタンプからこの期間内に発生する必要があります。

  1. #### Eql
  2. ``````eql
  3. sequence with maxspan=30s
  4. [ event_category_1 where condition_1 ] by field_baz
  5. [ event_category_2 where condition_2 ] by field_bar
  6. ...
  7. `

次のシーケンスクエリは、maxspan値が15m(15分)を使用します。一致するシーケンス内のイベントは、最初のイベントのタイムスタンプから15分以内に発生する必要があります。

Eql

  1. sequence with maxspan=15m
  2. [ file where file.extension == "exe" ]
  3. [ process where true ]

欠落イベント

!を使用して、欠落イベントに一致させます: 与えられた条件を満たさない時間範囲制約のあるシーケンス内のイベント。

Eql

  1. sequence with maxspan=1h
  2. [ event_category_1 where condition_1 ]
  3. ![ event_category_2 where condition_2 ]
  4. [ event_category_3 where condition_3 ]
  5. ...

欠落イベントの句は、シーケンスの先頭、末尾、および/または中間に、正のイベント句と任意の組み合わせで使用できます。シーケンスには複数の欠落イベント句を含めることができますが、少なくとも1つの正の句が必要です。with maxspanは、欠落イベント句が存在する場合に必須です。

次のシーケンスクエリは、ログオンイベントが5秒以内にログオフイベントに続かないことを見つけます。

Eql

  1. sequence by host.name, user.name with maxspan=5s
  2. [ authentication where event.code : "4624" ]
  3. ![ authentication where event.code : "4647" ]

キーワードによる

byキーワードをシーケンスクエリで使用して、同じ値を共有するイベントのみを一致させます。たとえそれらの値が異なるフィールドにあってもです。これらの共有値は、結合キーと呼ばれます。結合キーがすべてのイベントで同じフィールドにある必要がある場合は、sequence byを使用します。

Eql

  1. sequence by field_foo
  2. [ event_category_1 where condition_1 ] by field_baz
  3. [ event_category_2 where condition_2 ] by field_bar
  4. ...

次のシーケンスクエリは、byキーワードを使用して、一致するイベントを次のように制約します:

  • 同じuser.name値を持つイベント
  • 次のprocessイベントのfile.path値に等しいfileイベント。

Eql

  1. sequence
  2. [ file where file.extension == "exe" ] by user.name, file.path
  3. [ process where true ] by user.name, process.executable

user.nameフィールドがシーケンス内のすべてのイベントで共有されているため、sequence byを使用して含めることができます。次のシーケンスは、前のものと同等です。

Eql

  1. sequence by user.name
  2. [ file where file.extension == "exe" ] by file.path
  3. [ process where true ] by process.executable

sequence bywith maxspanを組み合わせて、フィールド値と時間範囲の両方でシーケンスを制約できます。

Eql

  1. sequence by field_foo with maxspan=30s
  2. [ event_category_1 where condition_1 ]
  3. [ event_category_2 where condition_2 ]
  4. ...

次のシーケンスクエリは、sequence bywith maxspanを使用して、次の条件を満たすイベントのシーケンスのみを一致させます:

  • 同じuser.nameフィールド値を共有する
  • 最初の一致するイベントの15m(15分)以内に発生する

Eql

  1. sequence by user.name with maxspan=15m
  2. [ file where file.extension == "exe" ]
  3. [ process where true ]

フィールドによるオプション

デフォルトでは、結合キーは非nullフィールド値でなければなりません。null結合キーを許可するには、?演算子を使用してbyフィールドをオプションとしてマークします。これは、検索しているデータセットにbyフィールドが含まれているかどうかわからない場合にも役立ちます。

次のシーケンスクエリは、sequence byを使用して、一致するイベントを次のように制約します:

  • 同じprocess.pid値を持つイベント、null値を除外します。process.pidフィールドが検索しているデータセットに存在しない場合、クエリはエラーを返します。
  • 同じprocess.entity_id値を持つイベント、null値を含みます。イベントにprocess.entity_idフィールドが含まれていない場合、そのprocess.entity_id値はnullと見なされます。これは、process.pidフィールドが検索しているデータセットに存在しない場合でも適用されます。

Eql

  1. sequence by process.pid, ?process.entity_id
  2. [process where process.name == "regsvr32.exe"]
  3. [network where true]

untilキーワード

  1. #### Eql
  2. ``````eql
  3. sequence
  4. [ event_category_1 where condition_1 ]
  5. [ event_category_2 where condition_2 ]
  6. ...
  7. until [ event_category_3 where condition_3 ]
  8. `

データセットには、共有IDでグループ化された次のイベントシーケンスが含まれています:

Txt

  1. A, B
  2. A, B, C
  3. A, C, B

次のEQLクエリは、イベントAの後にイベントBが続くシーケンスをデータセットで検索します。イベントCは有効期限イベントとして使用されます。

Eql

  1. sequence by ID
  2. A
  3. B
  4. until C

クエリは、シーケンスA, BA, B, Cに一致しますが、A, C, Bには一致しません。

  1. Windowsでは、プロセスIDPID)は、プロセスが実行中の間のみ一意です。プロセスが終了すると、そのPIDは再利用される可能性があります。
  2. `````by`````および`````sequence by`````キーワードを使用して、同じPID値を持つイベントのシーケンスを検索できます。
  3. **例**
  4. 次のEQLクエリは、`````sequence by`````キーワードを使用して、同じ`````process.pid`````値を共有するイベントのシーケンスに一致します。
  5. #### Eql
  6. ``````eql
  7. sequence by process.pid
  8. [ process where event.type == "start" and process.name == "cmd.exe" ]
  9. [ process where file.extension == "exe" ]
  10. `

しかし、PIDの再利用により、無関係なプロセスにまたがるイベントを含む一致するシーケンスが生成される可能性があります。誤検知を防ぐために、untilキーワードを使用して、プロセス終了イベントの前に一致するシーケンスを終了させることができます。

次のEQLクエリは、untilキーワードを使用して、processevent.typestopのイベントの前にシーケンスを終了させます。これらのイベントは、プロセスが終了したことを示します。

Eql

  1. sequence by process.pid
  2. [ process where event.type == "start" and process.name == "cmd.exe" ]
  3. [ process where file.extension == "exe" ]
  4. until [ process where event.type == "stop" ]

runsステートメントを使用

with runsステートメントを使用して、シーケンスクエリ内で同じイベント基準を連続して実行できます。たとえば:

Eql

  1. sequence
  2. [ process where event.type == "creation" ]
  3. [ library where process.name == "regsvr32.exe" ] with runs=3
  4. [ registry where true ]

は次のように等しいです:

Eql

  1. sequence
  2. [ process where event.type == "creation" ]
  3. [ library where process.name == "regsvr32.exe" ]
  4. [ library where process.name == "regsvr32.exe" ]
  5. [ library where process.name == "regsvr32.exe" ]
  6. [ registry where true ]
  1. [`````with runs`````キーワード](38d25857bc9a9de1.md#eql-by-keyword)とともに`````by`````ステートメントを使用できます。たとえば:
  2. #### Eql
  3. ``````eql
  4. sequence
  5. [ process where event.type == "creation" ] by process.executable
  6. [ library where process.name == "regsvr32.exe" ] by dll.path with runs=3
  7. `

サンプル

EQLサンプルを使用して、時間的に無秩序なイベントの系列を記述し、一致させることができます。サンプル内のすべてのイベントは、byキーワード(結合キー)を使用して指定された1つ以上のフィールドの同じ値を共有します。サンプル内の各項目は、イベントカテゴリとイベント条件であり、角括弧([ ])で囲まれています。イベントは、マッチするフィルターの順序でリストされます。

Eql

  1. sample by join_key
  2. [ event_category_1 where condition_1 ]
  3. [ event_category_2 where condition_2 ]
  4. ...

次のEQLサンプルクエリは、hostのユニークな値を持つ最大10のサンプルを返します。各サンプルは2つのイベントで構成されます:

  • 1. イベントで開始:
    • fileのイベントカテゴリ
    • file.extensionexe
  • 2. processのイベントに続く

Eql

  1. sample by host
  2. [ file where file.extension == "exe" ]
  3. [ process where true ]

サンプルクエリは、イベントの時間的順序を考慮しません。with maxspanおよびwith runsステートメント、ならびにuntilキーワードはサポートされていません。

関数

EQL関数を使用して、データ型を変換したり、数学を行ったり、文字列を操作したりできます。サポートされている関数のリストについては、関数リファレンスを参照してください。

大文字と小文字を区別しない関数

ほとんどのEQL関数はデフォルトで大文字と小文字を区別します。関数を大文字と小文字を区別しないようにするには、関数名の後に~演算子を使用します:

Eql

  1. stringContains(process.name,".exe") // Matches ".exe" but not ".EXE" or ".Exe"
  2. stringContains~(process.name,".exe") // Matches ".exe", ".EXE", or ".Exe"

関数が検索パフォーマンスに与える影響

EQLクエリで関数を使用すると、検索速度が遅くなる可能性があります。インデックスデータを変換するために関数を頻繁に使用する場合は、インデックス作成中にこれらの変更を行うことで検索を高速化できます。ただし、これはしばしばインデックス速度が遅くなることを意味します。

インデックスにはfile.pathフィールドが含まれています。file.pathには、ファイルのフルパスが含まれ、ファイル拡張子も含まれています。

EQL検索を実行する際、ユーザーはしばしばendsWith関数をfile.pathフィールドとともに使用して、ファイル拡張子に一致させます:

Eql

  1. file where endsWith(file.path,".exe") or endsWith(file.path,".dll")

これが機能する一方で、書くのが繰り返しになり、検索速度が遅くなる可能性があります。検索を高速化するには、次のようにすることができます:

  • 1. 新しいフィールドを追加file.extensionをインデックスに追加します。file.extensionフィールドには、file.pathフィールドからのファイル拡張子のみが含まれます。
  • 2. インジェストパイプラインを使用して、grokプロセッサまたは他の前処理ツールを含め、インデックス作成前にfile.pathフィールドからファイル拡張子を抽出します。
  • 3. 抽出されたファイル拡張子をfile.extensionフィールドにインデックスします。

これらの変更はインデックス作成を遅くする可能性がありますが、検索を高速化することができます。ユーザーは複数のendsWith関数呼び出しの代わりにfile.extensionフィールドを使用できます:

Eql

  1. file where file.extension in ("exe", "dll")

本番環境にデプロイする前に、インデックス作成の変更をテストおよびベンチマークすることをお勧めします。インデックス速度の調整および検索速度の調整を参照してください。

パイプ

EQLパイプは、EQLクエリによって返されたイベントをフィルタリング、集約、および後処理します。パイプを使用して、EQLクエリの結果を絞り込んだり、より具体的にしたりできます。

パイプは、パイプ(|)文字を使用して区切られます。

Eql

  1. event_category where condition | pipe

次のEQLクエリは、tailパイプを使用して、クエリに一致する最新の10のイベントのみを返します。

Eql

  1. authentication where agent.id == 4624
  2. | tail 10

パイプの出力を別のパイプに渡すことができます。これにより、単一のクエリで複数のパイプを使用できます。

サポートされているパイプのリストについては、パイプリファレンスを参照してください。

制限

EQLには次の制限があります。

EQLはフィールドパラメータを使用

EQLは、検索APIのfieldsパラメータを使用してフィールド値を取得します。fieldsパラメータに関する制限は、EQLクエリにも適用されます。たとえば、_sourceが返されるフィールドまたはインデックスレベルで無効になっている場合、値は取得できません。

フィールドの比較

EQL比較演算子を使用して、フィールドを別のフィールドと比較することはできません。これは、フィールドが関数を使用して変更されている場合でも適用されます。

テキストフィールドはサポートされていません

EQL検索は、textフィールドをサポートしていません。textフィールドを検索するには、EQL検索APIのクエリDSL filterパラメータを使用してください。

ネストされたフィールドでのEQL検索

EQLを使用して、nestedフィールドの値やnestedフィールドのサブフィールドを検索することはできません。ただし、nestedフィールドマッピングを含むデータストリームおよびインデックスは、その他のサポートを受けています。

エンドゲームEQL構文との違い

Elasticsearch EQLは、Elastic Endgame EQL構文と以下の点で異なります:

  • Elasticsearch EQLでは、ほとんどの演算子は大文字と小文字を区別します。たとえば、process_name == "cmd.exe"process_name == "Cmd.exe"と等しくありません。
  • Elasticsearch EQLでは、関数も大文字と小文字を区別します。関数を大文字と小文字を区別しないようにするには、~を使用します。たとえば、endsWith~(process_name, ".exe")のように。
  • 大文字と小文字を区別しない等価比較には、:演算子を使用します。*?は、どちらもワイルドカード文字として認識されます。
  • ==および!=演算子は、ワイルドカード文字を展開しません。たとえば、process_name == "cmd*.exe"*をリテラルのアスタリスクとして解釈し、ワイルドカードとしては解釈しません。
  • ワイルドカードマッチングには、大文字と小文字を区別する場合はlikeキーワードを、大文字と小文字を区別しない場合はlike~を使用します。:演算子はlike~と同等です。
  • 正規表現マッチングにはregexまたはregex~を使用します。
  • ===演算子の代わりにはなりません。
  • シングルクォートで囲まれた文字列(')はサポートされていません。代わりにダブルクォート(")で囲んでください。
  • ?"および?'は生の文字列を示しません。生の文字列は三重のダブルクォート(""")で囲んでください。
  • Elasticsearch EQLは次のことをサポートしていません:

シーケンスクエリがマッチを処理する方法

シーケンスクエリは、シーケンスのすべての潜在的なマッチを見つけることはありません。このアプローチは、大規模なイベントデータセットに対しては遅すぎてコストがかかりすぎます。代わりに、シーケンスクエリは保留中のシーケンスマッチを状態遷移機械として処理します:

  • シーケンスクエリ内の各イベント項目は、機械の状態です。
  • 各状態には、一度に1つの保留中のシーケンスのみが存在できます。
  • 同じ状態に同時に2つの保留中のシーケンスがある場合、最新のシーケンスが古いものを上書きします。
  • クエリにbyフィールドが含まれている場合、クエリは各ユニークなbyフィールド値に対して別々の状態遷移機械を使用します。

データセットには、次のprocessイベントが昇順で含まれています:

Js

  1. { "index" : { "_id": "1" } }
  2. { "user": { "name": "root" }, "process": { "name": "attrib" }, ...}
  3. { "index" : { "_id": "2" } }
  4. { "user": { "name": "root" }, "process": { "name": "attrib" }, ...}
  5. { "index" : { "_id": "3" } }
  6. { "user": { "name": "elkbee" }, "process": { "name": "bash" }, ...}
  7. { "index" : { "_id": "4" } }
  8. { "user": { "name": "root" }, "process": { "name": "bash" }, ...}
  9. { "index" : { "_id": "5" } }
  10. { "user": { "name": "root" }, "process": { "name": "bash" }, ...}
  11. { "index" : { "_id": "6" } }
  12. { "user": { "name": "elkbee" }, "process": { "name": "attrib" }, ...}
  13. { "index" : { "_id": "7" } }
  14. { "user": { "name": "root" }, "process": { "name": "attrib" }, ...}
  15. { "index" : { "_id": "8" } }
  16. { "user": { "name": "elkbee" }, "process": { "name": "bash" }, ...}
  17. { "index" : { "_id": "9" } }
  18. { "user": { "name": "root" }, "process": { "name": "cat" }, ...}
  19. { "index" : { "_id": "10" } }
  20. { "user": { "name": "elkbee" }, "process": { "name": "cat" }, ...}
  21. { "index" : { "_id": "11" } }
  22. { "user": { "name": "root" }, "process": { "name": "cat" }, ...}

EQLシーケンスクエリはデータセットを検索します:

Eql

  1. sequence by user.name
  2. [process where process.name == "attrib"]
  3. [process where process.name == "bash"]
  4. [process where process.name == "cat"]

クエリのイベント項目は次の状態に対応します:

  • 状態A: [process where process.name == "attrib"]
  • 状態B: [process where process.name == "bash"]
  • 完了: [process where process.name == "cat"]

    シーケンス状態遷移機械

マッチするシーケンスを見つけるために、クエリは各ユニークなuser.name値に対して別々の状態遷移機械を使用します。データセットに基づいて、rootユーザー用とelkbee用の2つの状態遷移機械が期待できます。

別々の状態遷移機械

保留中のシーケンスマッチは、次のように各機械の状態を移動します:

Txt

  1. { "index" : { "_id": "1" } }
  2. { "user": { "name": "root" }, "process": { "name": "attrib" }, ...}
  3. // Creates sequence [1] in state A for the "root" user.
  4. //
  5. // +------------------------"root"------------------------+
  6. // | +-----------+ +-----------+ +------------+ |
  7. // | | State A | | State B | | Complete | |
  8. // | +-----------+ +-----------+ +------------+ |
  9. // | | [1] | | | | | |
  10. // | +-----------+ +-----------+ +------------+ |
  11. // +------------------------------------------------------+
  12. { "index" : { "_id": "2" } }
  13. { "user": { "name": "root" }, "process": { "name": "attrib" }, ...}
  14. // Creates sequence [2] in state A for "root", overwriting sequence [1].
  15. //
  16. // +------------------------"root"------------------------+
  17. // | +-----------+ +-----------+ +------------+ |
  18. // | | State A | | State B | | Complete | |
  19. // | +-----------+ +-----------+ +------------+ |
  20. // | | [2] | | | | | |
  21. // | +-----------+ +-----------+ +------------+ |
  22. // +------------------------------------------------------+
  23. { "index" : { "_id": "3" } }
  24. { "user": { "name": "elkbee" }, "process": { "name": "bash" }, ...}
  25. // Nothing happens. The "elkbee" user has no pending sequence to move
  26. // from state A to state B.
  27. //
  28. // +-----------------------"elkbee"-----------------------+
  29. // | +-----------+ +-----------+ +------------+ |
  30. // | | State A | | State B | | Complete | |
  31. // | +-----------+ +-----------+ +------------+ |
  32. // | | | | | | | |
  33. // | +-----------+ +-----------+ +------------+ |
  34. // +------------------------------------------------------+
  35. { "index" : { "_id": "4" } }
  36. { "user": { "name": "root" }, "process": { "name": "bash" }, ...}
  37. // Sequence [2] moves out of state A for "root".
  38. // State B for "root" now contains [2, 4].
  39. // State A for "root" is empty.
  40. //
  41. // +------------------------"root"------------------------+
  42. // | +-----------+ +-----------+ +------------+ |
  43. // | | State A | | State B | | Complete | |
  44. // | +-----------+ --> +-----------+ +------------+ |
  45. // | | | | [2, 4] | | | |
  46. // | +-----------+ +-----------+ +------------+ |
  47. // +------------------------------------------------------+
  48. { "index" : { "_id": "5" } }
  49. { "user": { "name": "root" }, "process": { "name": "bash" }, ...}
  50. // Nothing happens. State A is empty for "root".
  51. //
  52. // +------------------------"root"------------------------+
  53. // | +-----------+ +-----------+ +------------+ |
  54. // | | State A | | State B | | Complete | |
  55. // | +-----------+ +-----------+ +------------+ |
  56. // | | | | [2, 4] | | | |
  57. // | +-----------+ +-----------+ +------------+ |
  58. // +------------------------------------------------------+
  59. { "index" : { "_id": "6" } }
  60. { "user": { "name": "elkbee" }, "process": { "name": "attrib" }, ...}
  61. // Creates sequence [6] in state A for "elkbee".
  62. //
  63. // +-----------------------"elkbee"-----------------------+
  64. // | +-----------+ +-----------+ +------------+ |
  65. // | | State A | | State B | | Complete | |
  66. // | +-----------+ +-----------+ +------------+ |
  67. // | | [6] | | | | | |
  68. // | +-----------+ +-----------+ +------------+ |
  69. // +------------------------------------------------------+
  70. { "index" : { "_id": "7" } }
  71. { "user": { "name": "root" }, "process": { "name": "attrib" }, ...}
  72. // Creates sequence [7] in state A for "root".
  73. // Sequence [2, 4] remains in state B for "root".
  74. //
  75. // +------------------------"root"------------------------+
  76. // | +-----------+ +-----------+ +------------+ |
  77. // | | State A | | State B | | Complete | |
  78. // | +-----------+ +-----------+ +------------+ |
  79. // | | [7] | | [2, 4] | | | |
  80. // | +-----------+ +-----------+ +------------+ |
  81. // +------------------------------------------------------+
  82. { "index" : { "_id": "8" } }
  83. { "user": { "name": "elkbee" }, "process": { "name": "bash" }, ...}
  84. // Sequence [6, 8] moves to state B for "elkbee".
  85. // State A for "elkbee" is now empty.
  86. //
  87. // +-----------------------"elkbee"-----------------------+
  88. // | +-----------+ +-----------+ +------------+ |
  89. // | | State A | | State B | | Complete | |
  90. // | +-----------+ --> +-----------+ +------------+ |
  91. // | | | | [6, 8] | | | |
  92. // | +-----------+ +-----------+ +------------+ |
  93. // +------------------------------------------------------+
  94. { "index" : { "_id": "9" } }
  95. { "user": { "name": "root" }, "process": { "name": "cat" }, ...}
  96. // Sequence [2, 4, 9] is complete for "root".
  97. // State B for "root" is now empty.
  98. // Sequence [7] remains in state A.
  99. //
  100. // +------------------------"root"------------------------+
  101. // | +-----------+ +-----------+ +------------+ |
  102. // | | State A | | State B | | Complete | |
  103. // | +-----------+ +-----------+ --> +------------+ |
  104. // | | [7] | | | | [2, 4, 9] |
  105. // | +-----------+ +-----------+ +------------+ |
  106. // +------------------------------------------------------+
  107. { "index" : { "_id": "10" } }
  108. { "user": { "name": "elkbee" }, "process": { "name": "cat" }, ...}
  109. // Sequence [6, 8, 10] is complete for "elkbee".
  110. // State A and B for "elkbee" are now empty.
  111. //
  112. // +-----------------------"elkbee"-----------------------+
  113. // | +-----------+ +-----------+ +------------+ |
  114. // | | State A | | State B | | Complete | |
  115. // | +-----------+ +-----------+ --> +------------+ |
  116. // | | | | | | [6, 8, 10] |
  117. // | +-----------+ +-----------+ +------------+ |
  118. // +------------------------------------------------------+
  119. { "index" : { "_id": "11" } }
  120. { "user": { "name": "root" }, "process": { "name": "cat" }, ...}
  121. // Nothing happens.
  122. // The machines for "root" and "elkbee" remain the same.
  123. //
  124. // +------------------------"root"------------------------+
  125. // | +-----------+ +-----------+ +------------+ |
  126. // | | State A | | State B | | Complete | |
  127. // | +-----------+ +-----------+ +------------+ |
  128. // | | [7] | | | | [2, 4, 9] |
  129. // | +-----------+ +-----------+ +------------+ |
  130. // +------------------------------------------------------+
  131. //
  132. // +-----------------------"elkbee"-----------------------+
  133. // | +-----------+ +-----------+ +------------+ |
  134. // | | State A | | State B | | Complete | |
  135. // | +-----------+ +-----------+ +------------+ |
  136. // | | | | | | [6, 8, 10] |
  137. // | +-----------+ +-----------+ +------------+ |
  138. // +------------------------------------------------------+