OSSIM. Создание простого плагина для разбора syslog

Данный материал будет полезен начинающим администраторам, проявляющим интерес к системе OSSIM.
Установка системы уже была подробно описана на хабре, поэтому на данном моменте я останавливаться не буду.
В статье описана процедура написания плагина для обработки журналов событий, получаемых системой OSSIM по протоколу syslog от приложения, работающего на удаленной машине. Здесь следует отметить, что данное приложение не поддерживается OSSIM «из коробки». Таким образом, данная инструкция подойдет для разработки плагина для любого Вашего приложения, которое для передачи журналов событий использует протокол syslog.
В качестве основы использовались документы вендора:
Alienvault. Building collector Plugins
Alienvault. How to create a data source plugin

1. Исходные данные

1.1 Архитектура

Сервер с установленным OSSIM (далее — Сервер OSSIM), имеющий IP адрес 192.168.0.111 и имя alienvault.
Сервер под управлением CentOS 6.6 (далее — Сервер) c IP адресом 192.168.0.54 и именем cnc-2. На Сервере установлено приложение (условно назовем его bw_lists), которое отправляет журналы событий в режиме реального времени по протоколу syslog на Сервер OSSIM.
Приложение является некой модификацией стандартного шелла, выполняющего фильтрацию вводимых пользователем команд.

Рисунок 1 – Архитектура решения

1.2 Описание структуры события

Формат события:
<дата в формате syslog> <имя хоста> bw_lists[<номер сессии>]: user:<имя пользователя> ip:<IP Сервера> ip_tko:<IP целевой системы> IN:<выполненная пользователем команда> OUT: Res: <отчет выполнения или отказа> <текст команды> <вывод целевой системы>
В каждое событий, отправляемое по syslog приложение включает:
1) номер сессии пользователя (в квадратных скобках сразу после слова bw_lists)
2) имя пользователя, выполнившего команду
3) IP адреса Сервера и целевой системы, на которой эта команда должна отработать
4) команду, выполненную пользователем (например — «configure terminal»)
5) отчет о выполнении или отказе в выполнении команды, отданной пользователем (ACCEPT или DENY)
6) вывод, полученный в консоли (например — «Enter configuration commands, one per line. End with CNTL/Z»)
Пример событий, полученных от приложения:

Nov 20 14:15:33 cnc-2 bw_lists[19025]: user:oper1 ip:192.168.0.54 ip_tko:192.168.1.104 IN: configure terminal OUT: Res: ACCEPT configure terminal Enter configuration commands, one per line. End with CNTL/Z.
Nov 20 14:15:39 cnc-2 bw_lists[19025]: user:oper1 ip:192.168.0.54 ip_tko:192.168.1.104 IN: interface Gi0/1 OUT: Res: ACCEPT interface Gi0/1 ^ % Invalid input detected at '^' marker.
Nov 20 14:16:29 cnc-2 bw_lists[19025]: user:oper1 ip:192.168.0.54 ip_tko:192.168.1.104 IN: exit OUT: Res: ACCEPT exit

2. Задачи

1) Настроить на Сервере OSSIM прием журналов событий по протоколу syslog от Сервера и запись их в файл;
2) Настроить разбор (парсинг) полученных журналов событий в системе OSSIM. Необходимо извлечь из них следующую информацию:

  • номер сессии пользователя (в квадратных скобках сразу после слова «bw_lists»);
  • имя пользователя, выполнившего команду (после «user:»);
  • IP адреса Сервера (после «ip:») и целевой системы (после «ip_tko:»), на которой эта команда должна отработать;
  • команду, выполненную пользователем (после «IN:», например — «configure terminal»);
  • отчет о выполнении или отказе в выполнении команды (после «Res:»), отданной пользователем (ACCEPT или DENY).

3. Решение

3.1 Настройка на Сервере OSSIM приема журналов событий от Сервера

В рамках выполнения этой задачи на Сервере OSSIM будет настроен rsyslog для приема журналов событий, приходящих от Сервера по протоколу syslog.
Для этого отредактируем файл /etc/rsyslog.conf и добавим в него строку:

if $programname contains 'bw_lists' then -/var/log/SR/bw-list-log.log

И перезапустим rsyslog, чтобы изменения вступили в силу:

/etc/init.d/rsyslog restart

Таким образом, события, полученные Сервером OSSIM от Сервера и содержащие «bw_lists» будут записаны в файл /var/log/SR/bw-list-log.log. Далее настроим разбор событий из этого файла самим OSSIM.

3.2 Настройка разбора (парсинга) и отображения полученных событий в OSSIM

Процесс настройки разбора событий в OSSIM разделяется на два этапа:

  • создание конфигурационного файла-парсера журналов событий;
  • добавление информации о парсере и типе(ах) событий в базу данных OSSIM;
  • включение плагина.

Первый файл отвечает за парсинг самого журнала и распределение полученной информации по полям схемы описания событий, используемой OSSIM, второй — для отображения типов и классов событий в интерфейсе OSSIM, а также для назначения приоритетов событиям.
Для описания событий OSSIM использует схему, состоящую из нескольких десятков полей, таких как: date, sourceIP, destinationIP, username, userdata1-9 и т.д. Подробно схема приведена в офф. документации OSSIM.

3.2.1 Создание конфигурационного файла-парсера журналов событий

Файлы-парсеры располагаются на сервере OSSIM в директории /etc/ossim/agent/plugins/
Создадим новый файл с именем bwlistlog.cfg (имя можно выбрать произвольное, оно ни на что не влияет и более нигде не фигурирует. Однако, имя обязательно должно соответствовать формату <букво-цифро сочетание без пробелов>.cfg).
В каждом файле должны быть выделены несколько секций (названия секций заключаются в квадратные скобки), а именно:

[DEFAULT]
# уникальный номер парсера (в терминологии OSSIM - plugin.)
plugin_id=9002 

[config]
# тип plugin'а. Они бывают двух типов - detector и monitor. Для приема по syslog используется тип detector
type=detector 
# тумблер включения
enable=yes 

# тип лога. log - текстовый файл. может также быть database (чтение данных из БД), sdee (для cisco), snortlog (логи snort), wmi (для безагентского сбора с машин под управлением ОС Windows поддерживающих протокол wmi)
source=log
# расположение файла с логами, который будет разбирать данный парсер.
location=/var/log/SR/bw-list-log.log 

# должен ли OSSIM создать файл в случае его отсутствия. Я не менял данную опцию
create_file=true 

# блок инструкций по перезапуску сервисов при старте-остановке агента OSSIM. Для источников, располагающихся не на Сервере OSSIM, как в нашем случае, рекомендуется оставить все по-умолчанию
process=    
start=no
stop=no
startup=
shutdown=

# раздел в котором можно задать "перевод" значений полей
[translation]  
ACCEPT=1
DENY=2

# название первого (и, в данном случае, единственного) правила парсера. 
[bwlistlog] 
# тип события. менять не нужно
event_type=event
# регулярное выражение, согласно которому происходит парсинг событий
regexp="^((?P\S+\s+\d+\s+\d+:\d+:\d+)\s+(?P\S+)\s+bw_lists\[(?P\d+)\]\:\s+user\:(?P\S+)\s+ip\:(?P\S+)\s+ip_tko\:(?P\S+)\s+IN\:(?P.*)\s+OUT\:\s+Res\:\s+(?P\S+).*)"
# далее задается соответствие полей, обозначенных с помощью парсера полям, предусмотренным для событий в схеме OSSIM. Подробнее в разделе 3.2.3
device={$sr_node}
date={normalize_date($date)}
plugin_sid={translate($result)}
src_ip={$tko_node}
username={$user}
userdata1={$message}
userdata2={$session}

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

(?P\S+\s+\d+\s+\d+:\d+:\d+)

означает, что информация в начале строки, которая попадает под выражение \S+\s+\d+\s+\d+:\d+:\d+ будет адресоваться по тегу «date». Далее мы сообщаем, что в поле «date» схемы OSSIM мы хотим положить значение нашего поля «date» предварительно выполнив его нормализацию (OSSIM умеет преобразовывать дату в разных форматах к своему единому):

date={normalize_date($date)}

Для тестирования регулярных выражений можно использовать, например, вот этот инструмент. Имейте ввиду, что данный инструмент с тегами работать не умеет. Поэтому, оттестировав свое регулярное выражение в нем, их нужно будет добавить.
Также необходимо пояснить поле «plugin_sid». События от одного источника — с одним и тем же «plugin_id» — могут принадлежать разным классам, например «ACCEPT» и «DENY» для нашего примера. «plugin_sid» как раз указывает на идентификатор класса, а строка:

plugin_sid={translate(result)}

говорит парсеру о том, что нужно обратиться в раздел [translate] для выполнения трансляции информации, полученной тегом «result». «ACCEPT» транслируется в единицу, «DENY» — в двойку. Как и зачем назначать классы событий — в следующем разделе.
Да, «plugin_sid» можно назначить и вручную для каждого правила парсинга, указав, например:

plugin_sid=1

3.2.2 Добавление информации о парсере и типе(ах) событий в базу данных OSSIM

После написания конфигурационного файла парсера необходимо добавить информацию о нем в БД OSSIM.
Это делается посредством написания mysql скрипта и его запуска. Примеры скриптов лежат на Сервере OSSIM в папке:
/usr/share/doc/ossim-mysql/contrib/plugins/
Имя скрипта можно выбирать произвольное.
Для наглядности, сразу приведу скрипт из нашего примера:

DELETE FROM plugin WHERE id = "9002";
DELETE FROM plugin_sid where plugin_id = "9002";
INSERT IGNORE INTO plugin (id, type, name, description) VALUES (9002, 1, 'bw-lists', 'Bash filtering');

INSERT IGNORE INTO plugin_sid (plugin_id, sid, category_id, class_id, name) VALUES (9002, 1, NULL, NULL, 'Command Accepted');
INSERT IGNORE INTO plugin_sid (plugin_id, sid, category_id, class_id, name) VALUES (9002, 2, NULL, NULL, 'Command Denied');

Первые три строки вычищают все старые упоминания о «plugin_id» под номером 9002 из БД и создают его заново.
Следующие две как раз описывают классы событий.
Как вы помните из предыдущего раздела, «plugin_sid» вычисляется посредством соотнесения информации, полученной из события с помощью парсера под тегом «result» (может быть «ACCEPT» и «DENY») и последующего преобразования ее в секции [translate] (в конфигурационном файле парсера). Таким образом имеем два класса событий 1 — «ACCEPT», 2 — «DENY».
Именно об этих классах событий сообщают БД OSSIM строки:

INSERT IGNORE INTO plugin_sid (plugin_id, sid, category_id, class_id, name) VALUES (9002, 1, NULL, NULL, 'Command Accepted');
INSERT IGNORE INTO plugin_sid (plugin_id, sid, category_id, class_id, name) VALUES (9002, 2, NULL, NULL, 'Command Denied');

Знакомые с синтаксисом «mysql» с легкостью их поймут. Для остальных поясню, что события, классифицированные как «ACCEPT» в интерфейсе OSSIM будут появляться с названием «Command Accepted», а «DENY», соответственно — «Command Denied». Здесь также можно задать параметры категорирования событий этого типа источников (category_id, class_id).
После создания скрипта необходимо загрузить его в БД OSSIM командой:

# ossim-db < /usr/share/doc/ossim-mysql/contrib/plugins/bw-lists.sql

3.2.3 Включение плагина

Включить созданный плагин можно следующим образом:
1) подключиться к Серверу OSSIM по SSH, зайти в меню: «Configure sensor» — «Configure Data Source Plugins»;
2) найти в списке плагин «bw-lists» и поставить возде него «*», нажать «ОК»;
3) вернуться в корневое меню кнопкой «Back»;
4) выбрать опцию «Apply all Changes».
Новый плагин готов к обработке журналов событий.
Однако, если события поступают, а в интерфейсе OSSIM, задав сортировку по типу плагина, вы их не видите, то….

4. Устранение неполадок

1) проверьте, что лог файл, указанный в конфигурационном файле парсера существует и в нем обновляются записи — т.е. журналы поступают;
2) проверьте, что формат событий подходит под написанное Вами регулярное выражение;
3) проверьте файл /var/log/alienvault/agent/agent.log на предмет ошибок, связанных с Вашим плагином:

grep ERR /var/log/alienvault/agent/agent.log|grep 9002
grep Discard /var/log/alienvault/agent/agent.log|grep 9002
grep Warn /var/log/alienvault/agent/agent.log|grep 9002