Создание пользовательской политики

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

Структура политики

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

Table 1. Блоки политики
Блок Описание Обязательный

Policy

Основные атрибуты политики

Да

Requirements

Проверяемые требования

Нет

Variables

Переменные для использования в требованиях

Нет

Checks

Проверки политики

Да

Поля блоков политики

Каждый блок политики имеет свои поля настроек.

Table 2. Блок Policy
Поле Обязательность Тип Допустимые значения Описание

id

Да

Строка

Любая строка

ID политики

file

Да

Строка

Любая строка

Имя файла политики

name

Да

Строка

Любая строка

Название политики

description

Да

Строка

Любая строка

Краткое описание

references

Нет

Массив строк

Любая строка

Ссылки на внешние источники или документацию

Table 3. Блок Requirements
Поле Обязательность Тип Допустимые значения Описание

title

Да

Строка

Любая строка

Название требования

description

Да

Строка

Любая строка

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

condition

Да

Строка

Любая строка

Условие для проверки списка правил

rules

Да

Массив строк

Любая строка

Список правил для проверки

Table 4. Блок Variables
Поле Обязательность Тип Допустимые значения Описание

variable_name

Да

Массив строк

Любая строка

Список переменных

Table 5. Блок Checks
Поле Обязательность Тип Допустимые значения Описание

id

Да

Числовой

Любое целое число

ID проверки

title

Да

Строка

Любая строка

Название проверки

description

Нет

Строка

Любая строка

Описание проверки

rationale

Нет

Строка

Любая строка

Причины проведения проверки

remediation

Нет

Строка

Любая строка

Рекомендации при обнаружении отклонений

compliance

Нет

Массив массивов строк

Любая строка

Стандарты и политики безопасности проверки

references

Нет

Массив строк

Любая строка

Ссылки на внешние источники или документацию

condition

Да

Строка

all, any, none

Условие успешного выполнения проверки

rules

Да

Массив строк

Любая строка

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

Поле id в блоках Policy и Checks должно быть уникальным среди файлов политики.

Пример политики

policy:
id: "unix_audit"
file: "unix_audit.yml"
name: "Системный аудит для основанных на Unix систем"
description: "Руководство по установке безопасной конфигурации для систем, основанных на Unix."
references:
- https://www.ssh.com/ssh/

requirements:
title: "Проверка наличия SSH сервиса и файлов, связанных с паролем, в системе"
description: "Требования к запуску сканирования в соответствии с политикой для систем, основанных на Unix."
condition: any
rules:
- 'f:$sshd_file'
- 'f:/etc/passwd'
- 'f:/etc/shadow'

variables:
$sshd_file: /etc/ssh/sshd_config
$pam_d_files: /etc/pam.d/common-password,/etc/pam.d/password-auth,/etc/pam.d/system-auth,/etc/pam.d/system-auth-ac,/etc/pam.d/passwd

checks:
- id: 3000
title: "Усиление безопасности SSH: порт не должен быть 22"
description: "Демон ssh не должен прослушивать порт 22 (значение по умолчанию) для входящих соединений."
rationale: "Изменяя порт по умолчанию, вы можете уменьшить количество успешных атак от зомби-ботов; атакующий или бот, выполняющий сканирование портов, может быстро определить ваш SSH порт."
remediation: "Измените значение опции Port в файле sshd_config."
compliance:
- pci_dss: ["2.2.4"]
- nist_800_53: ["CM.1"]
condition: all
rules:
- 'f:$sshd_file -> !r:^# && r:Port && !r:\s*\t*22$'

- id: 3001
title: "Усиление безопасности SSH: протокол должен быть установлен в значение 2"

Проверки

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

Условие проверки

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

  • all — проверка оценивается как:

    • Успешно — если все ее правила выполнены;

    • Неуспешно — если хотя бы одно из ее правил не выполнено.

  • any — проверка оценивается как:

    • Успешно — если хотя бы одно из ее правил выполнено;

    • Неуспешно — если ни одно из ее правил не выполнено.

  • none — проверка оценивается как:

    • Успешно — если ни одно из ее правил не выполнено;

    • Неуспешно — если выполнено хотя бы одно из ее правил.

Существуют определенные ситуации, при которых вышеупомянутые агрегаторы оцениваются как Неприменимо:

  • all — проверка оценивается как Неприменимо, если любое ее правило возвращает Неприменимо и ни одно из ее правил не возвращает Неуспешно.

  • any — проверка оценивается как Неприменимо, если ни одно из ее правил не оценивается как Успешно и любое ее правило возвращает Неприменимо.

  • none — проверка оценивается как Неприменимо, если ни одно из ее правил не оценивается как Успешно и любое ее правило возвращает Неприменимо.

Table 6. Результаты проверки
Условие \\ Оценка правила Успешно Неуспешно Неприменимо Результат

all

да

нет

нет

Успешно

all

*

нет

да

Неприменимо

all

*

да

*

Неуспешно

any

да

*

*

Успешно

any

нет

да

нет

Неуспешно

any

нет

*

да

Неприменимо

none

да

*

*

Неуспешно

none

нет

*

да

Неприменимо

none

нет

да

нет

Успешно

* — этот результат не влияет на итоговый показатель проверки.

Правила проверки

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

Table 7. Типы местоположений
Тип Символ

Файл

f

Директория

d

Процесс

p

Команды

c

Реестр (только для Windows)

r

Table 8. Операторы для проверки содержимого
Операция Оператор Пример

Точное соответствие

Нет оператора

f:/file -> CONTENT

Регулярное выражение

r:

f:/file -> r:REGEX

Числовое сравнение

n:

f:/file -> n:REGEX_WITH_CAPTURE_GROUP compare <= VALUE

Table 9. Операторы для числового сравнения:
Арифметический оператор Оператор Пример

Меньше

<

n:SomeProperty (\d) compare < 42

Меньше или равно

n:SomeProperty (\d) compare <= 42

Равно

==

n:SomeProperty (\d) compare == 42

Не равно

!=

n:SomeProperty (\d) compare != 42

Больше или равно

>=

n:SomeProperty (\d) compare >= 42

Больше

>

n:SomeProperty (\d) compare > 42

Для отрицания условия в правиле используйте not:

not f:/some_file -> some_text
Процесс поддерживает только проверки на существование, а Команда — только проверки содержимого.

Правила проверки на существование

Чтобы создать правило проверки на существование, не требуется использовать операторы содержимого. Формат такого правила:

RULE_TYPE:target

Примеры:

  • f:/etc/sshd_config — проверка наличия файла /etc/sshd_config.

  • d:/etc — проверка наличия директории /etc.

  • not p:sshd — отрицание наличия процесса sshd (правило Неуспешное, если процесс найден).

  • r:HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\Lsa — проверка наличия ключа реестра HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\Lsa.

  • r:HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\Lsa -> LimitBlankPasswordUse — проверка наличия значения LimitBlankPasswordUse в указанном ключе реестра.

Правила проверки содержимого

Формат правила проверки содержимого:

RULE_TYPE:target -> CONTENT_OPERATOR:value
  • Проверка содержимого ограничивается строкой.

  • Соблюдайте расстановку пробелов вокруг -> и compare.

  • Если цель правила проверки содержимого отсутствует, результат – Неприменимо.

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

f:/etc/ssh_config -> !r:PermitRootLogin
Не рекомендуется чрезмерное использование инверсии. Например, правило f:/etc/ssh_config → !r:PermitRootLogin будет оценено как Успешно, если обнаружит строку без PermitRootLogin.

Операторы проверки содержимого могут комбинироваться через &&:

f:/etc/ssh_config -> !r:^# && r:Protocol && r:2

Это правило оценивается как Успешно, если строка начинается не с #, содержит Protocol и 2.

  • Учитывайте пробелы вокруг &&.

  • Порядок выполнения тестов через && не определен.

Примеры:

  • c:systemctl is-enabled cups -> r:^enabled — проверяет наличие строки, начинающейся на enabled, в выводе команды.

  • f:$sshd_file +→+ n:^\s*MaxAuthTries\s*\t*(\d+) compare +⇐+ 4+ — значение MaxAuthTries не должно превышать 4.

  • r:HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\Lsa -> LimitBlankPasswordUse -> 1 — значение LimitBlankPasswordUse равно 1.

Примеры правил

В следующих примерах рассматривается каждый тип правил.

  1. Синтаксис правил для файлов:

    • Проверить существование файла:
      f:/путь_к_файлу

    • Проверить отсутствие файла:
      not f:/путь_к_файлу

    • Проверить содержимое файла (полное совпадение строки):
      f:/путь_к_файлу -> содержимое

    • Проверить содержимое файла по регулярному выражению:
      f:/путь_к_файлу -> r:РЕГУЛЯРНОЕ_ВЫРАЖЕНИЕ

    • Проверить числовое значение:
      f:/путь_к_файлу -> n:РЕГУЛЯРНОЕ_ВЫРАЖЕНИЕ(\d+) compare <= Число

  2. Синтаксис правил для директорий:

    • Проверить существование директории:
      d:/путь/к/директории

    • Проверить наличие файла в директории:
      d:/путь_к_директории -> файл

    • Проверить наличие в директории файлов, соответствующих регулярному выражению:
      d:/путь_к_директории -> r:^файлы

    • Проверить на содержимое файлы, соответствующие file_name:
      d:/путь_к_директории -> имя_файла -> содержимое

  3. Синтаксис правил для процессов:

    • Проверить выполнение процесса:
      p:имя_процесса

    • Проверить невыполнение процесса:
      not p:имя_процесса

  4. Синтаксис правил для команд:

    • Проверить вывод команды:
      c:команда -> вывод

    • Проверить вывод команды с использованием регулярного выражения:
      c:команда -> r:РЕГУЛЯРНОЕ_ВЫРАЖЕНИЕ

    • Проверить числовое значение:
      c:команда -> n:РЕГУЛЯРНОЕ_ВЫРАЖЕНИЕ_С_ГРУППОЙ_ЗАХВАТА compare >= число

  5. Синтаксис правил для реестра Windows:

    • Проверить существование реестра:
      r:путь_к_реестру

    • Проверить существование ключа реестра:
      r:путь_к_реестру -> ключ

    • Проверить содержимое ключа реестра:
      r:путь_к_реестру -> ключ -> содержимое

  6. Составные правила:

    • Проверить наличие строки, которая не начинается с # и содержит Port 22:
      f:/etc/ssh/sshd_config -> !r:^# && r:Port\.+22

    • Проверить отсутствие строки, которая не начинается с # и содержит Port 22:
      not f:/etc/ssh/sshd_config -> !r:^# && r:Port\.+22

  7. Другие примеры:

    • Проверка содержимого файла (полное совпадение строки):
      f:/proc/sys/net/ipv4/ip_forward -> 1

    • Проверка наличия файла:
      f:/proc/sys/net/ipv4/ip_forward

    • Проверка выполнения процесса:
      p:avahi-daemon

    • Проверка значения в реестре:
      r:HKEY_LOCAL_MACHINE\System\CurrentControlSet\Services\Netlogon\Parameters -> MaximumPasswordAge -> 0

    • Проверка наличия файлов в директории:
      d:/home -> ^.mysql_history$

    • Проверка существования директории:
      d:/etc/mysql

    • Проверка текущей конфигурации sshd на максимальное разрешенное количество попыток аутентификации:
      c:sshd -T -> !r:^\s*maxauthtries\s+4\s*$

    • Проверка, что root — единственная учетная запись с UID 0:
      f:/etc/passwd +→+ !r:^# && !r:^root: && r:^\w+:\w+:0:

Переменные

Переменные задаются в блоке переменных. Их имена предваряются символом $.

Примеры:

  • $list_of_files: /etc/ssh/sshd_config, /etc/sysctl.conf, /var/log/dmesg

  • $list_of_folders: /etc, /var, /tmp

  • $program_name: apache2

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

f:$list_of_files -> r:^Content to be found
c:systemctl is-enabled $program_name -> r:^enabled

Ограничений на количество переменных в правиле нет.