Spec-Zone.ru › Elasticsearch 8
›Руководство по Elasticsearch [8.17] ›Поиск EQL

Справочник по синтаксису EQL

Основной синтаксис

Запросы EQL требуют категории события и условия соответствия. Ключевое слово where соединяет их.

event_category where condition

Категория события — это индексированное значение поля категории события. По умолчанию API поиска EQL использует поле event.category из Elastic Common Schema (ECS). Вы можете указать другое поле категории события, используя параметр API event_category_field.

Например, следующий запрос EQL соответствует событиям с категорией события process и значением process.name равным svchost.exe:

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

Соответствие любой категории события

Чтобы сопоставить события любой категории, используйте ключевое слово any. Также можно использовать ключевое слово any, чтобы искать документы без поля категории события.

Например, следующий запрос EQL соответствует любым документам со значением поля network.protocol равным http:

any where network.protocol == "http"

Экранирование категории события

Используйте двойные кавычки (") или тройные двойные кавычки ("""), чтобы экранировать категории событий, которые:

  • Содержат специальный символ, такой как дефис (-) или точка (.)
  • Содержат пробел
  • Начинаются с цифры
".my.event.category"
"my-event-category"
"my event category"
"6eventcategory"

""".my.event.category"""
"""my-event-category"""
"""my event category"""
"""6eventcategory"""

Экранирование имени поля

Используйте обратные кавычки (`) для экранирования имён полей, которые:

  • Содержат дефис (-)
  • Содержат пробел
  • Начинаются с цифры
`my-field`
`my field`
`6myfield`

Используйте двойные обратные кавычки (``), чтобы экранировать любые обратные кавычки (`) в имени поля.

my`field -> `my``field`

Условия

Условие состоит из одного или нескольких критериев, которым должно соответствовать событие. Вы можете указать и объединить эти критерии, используя следующие операторы. Большинство операторов EQL по умолчанию чувствительны к регистру.

Операторы сравнения

<   <=   ==   :   !=   >=   >
< (меньше)
Возвращает true, если значение слева от оператора меньше значения справа. В противном случае возвращает false.
<= (меньше или равно)
Возвращает true, если значение слева от оператора меньше или равно значению справа. В противном случае возвращает false.
== (равно, чувствительно к регистру)
Возвращает true, если значения слева и справа от оператора равны. В противном случае возвращает false. Подстановки не поддерживаются.
: (равно, нечувствительно к регистру)
Возвращает true, если строки слева и справа от оператора равны. В противном случае возвращает false. Может использоваться только для сравнения строк. Поддерживает подстановки и поиск в списках.
!= (не равно, чувствительно к регистру)
Возвращает true, если значения слева и справа от оператора не равны. В противном случае возвращает false. Подстановки не поддерживаются.
>= (больше или равно)
Возвращает true, если значение слева от оператора больше или равно значению справа. В противном случае возвращает false. При сравнении строк оператор использует лексикографический порядок, чувствительный к регистру.
> (больше)
Возвращает true, если значение слева от оператора больше значения справа. В противном случае возвращает false. При сравнении строк оператор использует лексикографический порядок, чувствительный к регистру.

= не поддерживается как оператор равенства. Используйте == или : вместо него.

Ключевые слова для сравнения шаблонов

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. Это сравнение не поддерживается и вернёт ошибку для всего запроса.

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

Вместо этого вы можете переписать запрос, чтобы сравнить оба поля process.parent.name и process.name со статическими значениями.

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

Логические операторы

and  or  not
and
Возвращает true только если условие слева и справа оба возвращают true. В противном случае возвращает false.
or
Возвращает true, если одно из условий слева или справа true. В противном случае возвращает false.
not
Возвращает true, если условие справа false.

Операторы поиска в списках

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~.

Математические операторы

+  -  *  /  %
+ (сложение)
Добавляет значения слева и справа от оператора.
- (вычитание)
Вычитает значение справа от оператора из значения слева.
* (умножение)
Умножает значения слева и справа от оператора.
/ (деление)

Делит значение слева от оператора на значение справа.

Если и делимое, и делитель являются целыми числами, операция деления (\) округляет любые возвращаемые числа с плавающей запятой до ближайшего целого числа вниз. Чтобы избежать округления, преобразуйте либо делимое, либо делитель в число с плавающей запятой.

Пример
Поле process.args_count — это целое числовое поле long , содержащее количество аргументов процесса.

Пользователь, вероятно, ожидает, что следующий запрос EQL будет соответствовать только событиям со значением поля process.args_count равным 4.

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

Однако запрос EQL соответствует событиям со значением поля process.args_count равным либо 3, либо 4.

Для событий со значением поля process.args_count равным 3, операция деления возвращает число с плавающей запятой 1.333..., которое округляется до 1.

Чтобы соответствовать только событиям со значением поля process.args_count равным 4, преобразуйте либо делимое, либо делитель в число с плавающей запятой.

Следующий запрос EQL изменяет целое число 4 на эквивалентное число с плавающей запятой 4.0.

process where ( 4.0 / process.args_count ) == 1
% (остаток от деления)
Делит значение слева от оператора на значение справа. Возвращает только остаток.

Соответствие любому условию

Чтобы соответствовать событиям только по категории события, используйте условие where true.

Например, следующий запрос EQL соответствует всем событиям file:

file where true

Чтобы соответствовать любому событию, можно объединить ключевое слово any с условием where true:

any where true

Необязательные поля

По умолчанию запрос EQL может содержать только поля, которые существуют в наборе данных, по которому вы выполняете поиск. Поле существует в наборе данных, если оно имеет явное, динамическое или временное сопоставление. Если запрос EQL содержит поле, которого нет, он возвращает ошибку.

Если вы не уверены, существует ли поле в наборе данных, используйте оператор ?, чтобы пометить поле как необязательное. Если необязательное поле не существует, запрос заменяет его значением null вместо возврата ошибки.

Пример
В следующем запросе поле user.id является необязательным.

network where ?user.id != null

Если поле user.id существует в наборе данных, по которому вы выполняете поиск, запрос соответствует всем событиям network, которые содержат значение поля user.id. Если поле user.id не существует в наборе данных, EQL интерпретирует запрос как:

network where null != null

В этом случае запрос не соответствует ни одному событию.

Проверка наличия поля

Чтобы соответствовать событиям, содержащим любое значение для поля, сравните поле с null с помощью оператора !=:

?my_field != null

Чтобы соответствовать событиям, не содержащим значения поля, сравните поле с null с помощью оператора ==:

?my_field == null

Строки

Строки заключены в двойные кавычки (").

"hello world"

Строки в одинарных кавычках (') не поддерживаются.

Символы экранирования в строке

При использовании в строке специальные символы, такие как возврат каретки или двойная кавычка ("), должны быть экранированы предшествующей обратной косой чертой (\).

"example \r of \" escaped \n characters"
Последовательность экранирования Литеральный символ

\n

Перевод строки (символ новой строки)

\r

Возврат каретки

\t

Табуляция

\\

Обратная косая черта (\)

\"

Двойная кавычка (")

Можно экранировать символы Юникода, используя шестнадцатеричную последовательность экранирования \u{XXXXXXXX}. Шестнадцатеричное значение может иметь длину от 2 до 8 символов и регистронезависимо. Значения, длина которых меньше 8 символов, дополняются нулями. Эти последовательности экранирования можно использовать для включения непечатаемых или символов справа налево (RTL) в ваши строки. Например, можно экранировать символ маркировки справа налево (RLM) как \u{200f}, \u{200F} или \u{0000200f}.

Символ одинарной кавычки (') зарезервирован для использования в будущем. Нельзя использовать экранированную одинарную кавычку (\') для литеральных строк. Используйте экранированную двойную кавычку (\").

Необработанные строки

Необработанные строки рассматривают специальные символы, такие как обратные косые черты (\), как литеральные символы. Необработанные строки заключены в три двойные кавычки (""").

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

Необработанная строка не может содержать три последовательные двойные кавычки ("""). Вместо этого используйте обычную строку с последовательностью экранирования \".

"String containing \"\"\" three double quotes"

Подстановочные знаки

Для сравнения строк с помощью оператора : или ключевого слова like можно использовать подстановочные знаки * и ? для соответствия определённым шаблонам. Подстановочный знак * соответствует нулю или более символам:

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"

Подстановочный знак ? соответствует ровно одному символу:

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"

Оператор : и ключевое слово like также поддерживают подстановочные знаки в поиске в списках:

my_field : ("doc*", "f*o", "ba?", "qux")
my_field like ("Doc*", "F*O", "BA?", "QUX")

Последовательности

Вы можете использовать последовательности EQL для описания и поиска упорядоченной серии событий. Каждый элемент последовательности — это категория события и условие события, заключённые в квадратные скобки ([ ]). События перечислены в хронологическом порядке, начиная с самого последнего.

sequence
  [ event_category_1 where condition_1 ]
  [ event_category_2 where condition_2 ]
  ...

Пример
Следующий запрос EQL по последовательности соответствует следующей серии событий:

  1. Начинается с события с:

    • Категорией события file
    • Значением поля file.extension равным exe
  2. За которым следует событие с категорией события process
sequence
  [ file where file.extension == "exe" ]
  [ process where true ]

with maxspan оператор

Вы можете использовать with maxspan, чтобы ограничить последовательность заданным интервалом времени. Все события в соответствующей последовательности должны произойти в течение этого интервала, начиная с временной метки первого события.

maxspan принимает аргументы временных значений.

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 минут с момента временной метки первого события.

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

Пропущенные события

Используйте !, чтобы соответствовать пропущенным событиям: событиям в заданном интервале времени, которые не соответствуют заданному условию.

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

Операторы пропущенных событий могут использоваться в начале, в конце и/или в середине последовательности в любом сочетании с положительными операторами. Последовательность может содержать несколько операторов пропущенных событий, но должна содержать по крайней мере один положительный оператор. with maxspan является обязательным, когда присутствуют операторы пропущенных событий.

Пример
Следующий запрос по последовательности находит события входа в систему, за которыми не следует событие выхода в течение 5 секунд.

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

by ключевое слово

Используйте ключевое слово by в запросе последовательности, чтобы соответствовать только событиям, которые имеют одинаковые значения, даже если эти значения находятся в разных полях. Эти общие значения называются ключами объединения. Если ключ объединения должен находиться в одном и том же поле во всех событиях, используйте sequence by.

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
  • События с значением поля file, равным значению поля file.path следующего события process.
sequence
  [ file where file.extension == "exe" ] by user.name, file.path
  [ process where true ] by user.name, process.executable

Поскольку поле user.name общее для всех событий в последовательности, его можно включить, используя sequence by. Следующая последовательность эквивалентна предыдущей.

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

Вы можете объединить sequence by и with maxspan, чтобы ограничить последовательность как значениями полей, так и временным интервалом.

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 минут) от первого соответствующего события
sequence by user.name with maxspan=15m
  [ file where file.extension == "exe" ]
  [ process where true ]

Дополнительные поля by

По умолчанию ключ объединения должен быть значением поля, которое не является null. Для разрешения null ключей объединения используйте оператор ? для обозначения поля by как необязательное. Это также полезно, если вы не уверены, содержит ли анализируемый вами набор данных поле by.

Пример
Следующий запрос последовательности использует sequence by для ограничения соответствующих событий до:

  • Событий с одинаковым значением поля process.pid, исключая null значения. Если поле process.pid отсутствует в анализируемом наборе данных, запрос возвращает ошибку.
  • Событий с одинаковым значением поля process.entity_id, включая null значения. Если событие не содержит поле process.entity_id, его значение поля process.entity_id считается null. Это относится даже в том случае, если поле process.pid отсутствует в анализируемом наборе данных.
sequence by process.pid, ?process.entity_id
  [process where process.name == "regsvr32.exe"]
  [network where true]

Ключевое слово until

Вы можете использовать ключевое слово until, чтобы указать событие истечения срока действия для последовательности. Если это событие истечения срока действия происходит между соответствующими событиями в последовательности, последовательность истекает и не считается совпадением. Если событие истечения срока действия происходит после соответствующих событий в последовательности, последовательность все еще считается совпадением. Событие истечения срока действия не включается в результаты.

sequence
  [ event_category_1 where condition_1 ]
  [ event_category_2 where condition_2 ]
  ...
until [ event_category_3 where condition_3 ]

Пример
В наборе данных содержатся следующие последовательности событий, сгруппированные по общим идентификаторам:

A, B
A, B, C
A, C, B

Следующий запрос EQL ищет в наборе данных последовательности, содержащие событие A, за которым следует событие B. Событие C используется как событие истечения срока действия.

sequence by ID
  A
  B
until C

Запрос соответствует последовательностям A, B и A, B, C, но не A, C, B.

Ключевое слово until может быть полезным при поиске последовательностей процессов в журнале событий Windows.

В Windows идентификатор процесса (PID) уникален только во время работы процесса. После завершения процесса его PID может быть повторно использован.

Вы можете искать последовательность событий с одинаковым значением PID, используя ключевые слова by и sequence by.

Пример
Следующий запрос EQL использует ключевое слово sequence by, чтобы соответствовать последовательности событий, которые имеют одинаковое значение поля process.pid.

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. Эти события указывают на то, что процесс был завершён.

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

Выражение with runs

Используйте выражение with runs, чтобы последовательно выполнять те же критерии событий в запросе последовательности. Например:

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

эквивалентно:

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 ]

Значение runs должно находиться в диапазоне от 1 до 100 (включительно).

Вы можете использовать выражение with runs с ключевым словом by. Например:

sequence
  [ process where event.type == "creation" ] by process.executable
  [ library where process.name == "regsvr32.exe" ] by dll.path with runs=3

Примеры

Вы можете использовать примеры EQL для описания и сопоставления хронологически неупорядоченного ряда событий. Все события в примере имеют одинаковое значение для одного или нескольких полей, которые указываются с помощью ключевого слова by (ключи объединения). Каждый элемент в примере — это категория события и условие события, заключенные в квадратные скобки ([ ]). События перечислены в порядке соответствия фильтрам.

sample by join_key
  [ event_category_1 where condition_1 ]
  [ event_category_2 where condition_2 ]
  ...

Пример
Следующий запрос EQL с помощью примера возвращает до 10 примеров с уникальными значениями для host. Каждый пример состоит из двух событий:

  1. Начинается с события с:

    • Категорией события file
    • Значением поля file.extension равным exe
  2. За которым следует событие с категорией события process
sample by host
  [ file where file.extension == "exe" ]
  [ process where true ]

Запросы с примерами не учитывают хронологический порядок событий. Выражения with maxspan и with runs, а также ключевое слово until не поддерживаются.

Функции

Вы можете использовать функции 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 для сопоставления расширений файлов:

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.

Эти изменения могут замедлить индексирование, но позволяют ускорить поиск. Пользователи могут использовать поле file.extension вместо нескольких вызовов функции endsWith:

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

Мы рекомендуем проверить и выполнить тестирование производительности любых изменений в индексировании перед развертыванием их в рабочей среде. См. Настройка для скорости индексирования и Настройка для скорости поиска.

Трубы

Трубы EQL фильтруют, агрегируют и пост-обрабатывают события, возвращаемые запросом EQL. Вы можете использовать трубы для сужения результатов запроса EQL или для повышения их специфичности.

Трубы разделяются символом (|).

event_category where condition | pipe

Пример
Следующий запрос EQL использует трубу tail для возврата только 10 самых последних событий, соответствующих запросу.

authentication where agent.id == 4624
| tail 10

Вы можете передать вывод одной команды обработки данных в другую. Это позволяет использовать несколько команд обработки данных с одним запросом.

Список поддерживаемых команд обработки данных см. в Справочнике по командам обработки данных.

Ограничения

EQL имеет следующие ограничения.

EQL использует параметр fields

EQL извлекает значения полей с помощью параметра fields API поиска. Любые ограничения на параметр fields также применяются к запросам EQL. Например, если параметр _source отключен для любого возвращаемого поля или на уровне индекса, значения получить невозможно.

Сравнение полей

Вы не можете использовать операторы сравнения EQL для сравнения одного поля с другим. Это относится даже в том случае, если поля изменены с помощью функции.

Поля типа текста не поддерживаются

Поиск EQL не поддерживает поля типа text. Чтобы выполнить поиск по полю типа text, используйте параметр Query DSL filter API поиска EQL.

Поиск EQL по вложенным полям

Вы не можете использовать EQL для поиска значений поля типа nested или подполей поля nested. Однако потоки данных и индексы, содержащие соответствия nested, в остальном поддерживаются.

Отличия от синтаксиса Endgame EQL

Синтаксис EQL Elasticsearch отличается от синтаксиса 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 не поддерживает:

    • Функции массивов:

      • arrayContains
      • arrayCount
      • arraySearch
    • Функцию match
    • Объединения
    • Ключевые слова, связанные с происхождением событий:

      • child of
      • descendant of
      • event of
    • Следующие команды обработки данных:

      • count
      • filter
      • sort
      • unique
      • unique_count

Как запросы последовательности обрабатывают совпадения

Запросы последовательностей не находят все потенциальные совпадения для последовательности. Этот подход слишком медленный и дорогостоящий для больших наборов данных событий. Вместо этого запрос последовательности обрабатывает ожидающие совпадения последовательности как конечный автомат:

  • Каждый элемент события в запросе последовательности является состоянием в автомате.
  • Только одна ожидающая последовательность может находиться в каждом состоянии одновременно.
  • Если две ожидающие последовательности находятся в одном состоянии одновременно, последняя последовательность перезаписывает предыдущую.
  • Если запрос включает by поля, запрос использует отдельный конечный автомат для каждого уникального значения поля by.
Пример

Набор данных содержит следующие события process в порядке возрастания хронологического времени:

{ "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 выполняет поиск в наборе данных:

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"]
sequence state machine

Для поиска совпадающих последовательностей запрос использует отдельные конечные автоматы для каждого уникального значения user.name. Основываясь на наборе данных, вы можете ожидать два конечных автомата: один для пользователя root и один для elkbee.

separate state machines

Ожидающие совпадения последовательностей перемещаются по состояниям каждого автомата следующим образом:

{ "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] |
// |  +-----------+     +-----------+     +------------+  |
// +------------------------------------------------------+

© 2023-2025 Elasticsearch
As of September 2024, Elasticsearch is available under a choice of three licenses: the Server Side Public License (SSPL), the Elastic License, or the AGPLv3 (OSI approved).
Elasticsearch and the Elasticsearch logo are trademarks of Elasticsearch B.V., registered in the U.S. and in other countries.
https://www.elastic.co/guide/en/elasticsearch/reference/8.17/eql-syntax.html

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API