Использование custom functions в парсерах OSSIM

    Доброго дня, уважаемые!
    В продолжение моей статьи хочу рассмотреть и поделиться опытом работы с функционалом «custom functions», используемом в OSSIM. Это функции, которые предназначены для обработки полученной вследствие разбора (парсинга) журналов событий информации. Обработка может заключаться в разрешении имени по IP адресу, определении геолокации и всего того, на что хватит фантазии. В примере ниже я разберу вариант использования «custom functions» для дополнительного парсинга полученной информации.

    1. Для чего это нужно?


    Предположим, что вы извлекаете журналы событий из базы данных (далее — БД), как я описывал в статье. И случилось так, что в одном из полей БД у Вас лежит не одно какое-то значение, например «имя пользователя» или «IP адрес», а целая строка сообщения из которой нужно выделить ключевые слова (например, строка вида «issued command: ls /root; result: ACCEPT»). И Вам из данной строки нужно получить текст команды (ls /root) и результат ее выполнения (ACCEPT).
    Очевидно, что стандартным функционалом, доступным для источников журналов событий типа «mysql», это сделать невозможно. Тут-то и приходит на помощь функционал «custom functions». С его помощью из полученной строки мы сможем выделить интересующие нас фрагменты информации. Итак, приступим.

    2. Формулировка задачи


    На базе примера из статьи необходимо выделить информацию об отданной команде (все, что следует после «command:») и результате ее выполнения (все, что следует после «result:») из строки лога, хранимой в базе данных в поле «message». Записать текст команды в поле «userdata3», а результат выполнения команды в поле «userdata4».
    Пример таблицы из БД:
    +---------------------+----------+----------------------+----------+--------------------------------------------+
    | date                | event_id | event_type           | username | message                                    |
    +---------------------+----------+----------------------+----------+--------------------------------------------+
    | 2016-07-22 17:17:05 |      283 | type 1               | net_adm  | issued command: show arp; result: ACCEPT   |
    | 2016-07-22 17:17:49 |      284 | suspicious activity  | operator | issued command: show arp; result: ACCEPT   |
    | 2016-07-22 17:17:50 |      285 | suspicious activity  | admin    | issued command: show arp; result: ACCEPT   |
    | 2016-07-22 17:17:51 |      286 | suspicious activity  | guest    | issued command: show arp; result: ACCEPT   |
    | 2016-07-22 17:17:52 |      287 | type 1               | unknown  | issued command: show arp; result: ACCEPT   |
    | 2016-07-22 17:17:53 |      288 | type 1               | valeriy  | issued command: show arp; result: ACCEPT   |
    | 2016-07-22 17:17:54 |      289 | suspicious activity  | alex     | issued command: show arp; result: ACCEPT   |
    | 2016-07-22 17:17:55 |      290 | type 1               | cisco    | issued command: show arp; result: ACCEPT   |
    | 2016-07-22 17:17:57 |      291 | suspicious activity  | net_adm  | issued command: show arp; result: ACCEPT   |
    +---------------------+----------+----------------------+----------+--------------------------------------------+

    3. Решение


    Для решения задачи будет выполнено:
    • создание функции для выделения информации о команде;
    • создание функции для выделения информации о результате выполнения команды;
    • дополнительная настройка парсера (ранее созданного в примере).

    Для того, чтобы использовать свою собственную функцию в парсере OSSIM необходимо создать новый файл, например:
    /usr/share/alienvault/ossim-agent/plugins/db_logs_func.cfg

    И добавить функции в файл в виде:
    Start Function  <имя функции>
        <тело функции>
    End Function

    Функции пишутся на python.

    3.1. Создание функции для выделения информации о команде

    Я написал следующую функцию для выделения информации об отданной команде из текста события:
    def parse_command(input):
       res = re.search(r'command:.*;', input)
       return (res.group(0).split(": ")[1].strip(";"))

    Как видно, данная функция с помощью регулярного выражения получает необходимую информацию (все, что находится после «command:» и до последней ";". Говорю последняя т.к. в теле команды тоже могут присутствовать ";") и возвращает ее агенту OSSIM для дальнейшей обработки парсером.

    3.2. Создание функции для выделения информации о результате выполнения команды

    Аналогично пишем вторую функцию и добавляем ее в файл:
    def parse_result(input):
       res = re.search(r'result:\s+\S+', input)
       return (res.group(0).split(": ")[1])

    В итоге, файл «/usr/share/alienvault/ossim-agent/plugins/db_logs_func.cfg» имеет вид:
    Start Function parse_command
       def parse_command(input):
          res = re.search(r'command:.*;', input)
          return (res.group(0).split(": ")[1].strip(";"))
    End Function
    Start Function parse_result
       def parse_result(input):
          res = re.search(r'result:\s+\S+', input)
          return (res.group(0).split(": ")[1])
    End Function

    3.3. Дополнительная настройка парсера

    Подробно на разъяснении всей конфигурации парсера останавливаться не буду, т.к. это уже сделано ранее в примере.
    Для сообщения парсеру о необходимости использования файла с созданными функциями нужно в секцию [config] конфигурационного файла парсера дописать дописать следующую строку:
    custom_functions_file=/etc/ossim/agent/plugin/db_logs_func.cfg

    Для использования созданных функций в парсере OSSIM используется конфигурационная строка вида:
    <поле OSSIM>={<имя функции>(<параметр>)}
    Этой строкой мы сообщаем агенту OSSIM в какое поле схемы описания события OSSIM нужно поместить информацию, получаемую применением функции к параметру. А параметром в нашем случае является информация, полученная из БД из поля «message», т.е. текст события вида «issued command: show arp; result: ACCEPT».
    Поля OSSIM в нашем примере будут: userdata3, userdata4
    Функции, соответственно: «def parse_command» и «def parse_result»
    Параметром будет "$4"
    В итоге, строки, которые нужно ддобавить в конфигурационный файл парсера выглядят так:
    userdata3={parse_command($4)}
    userdata4={parse_result($4)}

    Ниже приведен итоговый фрагмент (секция query) конфигурационного файла парсера OSSIM:
    [query]
    query="select event_id, date, event_type, username, message from data_table where event_id > $1;"
    #order by event_id desc limit 1
    regexp=
    ref=0
    date={normalize_date($1)}
    plugin_sid={translate($2)}
    username={$3}
    userdata1={$4}
    userdata2={$2}
    userdata3={parse_command($4)}
    userdata4={parse_result($4)}

    После выполнения данных манипуляций необходимо перезапустить агента OSSIM:
    /etc/init.d/ossim-agent restart

    После перезапуска не лишним будет проследить за сообщениями в файле лога на предмет ошибок (вдруг где-то закралась):
    tail -f /var/log/alienvault/agent/agent.log|grep ERROR

    Если все сделано правильно, то в графическом интерфейсе OSSIM можно увидеть разбор события. Примерно такой, как на рисунке 1.

    Рисунок 1 – Разобранные события в интерфейсе OSSIM

    4. Усовершенствование


    Здесь хотелось бы сказать, что первая моя мысль была попробовать передавать два параметра в функцию, чтобы в поля userdata3 и userdata4 записывать разные части из исходного текста.
    Например, передавая (текст, 1) получать команду, а (текст, 2) — соответственно, результат. Такое решение мне кажется наиболее изящным.
    Я даже написал под это функцию, которая отрабатывает, если запускать ее в командной строке сервера. Но вот агент OSSIM никак не желает принимать два параметра, только один.
    Я обратился в alienvault с этим вопросом, но пока ответа не получил. Если у кого есть размышления на эту тему, прошу, пишите в личку или комментарии.
    Заранее спасибо!
    Share post

    Similar posts

    Comments 0

    Only users with full accounts can post comments. Log in, please.