EQL構文リファレンス
基本構文
EQLクエリには、イベントカテゴリと一致条件が必要です。where
キーワードがそれらを接続します。
Eql
event_category where condition
イベントカテゴリは、イベントカテゴリフィールドのインデックス付き値です。デフォルトでは、EQL検索APIは、Elastic Common Schema (ECS)からevent.category
フィールドを使用します。APIのevent_category_field
パラメータを使用して、別のイベントカテゴリフィールドを指定できます。
たとえば、次のEQLクエリは、イベントカテゴリがprocess
で、process.name
がsvchost.exe
のイベントに一致します:
Eql
process where process.name == "svchost.exe"
任意のイベントカテゴリに一致
任意のカテゴリのイベントに一致させるには、any
キーワードを使用します。また、any
キーワードを使用して、イベントカテゴリフィールドがないドキュメントを検索することもできます。
たとえば、次のEQLクエリは、network.protocol
フィールド値がhttp
の任意のドキュメントに一致します:
Eql
any where network.protocol == "http"
イベントカテゴリをエスケープ
イベントカテゴリをエスケープするには、囲む二重引用符("
)または三重の囲む二重引用符("""
)を使用します。
- 特殊文字(ハイフン
-
やドット.
など)を含む - スペースを含む
- 数字で始まる
Eql
".my.event.category"
"my-event-category"
"my event category"
"6eventcategory"
""".my.event.category"""
"""my-event-category"""
"""my event category"""
"""6eventcategory"""
フィールド名をエスケープ
フィールド名をエスケープするには、囲むバックティック(`)を使用します。
- ハイフン(
-
)を含む - スペースを含む
- 数字で始まる
Eql
フィールド名内のバックティック(`)をエスケープするには、二重バックティック(``)を使用します。
Eql
my`field -> `my``field`
条件
条件は、イベントが一致しなければならない1つ以上の基準で構成されます。これらの基準を指定し、次の演算子を使用して組み合わせることができます。ほとんどのEQL演算子はデフォルトで大文字と小文字を区別します。
比較演算子
Eql
< <= == : != >= >
<
(未満)- 演算子の左側の値が右側の値より小さい場合、
true
を返します。それ以外の場合はfalse
を返します。 <=
(以下または等しい)- 演算子の左側の値が右側の値以下の場合、
true
を返します。それ以外の場合はfalse
を返します。 ==
(等しい、大文字と小文字を区別)- 演算子の左側と右側の値が等しい場合、
true
を返します。それ以外の場合はfalse
を返します。ワイルドカードはサポートされていません。 :
(等しい、大文字と小文字を区別しない)- 演算子の左側と右側の文字列が等しい場合、
true
を返します。それ以外の場合はfalse
を返します。文字列の比較にのみ使用できます。ワイルドカードとリストルックアップをサポートします。 !=
(等しくない、大文字と小文字を区別)- 演算子の左側と右側の値が等しくない場合、
true
を返します。それ以外の場合はfalse
を返します。ワイルドカードはサポートされていません。 >=
(以上または等しい)- 演算子の左側の値が右側の値以上の場合、
true
を返します。それ以外の場合はfalse
を返します。文字列を比較する場合、演算子は大文字と小文字を区別する辞書式順序を使用します。 >
(より大きい)- 演算子の左側の値が右側の値より大きい場合、
true
を返します。それ以外の場合はfalse
を返します。
### パターン比較キーワード
#### Eql
``````eql
my_field like "VALUE*" // case-sensitive wildcard matching
my_field like~ "value*" // case-insensitive wildcard matching
my_field regex "VALUE[^Z].?" // case-sensitive regex matching
my_field regex~ "value[^z].?" // case-insensitive regex matching
`
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
process where process.parent.name == "foo" and process.parent.name == process.name
代わりに、process.parent.name
フィールドとprocess.name
フィールドの両方を静的値と比較するようにクエリを書き換えることができます。
Eql
process where process.parent.name == "foo" and process.name == "foo"
論理演算子
Eql
and or not
and
- 左側と右側の条件の両方が
true
を返す場合にのみ、true
を返します。それ以外の場合はfalse
を返します。 or
- 左側または右側の条件のいずれかが
true
の場合、true
を返します。それ以外の場合はfalse
を返します。 not
- 右側の条件が
false
の場合、true
を返します。
ルックアップ演算子
Eql
my_field in ("Value-1", "VALUE2", "VAL3") // case-sensitive
my_field in~ ("value-1", "value2", "val3") // case-insensitive
my_field not in ("Value-1", "VALUE2", "VAL3") // case-sensitive
my_field not in~ ("value-1", "value2", "val3") // case-insensitive
my_field : ("value-1", "value2", "val3") // case-insensitive
my_field like ("Value-*", "VALUE2", "VAL?") // case-sensitive
my_field like~ ("value-*", "value2", "val?") // case-insensitive
my_field regex ("[vV]alue-[0-9]", "VALUE[^2].?", "VAL3") // case-sensitive
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
+ - * / %
+
(加算)- 演算子の左側と右側の値を加算します。
-
(減算)- 演算子の右側の値を左側の値から減算します。
*
(乗算)- 演算子の左側と右側の値を乗算します。
/
(除算)- 演算子の左側の値を右側の値で割ります。
もし被除数と除数の両方が整数の場合、除算(\
)操作は返される浮動小数点数を最も近い整数に切り捨てます。切り捨てを避けるには、被除数または除数のいずれかを浮動小数点数に変換します。
例process.args_count
フィールドは、プロセス引数のカウントを含むlong
整数フィールドです。
ユーザーは、次のEQLクエリがprocess.args_count
値が4
のイベントにのみ一致することを期待するかもしれません。
Eql
process where ( 4 / process.args_count ) == 1
しかし、EQLクエリは、process.args_count
値が3
または4
のイベントに一致します。
`````process.args_count`````値が`````4`````のイベントにのみ一致させるには、被除数または除数のいずれかを浮動小数点数に変換します。
次のEQLクエリは、整数`````4`````を同等の浮動小数点数`````4.0`````に変更します。
#### Eql
``````eql
process where ( 4.0 / process.args_count ) == 1
`
%
(剰余)- 演算子の左側の値を右側の値で割ります。余りのみを返します。
任意の条件に一致
イベントカテゴリのみに基づいてイベントに一致させるには、where true
条件を使用します。
たとえば、次のEQLクエリは、任意のfile
イベントに一致します:
Eql
file where true
任意のイベントに一致させるには、any
キーワードをwhere true
条件と組み合わせることができます:
Eql
any where true
オプションフィールド
デフォルトでは、EQLクエリには、検索しているデータセットに存在するフィールドのみを含めることができます。フィールドは、明示的、動的、またはランタイムマッピングがある場合にデータセットに存在します。EQLクエリに存在しないフィールドが含まれている場合、エラーが返されます。
データセットにフィールドが存在するかどうかわからない場合は、?
演算子を使用してフィールドをオプションとしてマークします。オプションフィールドが存在しない場合、クエリはエラーを返すのではなく、null
で置き換えます。
例
次のクエリでは、user.id
フィールドがオプションです。
Eql
network where ?user.id != null
#### Eql
``````eql
network where null != null
`
この場合、クエリはイベントに一致しません。
フィールドが存在するか確認
フィールドの値が存在するイベントに一致させるには、null
を使用して!=
演算子を使用してフィールドを比較します:
Eql
?my_field != null
フィールド値が存在しないイベントに一致させるには、null
を使用して==
演算子を使用してフィールドを比較します:
Eql
?my_field == null
文字列
文字列は二重引用符("
)で囲まれます。
Eql
"hello world"
単一引用符('
)で囲まれた文字列はサポートされていません。
文字列内のエスケープ文字
文字列内で使用される場合、キャリッジリターンや二重引用符("
)などの特殊文字は、前のバックスラッシュ(\
)でエスケープする必要があります。
Eql
"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
"""Raw string with a literal double quote " and blackslash \ included"""
生文字列には三重の二重引用符("""
)を含めることはできません。代わりに、\"
エスケープシーケンスを使用した通常の文字列を使用してください。
Eql
"String containing \"\"\" three double quotes"
ワイルドカード
#### Eql
``````eql
my_field : "doc*" // Matches "doc", "docs", or "document" but not "DOS"
my_field : "*doc" // Matches "adoc" or "asciidoc"
my_field : "d*c" // Matches "doc" or "disc"
my_field like "DOC*" // Matches "DOC", "DOCS", "DOCs", or "DOCUMENT" but not "DOS"
my_field like "D*C" // Matches "DOC", "DISC", or "DisC"
`
#### Eql
``````eql
my_field : "doc?" // Matches "docs" but not "doc", "document", or "DOS"
my_field : "?doc" // Matches "adoc" but not "asciidoc"
my_field : "d?c" // Matches "doc" but not "disc"
my_field like "DOC?" // Matches "DOCS" or "DOCs" but not "DOC", "DOCUMENT", or "DOS"
my_field like "D?c" // Matches "DOC" but not "DISC"
`
#### Eql
``````eql
my_field : ("doc*", "f*o", "ba?", "qux")
my_field like ("Doc*", "F*O", "BA?", "QUX")
`
シーケンス
EQLシーケンスを使用して、順序付けられたイベントの系列を記述し、一致させることができます。シーケンス内の各項目は、イベントカテゴリとイベント条件であり、角括弧([ ]
)で囲まれています。イベントは、最も最近のイベントが最後にリストされるように、昇順の時間順にリストされます。
Eql
sequence
[ event_category_1 where condition_1 ]
[ event_category_2 where condition_2 ]
...
例
次のEQLシーケンスクエリは、この順序付けられたイベントの系列に一致します:
- 1. イベントで開始:
file
のイベントカテゴリfile.extension
のexe
- 2.
process
のイベントに続く
Eql
sequence
[ file where file.extension == "exe" ]
[ process where true ]
maxspanステートメントを使用
with maxspan
を使用して、シーケンスを指定された時間範囲に制約できます。一致するシーケンス内のすべてのイベントは、最初のイベントのタイムスタンプからこの期間内に発生する必要があります。
#### Eql
``````eql
sequence with maxspan=30s
[ event_category_1 where condition_1 ] by field_baz
[ event_category_2 where condition_2 ] by field_bar
...
`
例
次のシーケンスクエリは、maxspan
値が15m
(15分)を使用します。一致するシーケンス内のイベントは、最初のイベントのタイムスタンプから15分以内に発生する必要があります。
Eql
sequence with maxspan=15m
[ file where file.extension == "exe" ]
[ process where true ]
欠落イベント
!
を使用して、欠落イベントに一致させます: 与えられた条件を満たさない時間範囲制約のあるシーケンス内のイベント。
Eql
sequence with maxspan=1h
[ event_category_1 where condition_1 ]
![ event_category_2 where condition_2 ]
[ event_category_3 where condition_3 ]
...
欠落イベントの句は、シーケンスの先頭、末尾、および/または中間に、正のイベント句と任意の組み合わせで使用できます。シーケンスには複数の欠落イベント句を含めることができますが、少なくとも1つの正の句が必要です。with maxspan
は、欠落イベント句が存在する場合に必須です。
例
次のシーケンスクエリは、ログオンイベントが5秒以内にログオフイベントに続かないことを見つけます。
Eql
sequence by host.name, user.name with maxspan=5s
[ authentication where event.code : "4624" ]
![ authentication where event.code : "4647" ]
キーワードによる
by
キーワードをシーケンスクエリで使用して、同じ値を共有するイベントのみを一致させます。たとえそれらの値が異なるフィールドにあってもです。これらの共有値は、結合キーと呼ばれます。結合キーがすべてのイベントで同じフィールドにある必要がある場合は、sequence by
を使用します。
Eql
sequence by field_foo
[ event_category_1 where condition_1 ] by field_baz
[ event_category_2 where condition_2 ] by field_bar
...
例
次のシーケンスクエリは、by
キーワードを使用して、一致するイベントを次のように制約します:
- 同じ
user.name
値を持つイベント - 次の
process
イベントのfile.path
値に等しいfile
イベント。
Eql
sequence
[ file where file.extension == "exe" ] by user.name, file.path
[ process where true ] by user.name, process.executable
user.name
フィールドがシーケンス内のすべてのイベントで共有されているため、sequence by
を使用して含めることができます。次のシーケンスは、前のものと同等です。
Eql
sequence by user.name
[ file where file.extension == "exe" ] by file.path
[ process where true ] by process.executable
sequence by
とwith maxspan
を組み合わせて、フィールド値と時間範囲の両方でシーケンスを制約できます。
Eql
sequence by field_foo with maxspan=30s
[ event_category_1 where condition_1 ]
[ event_category_2 where condition_2 ]
...
例
次のシーケンスクエリは、sequence by
とwith maxspan
を使用して、次の条件を満たすイベントのシーケンスのみを一致させます:
- 同じ
user.name
フィールド値を共有する - 最初の一致するイベントの
15m
(15分)以内に発生する
Eql
sequence by user.name with maxspan=15m
[ file where file.extension == "exe" ]
[ 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
sequence by process.pid, ?process.entity_id
[process where process.name == "regsvr32.exe"]
[network where true]
untilキーワード
#### Eql
``````eql
sequence
[ event_category_1 where condition_1 ]
[ event_category_2 where condition_2 ]
...
until [ event_category_3 where condition_3 ]
`
例
データセットには、共有IDでグループ化された次のイベントシーケンスが含まれています:
Txt
A, B
A, B, C
A, C, B
次のEQLクエリは、イベントA
の後にイベントB
が続くシーケンスをデータセットで検索します。イベントC
は有効期限イベントとして使用されます。
Eql
sequence by ID
A
B
until C
クエリは、シーケンスA, B
とA, B, C
に一致しますが、A, C, B
には一致しません。
Windowsでは、プロセスID(PID)は、プロセスが実行中の間のみ一意です。プロセスが終了すると、そのPIDは再利用される可能性があります。
`````by`````および`````sequence by`````キーワードを使用して、同じPID値を持つイベントのシーケンスを検索できます。
**例**
次のEQLクエリは、`````sequence by`````キーワードを使用して、同じ`````process.pid`````値を共有するイベントのシーケンスに一致します。
#### Eql
``````eql
sequence by process.pid
[ process where event.type == "start" and process.name == "cmd.exe" ]
[ process where file.extension == "exe" ]
`
しかし、PIDの再利用により、無関係なプロセスにまたがるイベントを含む一致するシーケンスが生成される可能性があります。誤検知を防ぐために、until
キーワードを使用して、プロセス終了イベントの前に一致するシーケンスを終了させることができます。
次のEQLクエリは、until
キーワードを使用して、process
のevent.type
がstop
のイベントの前にシーケンスを終了させます。これらのイベントは、プロセスが終了したことを示します。
Eql
sequence by process.pid
[ process where event.type == "start" and process.name == "cmd.exe" ]
[ process where file.extension == "exe" ]
until [ process where event.type == "stop" ]
runsステートメントを使用
with runs
ステートメントを使用して、シーケンスクエリ内で同じイベント基準を連続して実行できます。たとえば:
Eql
sequence
[ process where event.type == "creation" ]
[ library where process.name == "regsvr32.exe" ] with runs=3
[ registry where true ]
は次のように等しいです:
Eql
sequence
[ process where event.type == "creation" ]
[ library where process.name == "regsvr32.exe" ]
[ library where process.name == "regsvr32.exe" ]
[ library where process.name == "regsvr32.exe" ]
[ registry where true ]
[`````with runs`````キーワード](38d25857bc9a9de1.md#eql-by-keyword)とともに`````by`````ステートメントを使用できます。たとえば:
#### Eql
``````eql
sequence
[ process where event.type == "creation" ] by process.executable
[ library where process.name == "regsvr32.exe" ] by dll.path with runs=3
`
サンプル
EQLサンプルを使用して、時間的に無秩序なイベントの系列を記述し、一致させることができます。サンプル内のすべてのイベントは、by
キーワード(結合キー)を使用して指定された1つ以上のフィールドの同じ値を共有します。サンプル内の各項目は、イベントカテゴリとイベント条件であり、角括弧([ ]
)で囲まれています。イベントは、マッチするフィルターの順序でリストされます。
Eql
sample by join_key
[ event_category_1 where condition_1 ]
[ event_category_2 where condition_2 ]
...
例
次のEQLサンプルクエリは、host
のユニークな値を持つ最大10のサンプルを返します。各サンプルは2つのイベントで構成されます:
- 1. イベントで開始:
file
のイベントカテゴリfile.extension
のexe
- 2.
process
のイベントに続く
Eql
sample by host
[ file where file.extension == "exe" ]
[ process where true ]
サンプルクエリは、イベントの時間的順序を考慮しません。with maxspan
およびwith runs
ステートメント、ならびにuntil
キーワードはサポートされていません。
関数
EQL関数を使用して、データ型を変換したり、数学を行ったり、文字列を操作したりできます。サポートされている関数のリストについては、関数リファレンスを参照してください。
大文字と小文字を区別しない関数
ほとんどのEQL関数はデフォルトで大文字と小文字を区別します。関数を大文字と小文字を区別しないようにするには、関数名の後に~
演算子を使用します:
Eql
stringContains(process.name,".exe") // Matches ".exe" but not ".EXE" or ".Exe"
stringContains~(process.name,".exe") // Matches ".exe", ".EXE", or ".Exe"
関数が検索パフォーマンスに与える影響
EQLクエリで関数を使用すると、検索速度が遅くなる可能性があります。インデックスデータを変換するために関数を頻繁に使用する場合は、インデックス作成中にこれらの変更を行うことで検索を高速化できます。ただし、これはしばしばインデックス速度が遅くなることを意味します。
例
インデックスにはfile.path
フィールドが含まれています。file.path
には、ファイルのフルパスが含まれ、ファイル拡張子も含まれています。
EQL検索を実行する際、ユーザーはしばしばendsWith
関数をfile.path
フィールドとともに使用して、ファイル拡張子に一致させます:
Eql
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
file where file.extension in ("exe", "dll")
本番環境にデプロイする前に、インデックス作成の変更をテストおよびベンチマークすることをお勧めします。インデックス速度の調整および検索速度の調整を参照してください。
パイプ
EQLパイプは、EQLクエリによって返されたイベントをフィルタリング、集約、および後処理します。パイプを使用して、EQLクエリの結果を絞り込んだり、より具体的にしたりできます。
パイプは、パイプ(|
)文字を使用して区切られます。
Eql
event_category where condition | pipe
例
次のEQLクエリは、tail
パイプを使用して、クエリに一致する最新の10のイベントのみを返します。
Eql
authentication where agent.id == 4624
| 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は次のことをサポートしていません:
- 配列関数:
match
関数- 結合
- 系譜関連のキーワード:
child of
descendant of
event of
- 次のパイプ:
シーケンスクエリがマッチを処理する方法
シーケンスクエリは、シーケンスのすべての潜在的なマッチを見つけることはありません。このアプローチは、大規模なイベントデータセットに対しては遅すぎてコストがかかりすぎます。代わりに、シーケンスクエリは保留中のシーケンスマッチを状態遷移機械として処理します:
- シーケンスクエリ内の各イベント項目は、機械の状態です。
- 各状態には、一度に1つの保留中のシーケンスのみが存在できます。
- 同じ状態に同時に2つの保留中のシーケンスがある場合、最新のシーケンスが古いものを上書きします。
- クエリに
by
フィールドが含まれている場合、クエリは各ユニークなby
フィールド値に対して別々の状態遷移機械を使用します。
例
データセットには、次のprocess
イベントが昇順で含まれています:
Js
{ "index" : { "_id": "1" } }
{ "user": { "name": "root" }, "process": { "name": "attrib" }, ...}
{ "index" : { "_id": "2" } }
{ "user": { "name": "root" }, "process": { "name": "attrib" }, ...}
{ "index" : { "_id": "3" } }
{ "user": { "name": "elkbee" }, "process": { "name": "bash" }, ...}
{ "index" : { "_id": "4" } }
{ "user": { "name": "root" }, "process": { "name": "bash" }, ...}
{ "index" : { "_id": "5" } }
{ "user": { "name": "root" }, "process": { "name": "bash" }, ...}
{ "index" : { "_id": "6" } }
{ "user": { "name": "elkbee" }, "process": { "name": "attrib" }, ...}
{ "index" : { "_id": "7" } }
{ "user": { "name": "root" }, "process": { "name": "attrib" }, ...}
{ "index" : { "_id": "8" } }
{ "user": { "name": "elkbee" }, "process": { "name": "bash" }, ...}
{ "index" : { "_id": "9" } }
{ "user": { "name": "root" }, "process": { "name": "cat" }, ...}
{ "index" : { "_id": "10" } }
{ "user": { "name": "elkbee" }, "process": { "name": "cat" }, ...}
{ "index" : { "_id": "11" } }
{ "user": { "name": "root" }, "process": { "name": "cat" }, ...}
EQLシーケンスクエリはデータセットを検索します:
Eql
sequence by user.name
[process where process.name == "attrib"]
[process where process.name == "bash"]
[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
{ "index" : { "_id": "1" } }
{ "user": { "name": "root" }, "process": { "name": "attrib" }, ...}
// Creates sequence [1] in state A for the "root" user.
//
// +------------------------"root"------------------------+
// | +-----------+ +-----------+ +------------+ |
// | | State A | | State B | | Complete | |
// | +-----------+ +-----------+ +------------+ |
// | | [1] | | | | | |
// | +-----------+ +-----------+ +------------+ |
// +------------------------------------------------------+
{ "index" : { "_id": "2" } }
{ "user": { "name": "root" }, "process": { "name": "attrib" }, ...}
// Creates sequence [2] in state A for "root", overwriting sequence [1].
//
// +------------------------"root"------------------------+
// | +-----------+ +-----------+ +------------+ |
// | | State A | | State B | | Complete | |
// | +-----------+ +-----------+ +------------+ |
// | | [2] | | | | | |
// | +-----------+ +-----------+ +------------+ |
// +------------------------------------------------------+
{ "index" : { "_id": "3" } }
{ "user": { "name": "elkbee" }, "process": { "name": "bash" }, ...}
// Nothing happens. The "elkbee" user has no pending sequence to move
// from state A to state B.
//
// +-----------------------"elkbee"-----------------------+
// | +-----------+ +-----------+ +------------+ |
// | | State A | | State B | | Complete | |
// | +-----------+ +-----------+ +------------+ |
// | | | | | | | |
// | +-----------+ +-----------+ +------------+ |
// +------------------------------------------------------+
{ "index" : { "_id": "4" } }
{ "user": { "name": "root" }, "process": { "name": "bash" }, ...}
// Sequence [2] moves out of state A for "root".
// State B for "root" now contains [2, 4].
// State A for "root" is empty.
//
// +------------------------"root"------------------------+
// | +-----------+ +-----------+ +------------+ |
// | | State A | | State B | | Complete | |
// | +-----------+ --> +-----------+ +------------+ |
// | | | | [2, 4] | | | |
// | +-----------+ +-----------+ +------------+ |
// +------------------------------------------------------+
{ "index" : { "_id": "5" } }
{ "user": { "name": "root" }, "process": { "name": "bash" }, ...}
// Nothing happens. State A is empty for "root".
//
// +------------------------"root"------------------------+
// | +-----------+ +-----------+ +------------+ |
// | | State A | | State B | | Complete | |
// | +-----------+ +-----------+ +------------+ |
// | | | | [2, 4] | | | |
// | +-----------+ +-----------+ +------------+ |
// +------------------------------------------------------+
{ "index" : { "_id": "6" } }
{ "user": { "name": "elkbee" }, "process": { "name": "attrib" }, ...}
// Creates sequence [6] in state A for "elkbee".
//
// +-----------------------"elkbee"-----------------------+
// | +-----------+ +-----------+ +------------+ |
// | | State A | | State B | | Complete | |
// | +-----------+ +-----------+ +------------+ |
// | | [6] | | | | | |
// | +-----------+ +-----------+ +------------+ |
// +------------------------------------------------------+
{ "index" : { "_id": "7" } }
{ "user": { "name": "root" }, "process": { "name": "attrib" }, ...}
// Creates sequence [7] in state A for "root".
// Sequence [2, 4] remains in state B for "root".
//
// +------------------------"root"------------------------+
// | +-----------+ +-----------+ +------------+ |
// | | State A | | State B | | Complete | |
// | +-----------+ +-----------+ +------------+ |
// | | [7] | | [2, 4] | | | |
// | +-----------+ +-----------+ +------------+ |
// +------------------------------------------------------+
{ "index" : { "_id": "8" } }
{ "user": { "name": "elkbee" }, "process": { "name": "bash" }, ...}
// Sequence [6, 8] moves to state B for "elkbee".
// State A for "elkbee" is now empty.
//
// +-----------------------"elkbee"-----------------------+
// | +-----------+ +-----------+ +------------+ |
// | | State A | | State B | | Complete | |
// | +-----------+ --> +-----------+ +------------+ |
// | | | | [6, 8] | | | |
// | +-----------+ +-----------+ +------------+ |
// +------------------------------------------------------+
{ "index" : { "_id": "9" } }
{ "user": { "name": "root" }, "process": { "name": "cat" }, ...}
// Sequence [2, 4, 9] is complete for "root".
// State B for "root" is now empty.
// Sequence [7] remains in state A.
//
// +------------------------"root"------------------------+
// | +-----------+ +-----------+ +------------+ |
// | | State A | | State B | | Complete | |
// | +-----------+ +-----------+ --> +------------+ |
// | | [7] | | | | [2, 4, 9] |
// | +-----------+ +-----------+ +------------+ |
// +------------------------------------------------------+
{ "index" : { "_id": "10" } }
{ "user": { "name": "elkbee" }, "process": { "name": "cat" }, ...}
// Sequence [6, 8, 10] is complete for "elkbee".
// State A and B for "elkbee" are now empty.
//
// +-----------------------"elkbee"-----------------------+
// | +-----------+ +-----------+ +------------+ |
// | | State A | | State B | | Complete | |
// | +-----------+ +-----------+ --> +------------+ |
// | | | | | | [6, 8, 10] |
// | +-----------+ +-----------+ +------------+ |
// +------------------------------------------------------+
{ "index" : { "_id": "11" } }
{ "user": { "name": "root" }, "process": { "name": "cat" }, ...}
// Nothing happens.
// The machines for "root" and "elkbee" remain the same.
//
// +------------------------"root"------------------------+
// | +-----------+ +-----------+ +------------+ |
// | | State A | | State B | | Complete | |
// | +-----------+ +-----------+ +------------+ |
// | | [7] | | | | [2, 4, 9] |
// | +-----------+ +-----------+ +------------+ |
// +------------------------------------------------------+
//
// +-----------------------"elkbee"-----------------------+
// | +-----------+ +-----------+ +------------+ |
// | | State A | | State B | | Complete | |
// | +-----------+ +-----------+ +------------+ |
// | | | | | | [6, 8, 10] |
// | +-----------+ +-----------+ +------------+ |
// +------------------------------------------------------+