Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?

Sorry. This is for Russians only, so no english text.

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

Ура! 29.07.2015 Пройдена проверка апдейтами на бою. Сегодня автоматически обновился из веб-интерфейса на версию 5.1 и ничего не отвалилось. Кстати, версия посимапатичней :)

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

/usr/local/bin
и называются
check_my_config.py
и
check_mysql_config.py
соответственно. А еще в этой же директории обязан лежать файл с именем
my_ParserUtil.tail
который должен начинаться строкой
# my ParserUtil tail
(регистр имеет значение). Это файл предназначен для реализации дополнительных функций в плагинах собственной разработки. По смыслу он именно то, как называется, хвост, который приклеивается к файлу
/usr/share/alienvault/ossim-agent/ParserUtil.py
Позже поясню, почему я так поступил.
Эти скрипты здесь выложены отдельнымы файлами обязательно поместите их на место и обязательно дайте права на исполнение:

chmod 755 /usr/local/bin/check_mysql_config.py
chmod 755 /usr/local/bin/check_my_config.py

Что делают эти скрипты? Первый проверяет, что файл

/etc/mysql/my.cnf
содержит директиву
!includedir /usr/local/etc/mysql/
и если ее нет, то дописывает в конец файла. Второй проверяет, что файл конфигурации плагинов содержит указание на использование кодировки для каждого из них и если его нет, то переписывает файл с указанием кодировки. По умолчанию ставится кодировка cp1251, но в файле есть "словарь исключений", где можно задать кодировки индивидуально. Вы можете поправить этот словарь, как вам надо. Кроме того, второй скрипт проверяет, что файл ParserUtil.py содержит "хвост" и если его там нет, то дописывает.

Начнем потихоньку ломать систему.
Первым делом мы должны установить в системе нужные нам русские локали, а именно UTF-8 и cp1251. Изначально они не установлены. Это делается легко и приятно с помощью команды
#dpkg-reconfigure locales 
не устанавливайте русские локали в качестве системных. Это совершенно не нужно и может вылезти боком. Достаточно, чтобы они просто были. Апдейты OSSIM не меняют эти настройки. Можно к этому больше не возвращаться.
Еще одна вещь, которую можно сделать один раз. Конфигурация FreeTDS. FreeTDS используется в качестве драйвера для доступа к внешним БД в плагинах, которые читают данные из баз (database type plugins) вы должны исправить общую секцию настроек в конфигурационном файле

#/etc/freetds/freetds.conf
[global]
tds version = 7.0
client charset = UTF-8

Этот файл также не изменяется при апдейтах.

Теперь приступим к поправке mySQL
Для начала создадим файл mysql.cnf в каталоге /usr/local/etc/mysql (каталог тоже нужно создать)

# /usr/local/etc/mysql/mysql.cnf
[client]
default-character-set=utf8

[mysqld]
collation-server = utf8_unicode_ci
init-connect='SET collation_connection = utf8_unicode_ci'
character-set-server = utf8

Теперь самое время проверить, что мы поместили в нужное место скрипт check_mysql_config.py и назначили ему права на исполнение. Если проверили то редактируем файл

/etc/init.d/mysql
добавляем запуск нашего скрипта в секцию "start" как показано здесь. Не перепутайте место :)

#
# main()
#

case "${1:-''}" in
  'start')
	sanity_checks;
	# Start daemon
	log_daemon_msg "Starting MySQL (Percona Server) database server" "mysqld"
	if mysqld_status check_alive nowarn; then
	   log_progress_msg "already running"
	   log_end_msg 0
	else
        /usr/local/bin/check_mysql_config.py > /dev/null
  	    "${PERCONA_PREFIX}"/bin/mysqld_safe > /dev/null 2>&1 &

Готово дело. Можем дать с консоли команду /etc/init.d/mysql restart

Теперь займемся улучшением самого OSSIM.
Для этого в двух файлах

/etc/init.d/ossim-server и /etc/init.d/ossim-agent
вставляем одну строчку в одной и той же секции (они одинаковые):

d_start() {
   /usr/local/bin/check_my_config.py > /dev/null

Вот прямо так и ставим первой строкой в секции d_start().
Теперь достаточно дать команду /etc/init.d/ossim-agent restart

Зачем так сделано?
Дело в том, что по меньшей мере с версии 5 в файле конфигурации /etc/ossim/agent/config.cfg можно задать кодировку для каждого плагина простым добавлением конструкции |cp1251 в конце строки с декларацией плагина. Тогда русские буковки можно использовать как в самом тексте файла конфигурации данного плагина, напроимер в регулярных выражениях, так и в данных которые этот плагин обрабатывает. Но эта фича не только не документирована, но и не доделана до конца. При любом апдейте или при включении нового плагина с консоли, короче при любой операции ossim-reconfig, файл конфигурации перезапишется без указания параметра кодировки. По этой причине я и вставил такой вот хак. Последняя команда любого апдейта или реконфига это перезапуск сервисов, поэтому я вставил в скрипты инициации проверку и правку конфигурации. Это сильно облегчило мою жизнь.
Теперь о "хвосте".
Все дело в кастомных функциях, которые можно использовать в плагинах. Существует механизм создания файла с такими функциями и включения его в плагин. Однако он не документирован. В документации никак не описан допустимый синтаксис и только приведены примеры элементарных функций. Не ясно даже можно ли передать функции более одного параметра. Очень похоже, что нельзя. Не понятно, можно ли использовать в таких кастомных функциях объекты и методы из модулей питона, например открывать файлы. Позже я разберусь по исходному коду, как именно парсится файл с описанием кастомных функций и выясню эти вопросы, но пока я решил, что проще дописать собственные функции в файл ParserUtil.py, который содержит набор "стандартных" функций для плагинов.
Вот так и появился "хвост". С хвостом надо обращаться осторожно, все, что вы туда дописываете, надо тщательно отлаживать. И кстати, при написании кода, ни в коем разе не забывайте, что конец строки в linux - это lf, а не cr+lf, как в Windows. Это существенный вопрос. Если пишете код на компе с виндой, не забывайте убедиться в том, что файл сохранен с правильными концами строк. Это умеет делать и MS Visual Studio и FAR.

Пожалуй всё. Есть вопросы - задавайте.

Нет. Не всё. Забыл про геолокацию.
В OSSIM для данных геолокации используется модуль GeoIP и бесплатные базы данных geolite и geolite-city от Maxmind. PurserUtil.py содержит соответсвующие функции, которые можно использовать в плагинах, непосредственно в файлах plugin.cfg.
Но дело в том, что эти базы имеют "устаревший" формат. Maxmid сейчас поставляет базы в новом формате GeoIP2. Мне эти базы нравятся больше. Но в питоне на OSSIM нет модуля для работы с этим форматом. Совсем нет. Видимо это проблема лицензии. Насколько я понял Geolite разработчики могут распространять бесплатно, а Geolite2 - нет. Я не счел нужным прикручивать новые базы к ParserUtil, поскольку собственно в плагинах мне эта геолокация нафиг не нужна. А вот в некоторых отчетах очень даже полезна, например в отчете об удаленном доступе rarep.py. Поэтому, я добавил необходимый модуль. А еще внезапно обнаружилось, что в системе нет любимого всеми установщика пакетов для питона pip. Ну, заодно и его поставим.

 
wget https://bootstrap.pypa.io/get-pip.py --no-check-certificate
python get-pip.py
pip install geoip2

Теперь надо загрузить саму базу вот отсюда

http://geolite.maxmind.com/download/geoip/database/GeoLite2-City.mmdb.gz

распаковать и положить в нужное место

/usr/share/geoip/GeoLite2-City.mmdb

Конечно, GeoLite2 - это не супер-пупер точные данные, но подробные базы GeoIP2 стоят совсем не маленьких денег. Я пока не написал скрипт для автоматического обновления базы. Подкладываю ее вручную.

#! /usr/bin/python
# -*- coding: latin1 -*-
import sys
#import codecs
import subprocess
cfg_path = '/etc/ossim/agent/config.cfg'
new_cfg_path = '/var/local/config.tmp'
encoding_exceptions = {'wmi-monitor':'utf8'}
my_encoding = 'cp1251'
with open (cfg_path,'r') as f:
conf = f.read()
f.close
start_flag = False
continue_flag = True
need_update = False
out_lines=[]
for line in conf.splitlines():
out_lines.append(line.strip())
if start_flag and continue_flag :
if not '=' in out_lines[-1]:
continue_flag = False
elif not '|' in out_lines[-1]:
key = out_lines[-1].split('=')[0]
need_update = True
if key in encoding_exceptions:
out_lines[-1] = out_lines[-1] + '|' + encoding_exceptions[key]
else:
out_lines[-1] = out_lines[-1] + '|' + my_encoding
if '[plugins]' in out_lines[-1]:
start_flag = True
if need_update :
with open(new_cfg_path,'w') as f:
for line in out_lines:
f.write(line + '\n')
f.close
cmd = '/bin/cp -f /etc/ossim/agent/config.cfg /etc/ossim/agent/config.cfg.myreconfig.bak'
p = subprocess.Popen (cmd, shell=True)
p_stutus = p.wait()
cmd = '/bin/cp -f /var/local/config.tmp /etc/ossim/agent/config.cfg'
p = subprocess.Popen (cmd, shell=True)
p_stutus = p.wait()
# check PerserUtil.py
pu_need_update = False
with open ('/usr/share/alienvault/ossim-agent/ParserUtil.py', 'r') as f:
pu=f.read()
f.close()
if not 'my ParserUtil tail' in pu:
cmd = 'cp -f /usr/share/alienvault/ossim-agent/ParserUtil.py /usr/share/alienvault/ossim-agent/ParserUtil.py.myreconfig.bak'
p = subprocess.Popen (cmd, shell=True)
p_stutus = p.wait()
cmd = 'cat /usr/local/bin/my_ParserUtil.tail >> /usr/share/alienvault/ossim-agent/ParserUtil.py'
p = subprocess.Popen (cmd, shell=True)
p_stutus = p.wait()
#! /usr/bin/python
# -*- coding: latin1 -*-
import sys
#import codecs
import subprocess
cfg_path = '/etc/mysql/my.cnf'
with open (cfg_path,'r') as f:
conf = f.read()
f.close
if not '!includedir /usr/local/etc/mysql' in conf:
cmd = 'cp -f /etc/mysql/my.cnf /etc/mysql/my.cnf.myreconfig.bak'
p = subprocess.Popen (cmd, shell=True)
p_stutus = p.wait()
with open (cfg_path,'a') as f:
f.write('\n!includedir /usr/local/etc/mysql\n')
f.close
# my ParserUtil tail
UNWANTED_URLS=[]
with open("/etc/my_ossim/unwanted_urls.list","r") as f:
UNWANTED_URLS=[line.rstrip() for line in f]
f.close()
def my_tmg_web_sid(bsent=0, breceived=0, url='0', uri=''):
if 'Microsoft-Server-ActiveSync' in uri and 'Cmd=Sync' in uri:
sid=2
return sid
sid = 1
if 'in-bank.ru' in url:
return sid
bsent = int(bsent)
breceived = int (breceived)
if bsent > 1000000:
return 2000
if bsent > breceived:
sid = sid + 10
if bsent > 200000:
sid = sid + 100
for elem in UNWANTED_URLS:
dot_elem="."+elem
if elem == url or dot_elem in url:
sid = sid + 1000
break
return sid
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.