Docs
Личный кабинетЛК

Синтаксис запросов


В данном разделе описаны правила и синтаксис для составления задач на сканирование.

Основы

Для запуска сканирования необходимо составить задание для выполнения или использовать уже готовый шаблон. Используется формат Yaml.

Пример:

tasks:
- uses: tcp/probe@v1
default:
ports:
- 1-65535
runPolicy: always
- uses: http@v1
events:
- event: tcp/probe@v1
mutate:
port: ${{ value.port }}
scheme: '${{ value.isTls ? "https": "http" }}'
condition: value.banner == ""
default:
port: 80
runPolicy: triggered

Строение запроса

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

Важно! Все задачи и события запускаются в порядке их указания сверху вниз.

uses - обязательное поле в рамках задачи, обозначает модуль (задачу), который вызывается в рамках сканирования.

runPolicy - обязательное поле в рамках задачи. Поле может принимать значения always (запускается всегда) и triggered (запускается по какому-либо событию).

default - определяет настройки по умолчанию, которые будут применяться для задачи.

events - используется для определения событий, которые должны произойти для запуска текущей задачи (uses). Применяется если свойство runPolicy выставлено в triggered.

condition - логическое условие для запуска текущей задачи (uses). Пример: value.port == 22 - проверяется, что порт равен 22.

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

Мутации

Мутацией является изменение значений переменных в ходе выполнения задачи. Это позволяет динамически манипулировать значениями, чтобы они соответствовали нужным параметрам.

mutate - свойство, которое позволяет изменить параметры задачи перед её выполнением.

Пример:

- uses: http@v1
events:
- event: tcp/probe@v1
mutate:
port: ${{ value.port }}
scheme: '${{ value.isTls ? "https": "http" }}'
condition: value.banner == ""
default:
port: 80
runPolicy: triggered

В данном случае это означает, что значения переменных port и scheme задачи http@v1 будут изменены перед ее запуском. Значения параметров будут взяты из задачи tcp/probe@v1.

value в примере относится к тому модулю, в котором используется. В данном примере ${{ value.port }} value объект относится к tcp/probe@v1. Через объект value можно использовать любые доступные поля модуля. Подробнее какие поля доступны для использования можно посмотреть в соответствующей документации к модулю в разделе Результат сканирования.

Матрицы

Матрица — это способ автоматического создания комбинаций значений для нескольких параметров, что позволяет выполнять один и тот же шаг с разными входными данными. Используется для параллельной обработки множества вариантов, не нужно вручную прописывать каждый шаг для каждого варианта.

В основном матрицы используются для выполнения задач с параметрами - списками.

Пример:

events:
- event: tcp/probe@v1
matrix:
probe: ${{ value.probes }}
mutate:
port: ${{ value.port }}
probe: ${{ matrix.probe }}
condition: len(value.probes) > 0

Оператор матрица matrix создает матрицу значений для переменной probe. Значения для матрицы берутся из value.probes, которые были получены в предыдущем шаге. value.probes — это список (или массив), содержащий несколько значений. Матрица работает следующим образом:

  • Каждый элемент в списке value.probes будет обработан отдельно.
  • Когда матрица с параметром probe создается, она проходит через все элементы в value.probes (например, если value.probes содержит [1000, 2000, 3000], то для каждого из этих значений будет выполнен отдельный шаг).
  • Для каждого элемента из value.probes будет создаваться новый набор значений для параметров, который будет передан в mutate.

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

Например:

  • В первом проходе probe будет равно 1000.
  • Во втором проходе probe будет равно 2000.
  • В третьем проходе probe будет равно 3000.
  • Одновременно port остается таким же, как изначально заданное значение в value.port.

Используемые операторы

КатегорияОператоры
Арифметические+, -, *, /, % (остаток от деления), ^ или ** (возведение в степень)
Сравнение==, !=, <, >, <=, >=
Логическиеnot или !, and или &&, or или ||
Условные?: (тернарный оператор), ?? (оператор сравнения с nil)
Доступ к элементам[], ., ?., in
Строковые+ (конкатенация), contains (содержит), startsWith (начинается с), endsWith (заканчивается на)
Регулярные выраженияmatches (сопоставление регулярному выражению)
Конвейер|

Доступ к элементам

Поля структур и элементы карт (maps) могут быть доступны с помощью оператора . или оператора []. Следующие два выражения эквивалентны:

value.port
value["port"]

Элементы массивов можно получать с помощью оператора []. Поддерживаются отрицательные индексы, где -1 означает последний элемент.

array[0] // первый элемент
array[-1] // последний элемент

Оператор in можно использовать для проверки наличия элемента в массиве или карте.

"192.168.1.2" in ["192.168.1.2", "10.10.0.123"]
"192.168.1.2" in {"ipv4": "192.168.1.2", "interface": "lo0"}

Опциональная цепочка

Оператор ?. используется для доступа к полю объекта или элементу карты (map) без необходимости проверять, является ли объект или карта nil. Если объект или карта равны nil, результатом выражения также будет nil.

value.request?.port
value.request != nil ? value.request.port : nil

Сравнение с nil

Оператор ?? используется для возврата левого операнда, если он не nil, в противном случае возвращается правый операнд. Следующие два выражения эквивалентны:

value.request?.port ?? 80
value.request != nil ? value.request.port : 80

Оператор конвейера

Оператор | используется для передачи результата выражения слева в качестве первого аргумента функции справа. Следующие два выражения эквивалентны:

value.title | lower() | split(" ")
split(lower(value.title), " ")

Строковые функции

trim(str[, chars])

Удаляет пробелы с обоих концов строки str. Если передан необязательный аргумент chars, он указывает строку с набором символов, которые нужно удалить.

trim(" Title ") == "Title"
trim("__Title__", "_") == "Title"

upper(str)

Преобразует все символы в строке str в верхний регистр.

upper("title") == "TITLE"

lower(str)

Преобразует все символы в строке str в нижний регистр.

lower("TITLE") == "title"

split(str, delimiter[, n])

Разбивает строку str по указанному разделителю delimiter и возвращает массив подстрок.

split("path/to/site", "/") == ["path", "to", "site"]
split("path/to/site", ",", 2) == ["path", "to,site"]

replace(str, old, new)

Заменяет все вхождения подстроки old в строке str на new.

replace("param=bad_value", "bad_value", "good_value") == "param=good_value"

hasPrefix(str, prefix)

Возвращает true, если строка str начинается с указанного префикса prefix.

hasPrefix("OpenSSH_9.2", "OpenSSH") == true

hasSuffix(str, suffix)

Возвращает true, если строка str заканчивается на указанный суффикс suffix.

hasSuffix("OpenSSH_9.2", "9.2") == true

Числовые функции

max(n1, n2)

Возвращает максимальное из двух чисел n1 и n2.

max(5, 7) == 7

min(n1, n2)

Возвращает минимальное из двух чисел n1 и n2.

max(5, 7) == 5

abs(n)

Возвращает абсолютное значение числа n.

abs(-5) == 5

round(n)

Возвращает ближайшее целое число, округляя в большую сторону при значении 0.5.

round(1.5) == 2.0

Функции для массивов

all(array, predicate)

Возвращает true, если все элементы удовлетворяют выражению. Если массив пуст, возвращает true.

all(value.cookies, {.key contains "host"})

any(array, predicate)

Возвращает true, если какие-либо элементы удовлетворяют выражению. Если массив пуст, возвращает false.

any(value.cookies, {.key startsWith "host"})

one(array, predicate)

Возвращает true, если ровно один элемент удовлетворяет выражению. Если массив пуст, возвращает false.

one(value.cookies, {.key == "host.local"})

none(array, predicate)

Возвращает true, если все элементы не удовлетворяют выражению. Если массив пуст, возвращает true.

none(value.cookies, {.key == "host.com"})

filter(array, predicate)

Возвращает новый массив путем фильтрации элементов массива по выражению.

filter(value.publicKeys, .type startsWith "rsa-")

find(array, predicate)

Находит первый элемент в массиве, удовлетворяющий выражению.

find([1, 2, 3, 4], # > 2) == 3

count(array[, predicate])

Возвращает количество элементов, удовлетворяющих выражению. Следующие два выражения эквивалентны:

count(value.publicKeys, .type == "ssh-rsa")
len(filter(value.publicKeys, .type == "ssh-rsa"))

Разные функции

len(v)

Возвращает длину массива, карты или строки.

len([1, 2, 3]) == 3
len({"ipv4": "192.168.1.2", "interface": "lo0"}) == 2
len("Title") == 5

get(v, index)

Извлекает элемент по указанному индексу из массива или карты v. Если индекс выходит за пределы диапазона, возвращает nil. Или ключ не существует, возвращает nil.

get([1, 2, 3], 1) == 2
get({"ipv4": "192.168.1.2", "interface": "lo0"}, "interface") == "lo0"
Назад
Расписания
Вперед
Шаблоны