Рассмотрим пример реализации защиты сетевого периметра с использованием Opensource-решений на базе:
Snort — система обнаружения\предотвращения вторжения (в контексте данной статьи будет рассматриваться как IDS);
OSSEC — хостовая IDS (Host-based intrusion detection system);
Prelude\Prewikka — SIEM-система для обработки и управления событиями (Security information and event management).

В предыдущих статьях, посвященных обеспечению безопасности веб-сайта и сетевого периметра были рассмотрены инструменты nginx-naxsi (web application firewall), fail2ban (сервис блокировки доступа) и snort (IDS). Давайте попробуем соединить все подсистемы воедино, снарядив в довесок SIEM, позволяющей просматривать и анализировать события в удобном виде. Кроме этого, использование подобной системы позволит подготовиться к соответствию со стандартом PCI DSS.

Далее в примерах будут использоваться 3 сервера:
Сервер R — сетевой шлюз;
Сервер WAF — веб-сервер с установленным Nginx-Naxsi и Fail2ban;
Сервер SIEM — сервер просмотра и обработки событий.

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

Установка и настройка Snort

Сервер R

В репозиториях Debian есть уже готовые сборки Snort и Snort-mysql, простые в установке и уже содержащие стандартный набор правил. Минус заключается в том, что правил довольно мало. Расширенный набор правил можно скачать с официального сайта (рекомендуется использовать правила, предоставляемые по платной подписке, содержащие наиболее актуальные сигнатуры атак). Устаревшие версии Snort, находящиеся в репозитории Debian, нам не подойдут, поэтому произведем установку из исходников:

# mkdir -p /opt/src
# cd /opt/src

Установим зависимости. Библиотеку libdnet, необходимую для работы Snort, придется также установить из исходников.


# apt-get install libdaq-dev libpcap-dev libssl-dev libpcre3-dev checkinstall
# wget http://sourceforge.net/projects/libdnet/files/libdnet/libdnet-1.11/libdnet-1.11.tar.gz/download -qO- | tar xvzpf - -C /opt/src
# cd libdnet-1.11 && ./configure && make && checkinstall

Установим Snort:


# wget https://www.snort.org/downloads/snort/snort-2.9.7.3.tar.gz -qO- | tar xvzpf - -C /opt/src
# cd /opt/src/snort-2.9.7.3 && ./configure --enable-sourcefire
# make && checkinstall

Отлично. Теперь необходимо скачать и подключить расширенный набор правил с сайта, предварительно зарегистрировавшись на Snort.org и получив oinkode:


# mkdir -p /etc/snort
# wget https://www.snort.org/rules/snortrules-snapshot-2962.tar.gz?oinkcode=038c3ee32c10a975b466522d823d9e9fa3ffbd2f -qO- | tar xvzpf - -C /etc/snort
# mv /etc/snort/etc/* /etc/snort/ && rm -rf /etc/snort/etc
# cat /etc/passwd | grep snort || useradd snort
# mkdir /var/log/snort && chown -hR snort /var/log/snort

Готово. Переходим к настройке. Укажем диапазон нашей внутренней подсети, пути доступа к правилам и т.д.:

# nano /usr/local/snort/etc/snort.conf

# Setup the network addresses you are protecting
ipvar HOME_NET 192.168.0.0/16

var RULE_PATH ./rules
var SO_RULE_PATH ./so_rules
var PREPROC_RULE_PATH ./preproc_rules

var WHITE_LIST_PATH ./rules
var BLACK_LIST_PATH ./rules

# path to dynamic preprocessor libraries
dynamicpreprocessor directory /usr/local/lib/snort_dynamicpreprocessor

# path to base preprocessor engine
dynamicengine /usr/local/lib/snort_dynamicengine/libsf_engine.so

# path to dynamic rules libraries
dynamicdetection directory /etc/snort/so_rules

Подготовим все необходимо для запуска Snort:


# touch /etc/snort/rules/white_list.rules
# touch /etc/snort/rules/black_list.rules
# chown snort:snort /etc/snort/rules/*.rules
# mkdir -p /var/log/snort
# chown snort:snort /var/log/snort

Проверим конфигурацию:

# snort -T -c /etc/snort/snort.conf

В случае появления ошибки:

snort: error while loading shared libraries: libdnet.1: cannot open shared object file: No such file or directory

сделаем симлинк библиотеки:

# cd /usr/lib/ && ln -s /usr/local/lib/libdnet.1.0.1 libdnet.1

Запускаем Snort:

# snort -c /etc/snort/snort.conf -D -i eth1 -u snort -g snort

Не забудем написать скрипт автозапуска и активизировать его. На этом установка и первичная настройка Snort завершена. Продолжаем.

Установка и настройка SIEM

Сервер SIEM

Произведем настройку Prelude SIEM:


# apt-get install apache2 libmysqlclient-dev make gcc libssl-dev
# apt-get install prelude-manager libprelude-dev

Произведем настройку автозапуска при старте системы:

# nano /etc/default/prelude-manager

RUN=yes

# update-rc.d prelude-manager defaults

И установим Prewikka — веб-интерфейс для удобства просмотра и анализа событий:

# apt-get install prewikka

Теперь нам необходимо настроить vhost на веб-сервере:


# cd /etc/apache2/sites-enabled/
# mv 000-default prewikka

<VirtualHost *:80>
ServerName siem.example.com
Setenv PREWIKKA_CONFIG "/etc/prewikka/prewikka.conf" 

<Location "/">
        Options ExecCGI

        <IfModule mod_mime.c>
                AddHandler cgi-script .cgi
        </IfModule>

        Order allow,deny
        Allow from all
</Location>

Alias /prewikka/ /usr/share/prewikka/htdocs/
ScriptAlias / /usr/share/prewikka/cgi-bin/prewikka.cgi

</VirtualHost>

а также установить права доступа для www-data:

# chown -hR www-data:www-data /etc/prewikka

Перезапускаем веб-сервер:

# /etc/init.d/apache2 restart

По-умолчанию Prewikka производит резолвинг хостов, что не всегда бывает полезным (особенно, если речь идет о секции SRC IP). Чтобы отключить резолв, необходимо выставить параметр -1 в секции dns_max_delay в файле /etc/prewikka/prewikka.conf.

Проверяем работу веб-интерфейса, открыв в браузере http://web_server_ip. Логин\пароль: admin\admin.

Установка и настройка OSSEC HIDS

Сервер SIEM

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


# apt-get install make gcc libssl-dev -y
# wget http://www.ossec.net/files/ossec-hids-2.8.2.tar.gz --user-agent=Mozilla -qO- | tar xvzpf - /tmp
# cd /tmp/ossec-hids-2.8.2/src && make setprelude && ../install.sh

Ответим на вопросы. Рекомендуется отключить active-response, позже, при необходимости, мы всегда сможем его активировать:

1- What kind of installation do you want (server, agent, local, hybrid or help)? server

  - Server installation chosen.

2- Setting up the installation environment.

 - Choose where to install the OSSEC HIDS [/var/ossec]:

    - Installation will be made at  /var/ossec .

3- Configuring the OSSEC HIDS.

  3.1- Do you want e-mail notification? (y/n) [y]: n

   --- Email notification disabled.

  3.2- Do you want to run the integrity check daemon? (y/n) [y]:

   - Running syscheck (integrity check daemon).

  3.3- Do you want to run the rootkit detection engine? (y/n) [y]:

   - Running rootcheck (rootkit detection).

  3.4- Active response allows you to execute a specific
       command based on the events received. For example,
       you can block an IP address or disable access for
       a specific user.
       More information at:
       http://www.ossec.net/en/manual.html#active-response

   - Do you want to enable active response? (y/n) [y]: n

     - Active response disabled.

  3.5- Do you want to enable remote syslog (port 514 udp)? (y/n) [y]: n

Интегрируем OSSEC с Prelude:

# nano /var/ossec/etc/ossec.conf

<global>
    <prelude_output>yes</prelude_output>
    <email_notification>no</email_notification>
</global>

Теперь нужно подключить OSSEC к Prelude. Для этого нам потребуется одновременный доступ к двум консолям. Это можно сделать утилитой screen (запустите screen, CTRL+A CTRL+C создасть новое окно, переключение между окнами осуществляется комбинацией CTRL+A).

Запустим в первой консоли:


# prelude-admin registration-server prelude-manager
а во второй:
# prelude-admin register OSSEC "idmef:w" 127.0.0.1 --uid ossec --gid ossec

Введя одноразовый пароль, получим сообщение об успешной интеграции OSSEC:

Registration request for analyzerID="ХХХХХХХХХХХХХХХХХ" permission="idmef:w".
Approve registration? [y/n]: y
127.0.0.1:56460 successfully registered.

Запустим сервисы:


# /etc/init.d/prelude-manager start
# /etc/init.d/ossec start

Добавление OSSEC-агентов

Существует, как минимум, два способа добавить агента OSSEC — сгенеровать ключ авторизации на сервере или же активировать агента удаленно. Рассмотрим оба варианта.

Вариант 1. Генерация ключа на сервере
На сервере SIEM выполним:

# /var/ossec/bin/manage_agents

- Adding a new agent (use '\q' to return to the main menu).
  Please provide the following:
   * A name for the new agent: ИМЯ_АГЕНТА
   * The IP Address of the new agent: ИП_АГЕНТА
   * An ID for the new agent[001]:

Если процедура производится в первый раз, необходимо перезапустить OSSEC-сервер, чтобы он начал слушать UDP-port 1514:
# /etc/init.d/ossec restart

Извлечем сгенерированный ключ для клиента с помощью опции «E»:
# /var/ossec/bin/manage_agents

укажем ID агента (в данном случае 001) и получим ключ:
Agent key information for ‘001’ is:

MDAxIFIzIDEwLjEuNC4xZZZZZZZZZZjU1NGZhNzY3NmI5N2RiYTU4YjMyZDk1MTEzNTcwMTcZZZZZZZZZZZZZZZZZZZZhhZjY=

Сервер R
Установим и настроим OSSEC-агент:


# wget http://www.ossec.net/files/ossec-hids-2.8.2.tar.gz --user-agent=Mozilla -qO- | tar xvzpf - -C /tmp
# /tmp/ossec-hids-2.8.2/install.sh

1- What kind of installation do you want (server, agent, local, hybrid or help)? agent
3.1- What's the IP Address or hostname of the OSSEC HIDS server?:Укажем IP адрес сервера
  3.2- Do you want to run the integrity check daemon? (y/n) [y]:

   - Running syscheck (integrity check daemon).

  3.3- Do you want to run the rootkit detection engine? (y/n) [y]:

   - Running rootcheck (rootkit detection).

  3.4 - Do you want to enable active response? (y/n) [y]: n

# /var/ossec/bin/manage_agents

Добавим ключ через опцию «I» и перезапустим OSSEC:

# /etc/init.d/ossec restart

Перейдем на сервер SIEM и убедимся, что агент подключился:

# /var/ossec/bin/agent_control -l

OSSEC HIDS agent_control. List of available agents:
   ID: 000, Name: siem.pentestit.ru (server), IP: 127.0.0.1, Active/Local
   ID: 001, Name: R3, IP: 10.1.4.1, Active

Вариант 2. Удаленное подключение агента

Установим на сервере R OSSEC-агент, как это было описано в первом варианте. На сервере SIEM запустим сервис аутентификации агентов с опцией -i (опция при регистрации агента сохраняет его IP-адрес, не допуская подключения с других IP адресов для данного агента):

/var/ossec/bin/ossec-authd -i

Вернемся на сервер R и запустим клиент аутентификации с указанием IP-адреса сервера OSSEC:

/var/ossec/bin/agent-auth -m OSSEC_SERVER_IP

Агент должен успешно пройти аутентификацию на сервере. Обратите внимание, что для приема событий OSSEC слушает подключения на 1514 UDP порту, в то время как модуль авторизации на сервере (при аутентификации вторым методом используется порт 1515 TCP.

Настройка профилей OSSEC

Гибкость OSSEC обеспечивается, в том числе, за счет использования профилей — набора правил для хоста или группы хостов, объединенных по определенным критериям, таких как операционная система, роль и т.д. Рассмотрим пример создания профиля для серверов, использующих Snort в качестве IDS. Для этого создадим на OSSEC-сервере файл, описывающий политику мониторинга логов для подобных серверов.

Сервер SIEM

# nano /var/ossec/etc/shared/agent.conf

<agent_config profile="snort">
    <localfile>
		<log_format>snort-fast</log_format>
        <location>/var/log/snort/alert</location>
    </localfile>
</agent_config>

Мы указали, что для профиля snort необходимо анализировать файл /var/log/snort/alert, имеющий формат snort-fast. Подключим профиль клиенту:
Сервер R

# nano /var/ossec/etc/ossec.conf

<client>
  <server-ip>10.1.4.11</server-ip>
  <config-profile>snort</config-profile>
</client>

# /etc/init.d/ossec restart

Отлично, теперь события Snort будут поступать на сервер SIEM.

По умолчанию, при установке OSSEC-агента, конфиг ossec.conf уже содержит список файлов для мониторинга. Для OSSEC версии 8.1 доступны различные форматы журналов событий, имеющих интуитивно понятное название. С полным списком форматов можно ознакомиться здесь. Помимо стандартных файлов журналов Linux-систем и приложений, доступны такие форматы, как:
snort-full, snort-fast — формат журнала Snort;
eventlog — стандартный формат журнала Windows;
eventchannel — формат журнала Windows, позволяющий обрабатывать не только классические Windows-логи, но и данные из Application and Services (для Windows Vista и старше);
command, full_command — выполнение команды в системе. Выполняется только при указании в ossec.conf на каждом агенте, нельзя передать через agent.conf;
multi-line — позволяет работать с журналами приложений, использующие несколько строг для генерации событий.

Кроме этого, по умолчанию ossec.conf содержит секции по анализу контроля целостности файлов.

События, поступающие от OSSEC-агентов на сервер, сначала проходят обработку пре-декодером, декодером, а после к ним применяется набор правил. Правила расположены в каталоге /var/ossec/rules и должны быть подключены в конфигурационном файле ossec.conf. Все конфигурационные файлы OSSEC имеют формат XML. На этапе пре-декодинга извлекается такая информация, как имя хоста, приложения, сгенерировавшего событие, источник события и т.д.

Декодер событий

Обработка события декодером (/var/ossec/etc/decoder.xml) производится на основе паттернов. Давайте попробуем создать декодер для событий fail2ban.

Оригинальное событие имеет следующий вид:

2015-06-19 00:39:35,920 fail2ban.actions: WARNING [some_waf_rule] Ban 94.XX.8.XX

Чтобы убедиться, что декодера для данного события не существует, обработаем его утилитой ossec-logtest:

# echo '2015-06-19 00:39:35,920 fail2ban.actions: WARNING [some_waf_rule] Ban 94.ХХ.8.ХХ' | /var/ossec/bin/ossec-logtest -a

и получим пустой результат:

2015/06/22 00:18:20 ossec-testrule: INFO: Reading local decoder file.
2015/06/22 00:18:20 ossec-testrule: INFO: Started (pid: 3153).

Опция -a для ossec-logtest выводит только алерт (если паттерн будет найдет в декодере и в правиле), в то время как опция -v/-d предоставит больше информации об обработке.

Создадим декодер, извлекающий из правила Source IP, название правила и действия утилиты fail2ban (Ban\Unban):
# nano /var/ossec/etc/decoder.xml

<decoder name="fail2ban">
<!-- 2015-06-19 01:08:21,688 fail2ban.actions: WARNING [some_waf_rule] Ban 94.ХХ.8.ХХ -->
 <prematch>^20\d\d-\d\d-\d\d \d\d:\d\d:\d\d,\d+ fail2ban.actions: WARNING </prematch>
  <regex>[(\S+)]\s+(\S+)\s+(\S+)</regex>
  <order>extra_data, status, srcip</order>
</decoder>

и повторим обработку:

# echo '2015-06-19 00:39:35,920 fail2ban.actions: WARNING [some_waf_rule] Ban 94.XX.8.XX' | /var/ossec/bin/ossec-logtest -v

...
**Phase 2: Completed decoding.
       decoder: 'fail2ban'
       extra_data: 'some_waf_rule'
       status: 'Ban'
       srcip: '94.XX.8.XX'
...

Отлично. Перейдем к созданию правил.

Итак, мы уже создали декодер для событий fail2ban, давайте попробуем разобраться с правилами OSSEC.

Каждое правило OSSEC имеет свой уникальный идентификатор, правила сгруппированы по их назначению. Более подробную информацию о правилах и о назначении идентифкаторов можно прочитать здесь. Таким образом мы можем использовать идентификаторы в диапазоне от 100000 до 109999 для собственных правил. Кроме этого, правила содержат уровень критичности (level) от 0 до 15. Значение 0 игнорируются, а 15 означает максимальный уровень критичности.

Давайте попробуем создать правило для событий fail2ban:

# nano /var/ossec/rules/local_rules.xml

  <rule id="100003" level="15">
    <decoded_as>fail2ban</decoded_as>
    <match> Ban </match>
    <description>Fail2ban Ban</description>
  </rule>

  <rule id="100004" level="3">
    <decoded_as>fail2ban</decoded_as>
    <match> Unban </match>
    <description>Fail2ban Unban</description>
  </rule>

Первое правило будет сообщать о блокировки, поэтому мы назначили ему максимальный уровень критичности (в Prewikka будет отображаться красным), второе (о разблокировки) с уровнем 3 (синий цвет).

Давайте попробуем создать правило для обработки событий Naxsi, который мы рассматривали в статье, посвященной обеспечению безопасности сайта. Событие имеет следующий вид:

2015/06/19 00:14:11 [error] 1569#0: *8948 NAXSI_FMT: ip=94.XX.8.XX&server=XXX.ru&uri=/wp-admin/admin-ajax.php&learning=1&vers=0.54&total_processed=158&total_blocked=30&block=1&cscore0=$XSS&score0=20&zone0=BODY|NAME&id0=1311&var_name0=data[clef]&zone1=BODY|NAME&id1=1311&var_name1=data[wp-refresh-post-lock][post_id]&zone2=BODY|NAME&id2=1311&var_name2=data[wp-refresh-post-lock][lock], client: 94.XX.8.XX, server: XXX.ru, request: "POST /wp-admin/admin-ajax.php HTTP/1.1", host: "XXX.ru", referrer: "https://XXX.ru/wp-admin/post.php?post=484&action=edit"

Проверим работу правила утилитой ossec-logtest:

# echo '2015/06/19 00:14:11 [error] 1569#0: *8948 NAXSI_FMT: ip=94.ХХ.8.ХХ&server=ХХХ.ru&uri=/wp-admin/admin-ajax.php&learning=1&vers=0.54&total_processed=158&total_blocked=30&block=1&cscore0=$XSS&score0=20&zone0=BODY|NAME&id0=1311&var_name0=data[clef]&zone1=BODY|NAME&id1=1311&var_name1=data[wp-refresh-post-lock][post_id]&zone2=BODY|NAME&id2=1311&var_name2=data[wp-refresh-post-lock][lock], client: 94.ХХ.8.ХХ, server: ХХХ.ru, request: "POST /wp-admin/admin-ajax.php HTTP/1.1", host: "ХХХ.ru", referrer: "https://ХХХ.ru/wp-admin/post.php?post=484&action=edit"' | /var/ossec/bin/ossec-logtest -a

и убедимся, что событие обрабатывается верно:

2015/06/19 00:19:31 ossec-testrule: INFO: Reading local decoder file.
2015/06/19 00:19:31 ossec-testrule: INFO: Started (pid: 19607).
** Alert 1434662371.1: - apache,
2015 Jun 19 00:19:31 siem->stdin
Rule: 31301 (level 3) -> 'Nginx error message.'
Src IP: 94.ХХ.8.ХХ
...

Вывод сообщает нам, что событие после обработки декодером в конечном итоге попадает под правило с идентификатором 31301. Рассмотрим его:

# nano /var/ossec/rules/nginx_rules.xml

<rule id="31301" level="3">
  <if_sid>31300</if_sid>
  <regex>^\S+ \S+ [error] </regex>
  <description>Nginx error message.</description>
</rule>

и дополним новым правилом:

# nano /var/ossec/rules/local_rules.xml

  <rule id="100001" level="5">
    <if_sid>31301</if_sid>
    <match>NAXSI_FMT:</match>
    <description>NAXSI message.</description>
  </rule>

Перезапустим OSSEC:

# /etc/init.d/ossec restart

Проверим:


# echo '2015/06/19 00:14:11 [error] 1569#0: *8948 NAXSI_FMT: ip=94.XX.8.XX&server=XXX.ru&uri=/wp-admin/admin-ajax.php&learning=1&vers=0.54&total_processed=158&total_blocked=30&block=1&cscore0=$XSS&score0=20&zone0=BODY|NAME&id0=1311&var_name0=data[clef]&zone1=BODY|NAME&id1=1311&var_name1=data[wp-refresh-post-lock][post_id]&zone2=BODY|NAME&id2=1311&var_name2=data[wp-refresh-post-lock][lock], client: 94.XX.8.XX, server: XXX.ru, request: "POST /wp-admin/admin-ajax.php HTTP/1.1", host: "XXX.ru", referrer: "https://XXX.ru/wp-admin/post.php?post=484&action=edit"' | /var/ossec/bin/ossec-logtest -a

2015/06/19 00:31:25 ossec-testrule: INFO: Reading local decoder file.
2015/06/19 00:31:25 ossec-testrule: INFO: Started (pid: 20111).
** Alert 1434663085.1: - local,syslog,
2015 Jun 19 00:31:25 siem->stdin
Rule: 100001 (level 5) -> 'NAXSI message.'
Src IP: 94.XX.8.XX
...

Отлично. Теперь события Naxsi будут иметь идентификатор 100001 с уровнем критичности 5.

Предположим, что наш веб-сервер обслуживает несколько виртуальных хостов и мы хотим игнорировать все сообщения Naxsi для виртуального хоста ХХХ1.ru. Такую задачу можно реализовать с помощью правила c уровнем критичности 0:

# nano /var/ossec/rules/local_rules.xml

  <rule id="100002" level="0">
    <if_sid>100001</if_sid>
    <match>server=ХХХ1.ru</match>
    <description>NAXSI for XXX1.ru.</description>
  </rule>

Заключение

Snort не умеет работать с SSL трафиком в нативном режиме. Для контроля SSL-соединений можно использовать дополнение к Snort в виде viewssld.

OSSEC достаточно гибкий инструмент, позволяющий обрабатывать события из различных источников и различного содержания, а также реализовать гибкую политику парсинга событий. К OSSEC-серверу можно подключать как управляемые агенты, так и agentless-устройства, такие как коммутаторы и прочие сетевые устройства, не поддерживающие OSSEC-агенты. Кроме этого, сервер OSSEC можно использовать для удаленного хранения log-файлов. Помимо анализа и обработки событий, OSSEC умеет работать в режиме IPS (используя «active response»): блокировать доступ или же выполнять иные действия.

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

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