MongoDB як логер для OSSIM

Доброго дня, шановні читачі! Ця стаття замислювалася мною як доповнення до чудової статті Євгенія Соколова про використання MongoDB як логер для OSSIM (тобто довгострокового сховища журналів подій). Я доповнив оригінальну статтю Євгена коментарями та роз'ясненнями, де, на мій погляд, це було необхідно для кращого розуміння.

Деякі частини оригінальної статті Євгенія я дозволив собі скопіювати з дозволу самого автора.

1. Для чого це потрібно?
Ті, хто хоче використовувати SIEM систему Alienvault OSSIM, або вже використовують її, напевно, звернули увагу на одне з головних її відмінностей від платного аналога (Alienvault USM) – відсутність компонента «Logger». Таким чином, єдиним варіантом зберігання зібраних журналів подій є база даних MySQL, що працює в основі OSSIM. Але чим більше стає її об'єм, тим повільніше починає працювати пошук і вся система в цілому. Оптимальним бачиться варіант зберігання невеликого «оперативного» обсягу журналів в базі OSSIM. Для довгострокового зберігання краще використовувати щось інше, наприклад MongoDB.

2. Формулювання завдання і вихідні дані
Завдання: налаштування OSSIM для відправки стягуються журналів подій на зберігання під зовнішню БД, якою є MongoDB.

Вихідні дані:

  • сервер з встановленою OSSIM (використана версія 5.2.2, IP: 192.168.0.111);
  • сервер з встановленою MongoDB (сервер під управлінням Debian 8.5, база даних MongoDB версії 3.2, IP: 192.168.0.77).
На процесі установки MongoDB зупинятися не буду, оскільки він добре описаний на офіційному сайті системи.
Схема взаємодії компонентів наведено на малюнку нижче.


Малюнок 1 — Схема взаємодії компонентів OSSIM і mongoDB

OSSIM складається з двох основних компонент: агент (ossim-agent) і сервер (ossim-server). Агент займається обробкою журналів подій, що надходять від різних джерел, і їх нормалізацією, тобто приведенням до єдиного формату. Після нормалізації агентом, події передаються компоненту ossim-sever для обробки (кореляція, побудова звітів тощо). Після обробки події містяться в БД MySQL. В рамках вирішення поставленої задачі буде налаштована відправка агентом нормалізованих подій на сервер mongoDB, як показано на малюнку 1.

Трохи заглибившись в код агента (написаний на python), можна побачити, що агент створює об'єкт класу Event, який віддає сервера. Об'єкт Event в одному зі своїх атрибутів містить рядок сирого лода від джерела. Передачею події серверу займається клас OutputPlugins, код якого лежить в /usr/share/alienvault/ossim-agent/Output.py. Якщо ми почитаємо цей код, то побачимо, що виведення даних передбачений не тільки на сервер, але також і в текстовий файл, файл у форматі csv, SQL базу даних (будь-яку, яку підтримує модуль python adoDB). Ці опції можна просто включити у файлі конфігурації агента в /etc/ossim/agent/config.cfg. Різні «висновки» можна включати одночасно. Таким чином можна включити паралельну передачу подій зовнішнього логгеру.

3. Рішення
Тут необхідно пояснити, що для реалізації необхідного функціоналу потрібно буде вносити правки в код самого ossim, а точніше трьох файлів, які відповідають за обробку агентом журналів подій: Output.py, Agent.py, Event.py.
Для вирішення завдання буде виконано:

  • додавання коду у файли ossim (Output.py, Agent.py, Event.py);
  • налаштування mongoDB для прийому журналів подій;
  • включення відсилання журналів подій на сервер mongoDB.
3.1. Додавання коду у файли ossim (Output.py, Agent.py, Event.py)
Файли Output.py, Agent.py, Event.py розташовуються на сервері OSSIM в папці /usr/share/alienvault/ossim-agent.
Модифіковані для роботи з mongoDB зразки файлів Output.py, Agent.py, Event.py, які можна скопіювати в свою інсталяцію OSSIM, замінивши вихідні (на всякий випадок, зробивши їх резервну копію) можна взяти за посиланням в папці «OSSIM/usr/share/alienvault/ossim-agent/» гілки 2.1.1. Нижче будуть описані зміни, внесені в оригінальні файли Output.py, Agent.py, Event.py у OSSIM.

Модифікація Output.py
Насамперед, необхідно додати в Output.py код класу для створення об'єкта «висновок». У секції GLOBAL IMPORTS:

# GLOBAL IMPORTS
#
import os
re import
import string
import sys
import uuid
from pymongo import MongoClient
from bson import BSON

Додані два останні рядки. «from pymongo import MongoClient» — підключає модуль клієнта mongoDB (очевидно, для роботи з mongo). «from bson import BSON» — підключає кодек BSON (binary JSON).

Далі додається клас «OutputESGuard», який виконує передачу подій на сервер mongoDB. Виглядає він наступним чином:

class OutputESGuard(OutputPlugins):
def __init__(self, f):

logger.info("Added ESGuard output")
logger.debug("OutputDB options: %s" % (conf.hitems("output-esguard")))

self.conf = conf

self.dbhost = self.conf.get('output-esguard', 'host')
self.dbport = self.conf.get('output-esguard', 'port')
self.dbschema = self.conf.get('output-esguard', 'base')
self.dbuser = self.conf.get('output-esguard', 'user')
self.dbpass = self.conf.get('output-esguard', 'pass')

mongodbURI = "mongodb://" + self.dbuser + ":" + self.dbpass + "@" + self.dbhost + ":" + self.dbport + "/" + self.dbschema
try :
self.conn = MongoClient(mongodbURI)
self.log_db = self.conn[self.dbschema]
self.event_coll = self.log_db['logger']
self.activated = True
except Exception, e:
logger.error(": Error connecting to Mongodb %s" % (e))

def event(self, e): 

if e["event_type"] == "event" and self.activated: 

try :
self.event_coll.insert_one(BSON.decode(e.to_bson_esguard()))
except :
logger.error(": Error insert data to mongodb log_coll. Plugin_id is %s. Retry as binary" % (e['plugin_id'])) 
self.event_coll.insert_one(BSON.decode(e.to_bson()))

def shutdown(self):
logger.info("Closing ESGuard output ..")
self.conn.close()
self.activated = False

Також в Output.py код класу Output був доданий метод add_esguard_output:

@staticmethod
def add_esguard_output(conf):
if Output.esguard_output is False:
Output._outputs.append(OutputESGuard(conf))
Output.esguard_output = True

Модифікація Event.py
Код класу Event (/usr/share/alienvault/ossim-agent/Event.py) був доданий метод to_bson_esguard() (який використовується методом event в output.py). Цей метод (to_bson_esguard()) являє собою копію наявного методу to_bson з однією відмінністю. У стандартному методі атрибут log (саме в ньому міститься подія в сирому вигляді) оголошується, як бінарний і записується в Base64. Нам же там потрібний текст в utf8. Саме це і було змінено.

Однак не всі плагіни пишуть в payload текст. Є, наприклад, Suricata, яка може помістити туди бінарні дані. Це відбувається не завжди. Зазвичай теж текст, але іноді — потік байтів. При спробі сунути сервера бінарники в полі, описаному як текст, він повертає помилку парсера utf8. Для попередження такої помилки включена передача в блок try. При виникненні помилки, event перекодовується, використовуючи стандартний метод to_bson(), і повторно відправляється на сервер.

Модифікація Agent.py
В Agent.py необхідно додати секцію читання та обробки файлу конфігурації(/etc/ossim/agent/config.cfg), перевірку наявності в ньому розділу [output-esguard] і читання параметрів, в ньому вказаних. У даному розділі буде вказаний IP адреса і облікові дані сервера mongoDB, в який відправляються журнали подій.

def init_output(self):
"'
Initialize Outputs
"'

printEvents = True

if self.conf.has_section("output-properties"):
printEvents = self.conf.getboolean("output-properties", "printEvents")
Output.print_ouput_events(printEvents)

if self.conf.has_section("output-plain"):
if self.conf.getboolean("output-plain", "enable"):
Output.add_plain_output(self.conf)

# output-server is enabled in connect_server()
# if the connection becomes availble

if self.conf.has_section("output-csv"):
if self.conf.getboolean("output-csv", "enable"):
Output.add_csv_output(self.conf)

if self.conf.has_section("output-db"):
if self.conf.getboolean("output-db", "enable"):
Output.add_db_output(self.conf)

if self.conf.has_section("output-esguard"):
if self.conf.getboolean("output-esguard", "enable"):
Output.add_esguard_output(self.conf)

3.2. Налаштування mongoDB для прийому журналів подій
Мінімальна настройка mongoDB передбачає:

  • створення користувача для підключення до БД;
  • налаштування листнера для підключення до БД по мережі;
  • включення аутентифікації;
Для створення користувача БД потрібно підключитися до БД з консолі сервера, на якому вона встановлена:

# mongo
MongoDB shell версія: 3.2.8
connecting to: admin

Створення користувача виконується командою:

db.createUser( { user: "ossim", pwd: "1q2w3e4r", roles: [ {role: "readWrite", db: "test"} ] } )

наведеної вище командою ми створили користувача з ім'ям «ossim», паролем «1q2w3e4r», що має права на читання і запис в БД «test». Згідно ідеології mongoDB вручну створювати БД (як це прийнято в реляційних БД, тому MySQL) не потрібно. Вона створюється автоматично, в той момент, коли в неї надходить перша запис.
Також, для зручності, можна створити користувача з привілеями створення і управління обліковими записами користувачів (для того, щоб ми могли керувати користувачами після того, як включимо аутентифікацію і авторизацію при доступі до БД):

db.createUser( { user: "uadm", pwd: "1q2w3e4r", roles: [ "userAdminAnyDatabase" ] } )

Налаштування інсталяція mongoDB «з коробки» не дозволяють підключатися до БД по мережі, тому необхідно закоментувати в секції «net» файлу конфігурації "./etc/mongod.conf" рядок «bindIp: 127.0.0.1» (або вписати туди адреси інтерфейсів, на яких буде відповідати БД):

net:
port: 27017
# bindIp: 127.0.0.1

Крім того, ці ж параметри дозволяють підключення до БД анонімних користувачів (о_О). Для включення механізмів аутентифікації і авторизації необхідно додати в секцію «security» рядка «authorization: enabled» (mongoDB версії 2.х робиться інакше. Якщо використовуєте версію 2.х, див. офіційну документацію на сайті):
security:
authorization: enabled

І виконати перезавантаження сервера:

/etc/init.d/mongod restart

Перевірити, чи те, що УЗ працює можна командою з консолі:

# mongo localhost:27017/test -u ossim -p
MongoDB shell версія: 3.2.8
Enter password:
connecting to: localhost:27017/test

3.3. Включення відсилання журналів подій на сервер mongoDB
Отже, на даний момент, ми маємо компонент ossim-agent сервера ossim з налаштованим додатковим висновком подій в mongoDB і саму БД, готову до прийому даних по мережі. Залишилося тільки повідомити агенту ossim, куди передавати журнали подій. Для цього, в кофигурационный файл агента (/etc/ossim/agent/config.cfg) потрібно додати відповідну секцію. Приклад вмісту наведено нижче:

[output-esguard]
enable=True
host=192.168.0.77
port=27017
base=test
user=ossim
pass=1q2w3e4r

Конфігурація говорить сама за себе: тумблер включення «enable», адресу сервера «host», порт «port» (за замовчуванням 27017), ім'я бази даних «base» ім'я користувача «user» і пароль «pass».

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

/etc/init.d/ossim-agent restart

4. Висновок
Якщо все зроблено правильно, то події вже почали передаватися в mongoDB. Подивитися, чи з'явилися вони там можна з допомогою графічних клієнтів, яких безліч(гугл в допомогу) або підключившись до mongoDB через консоль і виконавши команду «show collections»:

# mongo localhost:27017/test -u ossim -p
MongoDB shell версія: 3.2.8
Enter password:
connecting to: localhost:27017/test
> show collections
logger.20160810
logger.20160811
logger.20160812
logger.20160813
logger.20160814
logger.20160815

Спасибі за увагу!
Джерело: Хабрахабр

0 коментарів

Тільки зареєстровані та авторизовані користувачі можуть залишати коментарі.