Язык eXtraction and Processing: разработка корреляций без боли и страданий

20 минут
Дмитрий Федосов
Дмитрий Федосов
Старший специалист отдела обнаружения атак, Positive Technologies
Юлия Фомина
Юлия Фомина
Ведущий специалист отдела обнаружения атак, Positive Technologies
Для кого:
Специалисты по информационной безопасности, разработчики, аналитики SOC
Скиллы:
Корреляция событий, разработка контента, обнаружение атак
  • VSCode XP
  • Корреляция

Чем хорош eXtraction and Processing

Начнем с терминологии. eXtraction and Processing (XP) — созданный в Positive Technologies язык разработки правил нормализации, корреляции и обогащения. Они используются в MaxPatrol SIEM, PT XDR и SOLDR для обнаружения атак на основе анализа потока событий с конечных точек. VS Code — это IDE (integrated development environment) для разработки программ на классических языках: JavaScript, C#, Python и др. Инструмент позволяет добавить поддержку произвольного языка с помощью языковых расширений. Реализовав расширение VSCode XP, мы получили возможность использовать VS Code для разработки контента на XP.

Почему именно eXtraction and Processing:

  1. Запрос со стороны сообщества на экспертную открытость вокруг языка.
  2. Простой текстовый формат и подробная документация.
  3. Наличие опыта и знаний, которыми мы готовы делиться.
  4. Позволяет описать сложную логику обнаружения.
  5. Публичные инструменты, позволяющие вести разработку контента даже без соответствующих ИБ-продуктов.
  6. Базовые правила нормализаций для Windows и Linux (auditd) и общедоступные правила, которые будут пополняться.

Подчеркнем, что XP можно использовать, даже если у вас нет соответствующих ИБ-решений. Прежде всего это универсальный способ описания экспертизы по обнаружению атак. А если хотите проверить, сработает ли правило на определенные события, достаточно вручную извлечь их из журналов (например, Windows Event Log), скопировать в расширение, запустить корреляцию и получить набор сработавших правил.

Начнем с нормализации событий в XP.

1.jpg
Рисунок 1. Нормализация события в XP

В левом столбце на рис. 1 показана запись в журнале Windows в формате XML (17 Sysmon). Справа — нормализованное событие в формате нашей таксономии: все поля унифицированы, приведены к единому стандарту.

Унификация — это всегда полезно. Она позволяет осуществлять поиск событий без привязки к формату журналов конкретного вендора или продукта. Например, по фильтру subject.account.name = “pushkin” and action = “login” можно найти все приложения, к которым осуществлял доступ данный пользователь.

Поля разделены на группы. Например, event_src — группа, описывающая источник события. В ней есть event_src.host — имя хоста, event_src.subsys — источник события (журнал или подсистема), event_src.vendor — вендор источника событий. Ниже находятся поля группы subject.account, содержащие информацию о пользователе. Еще один важный блок — subject.process, включающий идентификатор процесса, его имя и директорию, откуда он был запущен.

2.jpg
Рисунок 2. Пример простейшей корреляции на языке ХР

Рассмотрим пример простейшей корреляции для выявления манипуляции задачами в Windows. На рис. 2 инструкция event определяет событие, которое нужно отфильтровать из потока. Вложенная инструкция filter определяет условие, по которому будут отбираться события, а key показывает, как будут разделяться различные потоки, подходящие под фильтр и имеющие разный набор значений полей, указанных в key.

Кроме того, здесь можно использовать макросы. Они напоминают функции в классических языках программирования, определяются ключевым словом filter и хранятся в отдельных файлах. В них выносят повторяющиеся в фильтрах различных корреляций условия для повторного использования, что позволяет уменьшить дублирование кода фильтра и упростить его. Например, макрос NotFromCorrelator определяет, что среди событий будут отобраны только нормализованные, а корреляционные — пропущены. ProcessStart_Windows_any() показывает, что нам интересны именно события запуска процессов в Windows, события с Event ID: 1 (sysmon), 4688, 592. Также в макросы можно передавать параметры, что позволяет сделать код фильтра еще проще и понятнее.

Фильтр осуществляет логические проверки, которые помогают найти запущенный процесс — в нашем случае schtasks.exe (поле object.process.name). Поле object.process.cmdline содержит параметры процесса schtasks.exe, среди которых мы отбираем create, change, run, delete, end с помощью регулярного выражения. В результате мы получаем простейший детект: когда случится соответствующее событие, оно будет нормализовано и успешно пройдет фильтр, а затем коррелятор породит корреляционное событие, которое визуализируется в продукте.

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

Еще одним преимуществом языка XP является простота настройки окружения по работе с ним через расширение VSCode XP. Нужно скачать релиз из репозитория XP Knowledge Base Toolkit, сделать клон репозитория c публичными правилами, и вуаля. Расширение лежит в магазине VS Code — ищите по ключевым словам «correlation, xplang, siem». Единственное, что потребуется сделать после установки — указать в настройках путь до Knowledge Base Toolkit. Буквально пара минут — и можно разрабатывать контент, изучать атаки и вносить свой вклад в сообщество.

Подробнее о работе с eXtraction and Processing мы рассказали на докладе «VSCode XP: корреляции без боли и страданий» и на воркшопе «Лучшие практики по созданию правил на языке XP».

Почему мы выбрали VS Code

Самый простой ответ — потому что большинство наших экспертов уже использовали эту IDE и имели соответствующий опыт. Кроме того, если погрузиться в функционал VSCode, можно выделить следующие преимущества этого инструмента:

  1. Поддержка Language server protocol (LSP), возможность легко расширить поддержку для редакторов Eclipse, Emacs, Notepad++, Sublime Text и других.
  2. Расширения поддерживают произвольные WebView, что позволяет реализовывать практически любые функции нативных приложений.
  3. Большой магазин существующих расширений: GitLens, Spell Checker и т. д.
  4. Кроссплатформенность (Windows, Linux, macOS).
  5. Доступность веб-версии через Docker.
  6. Множество цветовых тем на любой вкус и цвет.

Кроме того, при написании экспертизы мы хотели использовать все плюшки, которые уже давно есть у разработчиков: подсветка синтаксиса, автодополнение, сниппеты и многое другое. VS Code позволил нативно их реализовать.

3.jpg
Рисунок 3. Интерфейс VSCode XP

В левой части интерфейса VSCode XP (см. рис. 3) представлено дерево контента. Open-xp-rules — ключевая директория системы, своего рода база знаний. В common находятся макросы, а ниже в packages — пакеты экспертизы. Обычно в директориях пакетов есть поддиректории, которые определяют тип содержащегося в них контента, например correlation_rules, enrichment_rules, normalization_formulas и др. Для упрощения поиска правил корреляции мы раскладываем их по техникам согласно классификации MITRE ATT&CK. На рис. 3 показаны несколько правил: ProxyNotShell (Initial Access), Schtasks_Commandline (Execution) и всеми любимый Mimikatz (Credential Access).

Пять правил работы с контентом в Positive Technologies

  • Пишем тесты. Всегда пишем тесты. Любое правило не существует, если у него нет тестов; это значит, что перед вами какой-то код, который, возможно, работает, но, скорее всего, нет.
  • Применяем test-driven development (TDD). Проводим разные варианты атак, собираем нужные события, на основе которых делаем тесты. После этого разрабатываем правило и запускаем тесты для проверки. Если все тесты прошли — правило работает, если нет — нужно исправить ошибки и доработать правило.
  • Используем систему контроля версий. В нашем случае Git, но это не принципиально. Главное — иметь удобный инструмент для хранения и управления контентом.
  • Используем feature branch workflow. Для создания правила от основной ветки разработки отводится feature branch, в которой создаются и исправляются правила. Затем автор заводит merge request в основную ветку, и его проверяют два других эксперта. После ревью ветка вливается в основную ветку разработки.
  • Continuous integration для запуска тестов. CI поможет запустить все тесты (нормализаций, корреляций и обогащений) и через определенное время выдаст вердикт: все работает, можно собирать пакет и отдавать клиентам.

Как писать правила: разбираем на простейшем примере Mimikatz

Работа начинается со сбора событий. Предположим, у вас есть тестовая инфраструктура с настроенным аудитом. Если события заведены в MaxPatrol SIEM, можно скопировать нужные через интерфейс. Также можно копировать события в формате XML из Event Viewer или брать их из журналов Syslog и Auditd (скоро).

Следующий важный шаг — предварительная корреляция собранных событий, которая позволит понять, имеются ли какие-то сработки на данную последовательность. Здесь может быть несколько вариантов развития событий.

  • Сработок нет. Если вы не можете задетектить хакерскую утилиту или атаку, пора разработать правило для выявления данной активности.
  • Сработки есть, и по ним имеются адекватные данные. Поздравляем — кейс покрыт, дополнительные правила не потребуются.
  • Есть ложные сработки (false positive). Если видите, что сработка не релевантна вашим событиям, необходимо скорректировать правило.
4.jpg
Рисунок 4. Корреляция событий

В нашем случае (см. рис. 4) VSCode XP тонко намекает, что сработок нет, значит, пора разрабатывать правило. Для удобства пользователей мы реализовали механизм создания правил из шаблонов: открываете раздел, вводите название правила и выбираете наиболее близкий из списка.

5.jpg
Рисунок 5. Шаблоны в VSCode XP

Например, шаблон For_Profiling подходит, если вы хотите разработать правила, профилирующие доступ к какой-либо системе, например GitLab, Teamcity или 1C_Enterprise. Следом идет группа шаблонов для Unix-систем. Все они привязаны к основному событию, на основании которого вы планируете писать детект. Например, сетевое подключение, запуск процесса и др. Далее следует группа шаблонов корреляций для Windows, содержащих в качестве основных событий загрузку DLL или EXE в адресное пространство процесса, создание потока в другом процессе, выполнение команд Powershell и т. д. Кроме того, существуют универсальные шаблоны, которые можно использовать, если не подошли другие. В случае с Mimikatz выбираем Windows_Process_Start.

6.jpg
Рисунок 6. Шаблон правила Mimikatz

У корреляционного события есть несколько обязательных полей, их можно задавать в on, но хорошая практика — делать это в блоке emit. Остановимся на блоке emit нашего шаблона (см. рис. 6). $correlation_type отвечает за типы корреляционных событий. Основные — event и incident, также есть subrule и draft. Субъект активности — это account; действие, которое он производит, — start; то, что он запускает, — object; статус действия — success. Поле $importance отвечает за важность срабатывания — она может варьироваться для разных типов корреляционных событий. Например, если обнаруженная атака действительно угрожает инфраструктуре, нужно использовать «high». В поля группы $category вносится информация о категории детекта, тактике и технике MITRE ATT&CK, которые соответствуют данной сработке.

7.jpg
Рисунок 7. Директива emit, адаптированная для детекта Mimikatz

Далее добавляем smoke-тесты, которые покажут, что мы подготовили полноценную заготовку для правила. Они нужны на этапе разработки правила для проверки отсутствия синтаксических ошибок, заполнения всех обязательных полей и наличия на выходе корреляционных событий (см. рис. 8).

8.jpg
Рисунок 8. Пример smoke-теста

Для этого:

  1. Запускаем с разными параметрами утилиту, активность которой хотим детектировать, и собираем группы сырых событий (raw events) из журналов аудита или ИБ-продуктов.
  2. Группы событий добавляем в поле Сырые события у разных тестов и оборачиваем в нужный конверт (технические метаданные события).
  3. В поле Условия прохождения теста автоматически добавляется нужный код:

expect 1 {"correlation_name": "Mimikatz"}

Если кратко, код означает следующее: после поступления собранных сырых событий с узла, их нормализации, корреляции и обогащения на выходе будет получено одно событие с полем correlation_name, равным Mimikatz. То есть будет сработка корреляционного правила с именем Mimikatz.

9.jpg
Рисунок 9. Нормализованное событие Event ID 4688

Кроме того, в окне интеграционных тестов есть кнопка Нормализовать событие. После ее нажатия исходное сырое событие превратится в нормализованное (внезапно). Теперь видно, какие поля и значения нужно использовать в фильтре правила. В нашем случае Windows-событие Event ID 4688 будет выглядеть как msgid: 4688.

Начнем с самого простого — в значении поля object.process.fullpath попробуем найти «Mimikatz». Берем шаблон, добавляем в него вызов внутренней функции языка regex. Передаем ей приведенное к lower-кейсу значение object.process.fullpath для избежания неоднозначности пути в ОС Windows. Вторым параметром передаем регулярное выражение, третьим — номер группы, которая извлекается из регулярного выражения и является возвращаемым значением функции regex.

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

10.jpg
Рисунок 10. Подсказка по параметрам функции regex

Следующее событие, которое мы нормализуем, — EventID 1 (Sysmon). Может получиться так, что Script kiddie, который раньше просто качал Mimikatz с GitHub, переименует его. Беспокоиться не о чем: версия с GitHub все равно содержит метаданные (object.process.meta), в которых есть description, где черным по белому написано: это Mimikatz. Для решения этой задачи достаточно расширить условия детекта.

11.jpg
Рисунок 11. Расширяем условия детекта

Если хакер не только переименовал Mimikatz, но и заменил метаданные (в результате чего Mimikatz превратился, к примеру, в Bibikatz), заданными ранее условиями мы его уже не задетектим. Однако остаются параметры: их реже прячут или переименовывают, потому что для этого нужно обладать опытом разработки на С++. Снова расширяем условия детекта.

12.jpg
Рисунок 12. Еще больше расширяем условия детекта

Фактически мы проверяем object.process.cmdline (см. рис. 12) на предмет ключевых слов, которые чаще всего используются Mimikatz. Если они есть в cmdline, это зловредная активность.

Прохождение smoke-тестов означает, что мы почти сделали простейшее правило по выявлению Mimikatz. Заметим, что, если бы мы писали правило с нуля, а не пользовались шаблоном, нам пришлось бы сделать еще один шаг: пробросить в корреляционное событие (присвоить корреляционному событию) значения наиболее важных и репрезентативных полей из исходного события (событий) в инструкции on. Обычно это достаточно большой кусок однообразного кода: например, на рис. 13 показан проброс только части полей события старта процесса в ОС Windows.

13.png
Рисунок 13. Проброс полей в корреляционное событие

Пора переходить от smoke-тестов к полноценным интеграционным. Хорошая практика — помимо correlation_name проверять и другие результирующие поля правила, которые мы ранее пробросили из событий в блоках on. Для их формирования необходимо в каждом тесте нормализовать сырые события и получить ожидаемое с помощью одноименной кнопки (см. рис. 14).

14.jpg
Рисунок 14. Получение ожидаемого события для интеграционных тестов

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

15.jpg
Рисунок 15. От smoke-тестов к интеграционным

Еще раз запускаем все тесты и проверяем, что они проходят. Отлично — мы готовы финишировать. Осталось несколько мелочей: добавить локализации (одну или несколько), заполнить метаданные (автор правила, описание выявляемых сценариев, необходимые события и т. д.), закоммитить правило и завести merge request с привлечением опытных ревьюверов.

Все готово, вы великолепны!

Если считаете, что детектировать Mimikatz в 2023 г. — это моветон, посмотрите, как написать с помощью VSCode XP чуть более сложное и актуальное правило на уязвимость ProxyNotShell. Это пример того, как два события мало о чем говорят по отдельности, но вместе позволяют обнаружить эксплуатацию опасной уязвимости.

СТАТЬИ ПО ТЕМЕ

Подписаться на обновления!Подписаться на обновления!Подписаться на обновления!Подписаться на обновления!Подписаться на обновления!Подписаться на обновления!Подписаться на обновления!Подписаться на обновления!Подписаться на обновления!Подписаться на обновления!Подписаться на обновления!Подписаться на обновления!
Подписаться на обновления!Подписаться на обновления!Подписаться на обновления!Подписаться на обновления!Подписаться на обновления!Подписаться на обновления!Подписаться на обновления!Подписаться на обновления!Подписаться на обновления!Подписаться на обновления!Подписаться на обновления!Подписаться на обновления!