Всем привет! На связи Михаил Максимов, я — ведущий эксперт департамента развития технологий в R&D Positive Technologies. За плечами у меня многолетний опыт по развитию экспертизы в нашей системе MaxPatrol SIEM и процессов вокруг нее. И сегодня я хочу поговорить про один из видов экспертизы в продуктах этого класса — правилах нормализации. Если вы новичок в этом направлении и ранее вам не приходилось сталкиваться на практике с SIEM-системами и правилами для нее — не пугайтесь, основы этой темы мы тоже затронем ?

Что нас ждет:

  • определимся с тем, что же это такое — событие информационной системы, какие разновидности событий бывают;

  • узнаем, что такое нормализация событий и какие этапы можно в этом процессе выделить, рассмотрим нюансы, с которыми можно столкнуться;

  • детально разберем язык eXtraction and Processing (XP) для задач нормализации, лежащий в основе правил MaxPatrol SIEM, и посмотрим на примеры кода правил разной сложности;

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

Итак, приступим!

Что такое событие информационной системы и зачем нужна его нормализация

Любое приложение или система, имеющие на своем борту ОС и рассчитанные на работу в корпоративной среде, обязательно имеют подсистему журналирования. Эта подсистема отвечает за фиксацию наиболее важных (и не только их, о чем мы тоже поговорим) действий, происходящих в рамках рассматриваемой системы или приложения (далее будем называть их источниками), в виде журнала, который может храниться в разных форматах. Каждое такое действие представляется в виде самостоятельной записи в этом журнале. Эту запись мы будем называть событием.

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

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

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

Так как источники пишут журналы каждый по-своему, как в плане формата, так и в плане наполнения данными (что остается на усмотрение вендора), то в итоге мы имеем большой «зоопарк» разношерстных данных, с которым сложно работать в сыром виде, если мы говорим про централизованную обработку событий в части хранения и анализа для выявления вредоносного воздействия на инфраструктуру. Даже если общая структура события у двух разных источников может быть похожа, то представление одних и тех же данных внутри события могут различаться. Например, протокол UDP может быть представлен в виде числа 17.

Для того чтобы привести весь «зоопарк» различных вариантов представления событий к единому формату и получить возможность унифицированно работать с событиями от всех источников в инфраструктуре, выполняется этап нормализации.

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

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

Базово можно выделить два вида представления событий — текстовые и структурированные. Встречаются и случаи комбинирования этих видов представлений, про них мы поговорим отдельно, когда будем разбирать возможности языка eXtraction and Processing (XP) в части нормализации событий.

eXtraction and Processing (XP) — созданный в Positive Technologies язык разработки правил нормализации, корреляции и обогащения. Они используются в MaxPatrol SIEMPT XDR и системе SOLDR для обнаружения атак на основе анализа потока событий с конечных точек.

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

Второй вид представляет собой вложенную структуру параметров (многоуровневый ассоциативный массив). Примером могут быть форматы JSON или XML. Источник может самостоятельно генерировать события в структурированном виде, а может сохранять информацию о фиксируемых действиях, например, в одну или несколько таблиц базы данных, и уже после сбора таких событий через коннектор SIEM-системы они могут быть представлены в структурированном виде.

Стоит также отметить, что иногда вендор для текстового представления источника предлагает на выбор разные шаблоны форматов события, и от них будет зависеть то, в каком виде оно будет фиксироваться в журнале.

На что обращать внимание при выборе формата событий, если источник позволяет это сделать

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

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

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

 Зачастую при конфигурировании подсистемы журналирования источника идут по более простому пути — выбирают тот вариант, которые проще и быстрее настроить. Но не всегда проще и быстрее означает лучше. Выбрав более полный формат событий, впоследствии можно будет использовать эти дополнительные данные для написания новых детектов или улучшить точность существующих, предоставив оператору дополнительный контекст для расследования.

Как выглядит нормализованное событие

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

Глобально можно выделить несколько больших блоков:

  1. Описание субъектно-объектного взаимодействия, наблюдаемого в событии, которое можно читать как «субъект А выполнил действие B над (или «по отношению к») объектом C с результатом D». Например: «пользователь User1 успешно создал нового пользователя User2».

  2. Описание сторон взаимодействия на сетевом уровне: какие узлы мы наблюдаем в событии, кто из них является источником взаимодействия, а кто — назначением. Например, когда в событии узел A является инициатором соединения с узлом B, первый мы рассматриваем как источник взаимодействия (source, сокращенно src), а второй — назначением взаимодействия (destination, сокращенно dst).

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

  4. Дополнительная информация о взаимодействии в событии.

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

Основные этапы нормализации

Процесс нормализации события можно разделить на два основных этапа, выполняющихся последовательно:

  1. Первичный парсинг события (разбор события на составные элементы) и проверка выполнения условий отбора.

  2. Необходимые преобразования и дополнительная обработка исходных данных события с последующим маппингом их на поля схемы нормализованного события, то есть формирование его финального вида.

Посмотрим на первый этап детальнее в разрезе возможных представлений событий, про которые мы говорили ранее.

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

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

Парсинг текстовых журналов может быть читаемым — и без пол-литра разберемся!

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

Разберем каждый из них:

  • Сложность написания регулярного выражения для разбора события. События далеко не всегда бывают компактными и лаконичными, чтобы для их парсинга можно было написать читаемое и понятное регулярное выражение. Поэтому при разборе событий регулярными выражениями среди прочего используют подход «лесенки» — разбирают одним регулярным выражением только определенный кусочек события, а оставшуюся часть события передают на следующий уровень парсинга — другому регулярному выражению. В итоге имеем «лесенку» регулярных выражений для разбора одного события и теряем в читаемости такого правила.

  • Сложность корректировки регулярных выражений под изменившиеся требования к данным. Например, в новой версии источника для события частично поменялся формат, в связи с чем появилась необходимость дополнительно поддержать обновленный формат в парсере.

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

  • Результатом низкой читаемости регулярных выражений может стать сложность передачи поддержки правил нормализации от одного сотрудника, их разработавшего, другому, который видит их первый раз. Чтобы разобраться с ранее написанным правилом, потребуется дополнительное время.

В языке XP мы отказались от использования регулярных выражений в правилах нормализации, дав пользователю функциональность форматных строк TEXT с использованием токенов для работы с типовыми данными, которые можно встретить в текстовом событии. Например, токен DATETIME предназначен для извлечения даты и времени, IPV4 и IPV6 — для извлечения IP-адреса, KEYVALUE — для извлечения ассоциативного массива, содержащего пары «ключ — значение», STRING — для извлечения любой последовательности символов до первого пробела, NUMBER — для чисел. Для того чтобы одной форматной строкой TEXT можно было парсить один и тот же тип события, который может немного различаться в зависимости от контекста произошедшего действия, есть возможность задавать опциональные и альтернативные участки ожидаемых данных.

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

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

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

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

Копируем его в форматную строку TEXT:

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

Основными якорями, за которые мы цепляемся в этом событии, являются три участка данных, которые окрашены в зеленый цвет и которые в форматной строке представлены в виде текстовых констант.

А теперь давайте сделаем так, чтобы этим же правилом парсилось парное событие, сообщающее уже об успешной аутентификации:

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

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

Как видим, у нас добавился блок с ожиданием в событии альтернативных данных в виде строковых констант. В случае успешной аутентификации переменная $rest будет содержать пустую строку, а в случае неуспешной — причину, текст которой мы дополнительно разберем на втором этапе работы правила нормализации.

А что со структурированными журналами?

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

Мы выделили несколько форматных строк для работы со структурированными данными:

  • JSON, XML — названия говорят сами за себя, полноценный разбор данных указанных форматов. В самой форматной строке можно задать одно условие отбора или же оставить ее пустой и все необходимые условия указать через ключевое слово COND, про которое мы поговорим ниже.

  •  EVENTLOG — предназначен для событий формата EventLog, который представлен в пайплайне обработки событий в виде JSON определенной структуры. Позволяет получать доступ к данным по более короткому наименованию составных ключей, чем если бы мы рассматривали событие как обычный JSON. Задание форматной строки аналогично JSON.

  • TABULAR — предназначен для событий, представляющих из себя плоский JSON, обычно характерный для событий, собранных из баз данных. В форматной строке указываются наименование тех ключей, которые обязательно должны быть в событии со значением, отличным от null. Дополнительно позволяет выполнять маппинг данных события в поля схемы или временные переменные сразу в форматной строке.

Основным инструментом для проверки выполнения условий отбора в правилах нормализации языка XP является конструкция COND (которая точно так же может быть использована и при парсинге текстовых журналов, когда только форматной строки недостаточно для задания условий соответствия). COND позволяет задать более сложные условия отбора, чтобы удостовериться, что правилом нормализации будет обработано именно целевое событие.

Посмотрим несколько примеров форматных строк и конструкции COND для структурированных данных:

На матрешку событийных форматов взглянуть не хотите?

Бывают примеры событий, содержащие данные сразу в нескольких форматах. Например, это может быть текстовый журнал, часть которого представляет собой развесистые структурированные данные JSON, или же в структурированном событии табличного вида (плоский JSON) в одном из полей может находиться текст, требующий разбора, или XML-структура, из которой нужно извлечь определенные значения.

Для подобных случаев в языке XP предусмотрен механизм, позволяющий обрабатывать части событий как самостоятельные целевые события. Фактически это вложенное правило нормализации, которое описывается внутри конструкции из ключевых слов subformula и endsubformula, а вызов обработки осуществляется с помощью функции submessage:

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

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

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

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

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

Давайте посмотрим на несколько примеров такой обработки.

Вернемся к событиям аутентификации, которые мы рассматривали в рамках текстовых форматных строк. Там мы сохранили несколько значений, извлеченных из события, во временные переменные для дальнейшей обработки, самое время ее выполнить:

В этом случае обработка исходных данных простая: осуществляем маппинг статуса события (успешная или неуспешная аутентификация) на соответствующие значения поля status в нашей схеме, где оно имеет тип Enum, по аналогии устанавливаем в поле importance уровень важности события в зависимости от статуса и делаем небольшую модификацию текста, описывающего причину неудачной аутентификации, — «откусываем» в конце точку, если она там есть, после чего сохраняем в итоговое поле нормализованного события reason.

Посмотрим на еще один пример кода, немного более насыщенный, чем предыдущий:

Тут мы видим преобразование метки времени из числового формата в DATETIME, приведение наименования протокола к нижнему регистру, а также формирование удобного для восприятия описания причины возникновения события, которое представляет собой комбинацию значений разных полей исходного события при условии, что эти значения непустые (в этом случае наличие тех или иных полей будет меняться в зависимости от контекста события).

Нюансы процесса нормализации

Немаловажным вопросом в процессе нормализации события является понимание того, что в этом событии происходит, какое действие оно описывает, кто является участниками этого действия (субъект, объект, сетевые узлы).

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

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

Эту тему мы более подробно затрагивали несколько лет назад в цикле наших статей, посвященных правилам корреляции, где среди прочего постарались раскрыть вопросы методологии нормализации событий. Еще один интересный вопрос: а все ли получаемые события от источника нужно нормализовывать? И ответ на этот вопрос сильно зависит от самого источника и в первую очередь от того, как построена его подсистема журналирования и насколько гибко ее можно конфигурировать. Мы на своей практике встречали источники, которые наряду с важными событиями для мониторинга службой ИБ осуществляли журналирование событий, не несущих полезной нагрузки (это может быть, например, отладочная информация, полезная только разработчику системы, отключить такие события иногда невозможно, так как они могут добавляться в журнал на одном уровне с важными для ИБ событиями). Поэтому ответ на исходно поставленный вопрос будет «нет». К вопросу выбора событий, для которых мы будем разрабатывать правила нормализации, нужно подходить осознано, ориентируясь на возможности источника (можем ли мы на уровне источника отсеять ненужные события) и решаемые мониторингом задачи.

Почему свой DSL

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

И вот почему:

  • Язык должен быть простым в понимании, иметь низкий порог входа (и наши программы стажировок хорошо показали, что даже те пользователи, которые видели язык впервые, разбирались в нем очень быстро).

  • Язык должен быть наглядным и хорошо читаемым — для облегчения разработки правил, а также для быстрого понимания кода, когда приходится адаптировать правила под события новой версии источника (в том числе в ситуациях, когда само правило было разработано другим сотрудником).

  • Свой DSL дает возможность ограничить использование потенциально опасных для производительности продукта конструкций или спрятать такие конструкции под специфичные для предметной области функции с «подкапотной» оптимизацией.

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

Инструменты для разработки и отладки правил нормализации на языке XP

Для разработки и отладки правил есть соответствующий SDK в виде CLI-утилит, который при желании можно добавить в интересующий текстовый редактор или IDE, если у них есть такая возможность.

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

? 28 марта в 14:00 мы запускаем серию вебинаров «MaxPatrol SIEM: оголяемся технологически», в которой рассказываем о том, какие технологии находятся «под капотом» и как все устроено в нашей SIEM-системе.

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

Кроме того, в рамках продукта поставляется самостоятельная утилита PTSIEMSDK GUI, которая тоже использует SDK для языка XP и предоставляет расширенные возможности по отладке правил, позволяет проверять различные сценарии обработки событий и поддерживает целый набор систем помощи для написания кода правил, в том числе содержит справочник схемы полей нормализованного события. Так как утилита является самостоятельной, она не требует доступа к живой инсталляции продукта и позволяет разрабатывать и вести отладку правил имея под рукой всего лишь ноутбук, даже без доступа к корпоративной сети. В этом месяце вышла ее новая версия — 4.0, которая получила новые функции и целый набор улучшений, так что пользователям предыдущей версии рекомендуем обновиться — вам должно понравиться.

Для редактора Visual Studio Code сообщество экспертов разработало полноценное расширение для создания и отладки правил на языке XP, которое доступно для загрузки непосредственно через сам редактор в соответствующем разделе (называется так же, как и сам язык — eXtraction and Processing). Желающие могут поучаствовать в развитии расширения, оно имеет открытый исходный код.

Вместо заключения

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

Достаточно загрузить расширение eXtraction and Processing  в редакторе Visual Studio Code (или воспользоваться утилитой PTSIEMSDK GUI, если в вашей организации уже используется или пилотируется MaxPatrol SIEM), ознакомиться с примерами правил в репозитории сообщества экспертов, и можно приступать к разработке собственных правил! 

Комментарии (1)


  1. ndmpt
    26.03.2024 13:31
    +2

    Простой и понятный DSL для правил SIEM оказался чрезвычайно удобен для системных правок при работе с контентом, происходящих довольно часто. Например, из-за постоянно меняющихся форматов логов - при правках всех нормализаций событий с выходом новых версий источника, или же при рефакторинге сложных высокоуровневых правил корреляции и обогащения, необходимость которого может быть вызвана потребностями экспертизы.