Василий Ларин, Security Vision
Система обнаружения вторжений (СОВ) является одним из важных звеньев сетевой безопасности в инфраструктуре компании. Они могут встраиваться в комплекс сложных аппаратных устройств, например, в популярные сейчас межсетевые экраны нового поколения (NGFW), а также могут существовать как самостоятельные средства защиты информации (СЗИ). В данной статье рассказывается про СОВ Zeek. Как правило, Zeek используется для сбора трафика, который будет в последствии анализироваться аналитиками SOC. Но в данной статье показывается, что Zeek можно использовать и как систему предотвращения вторжений путём взаимодействия с различными механизмами безопасности на хосте. Также в статье описывается ещё одно решение – Malcolm, которое тесно связано с Zeek. Malcolm – это система анализа трафика, которая включает в себя такие решения, как Zeek, Suricata, а также компоненты визуализации, показывающие изменения трафика в реальном времени. При правильной настройке Malcolm может стать неплохим и относительно бесплатным решением, которое можно встроить в отдел SOC средней или маленькой компании.
Описание Zeek
Zeek (ранее известен как Bro) - это open-source решение для анализа трафика в сети. Одно из главных преимуществ заключается в том, что Zeek предоставляет большой набор логов. Каждый лог файл содержит в себе определенную сетевую активность: HTTP-сессии, DNS-запросы, TLS-соединения, информацию о TLS-сертификатах и многое другое. В дополнение к журналам, Zeek имеет встроенные функции для ряда задач анализа и обнаружения. Он может извлекать файлы из HTTP-сессий, обнаруживать вредоносное ПО путем взаимодействия с внешними реестрами, сообщать об уязвимых версиях программного обеспечения, обнаруженных в сети, идентифицировать популярные веб-сайты, приложения и многое другое.
Помимо такой мощной функциональности «из коробки», Zeek представляет собой полностью настраиваемую и расширяемую платформу для анализа трафика. Zeek предоставляет пользователям предметно-ориентированный язык сценариев для решения произвольных аналитических задач. Zeek работает на стандартном оборудовании и, следовательно, представляет собой хорошую альтернативу дорогим решениям. Zeek специально ориентирован на высокоскоростной мониторинг сети в больших объемах. Zeek написан на языке С++ и распространяется под лицензией BSD.
Архитектура Zeek
Рис. 1 Архитектура Zeek
Архитектура Zeek разделена на два основных компонента. Первый компонент – это event engine (движок событий). Он помогает разделить сетевой пакет на несколько высокоуровневых событий. Эти события отражают сетевую активность, т.е. они описывают то, что было замечено в сетевом пакете. Компонент event engine включает в себя ряд подкомпонентов: источники ввода, анализ пакетов, анализ сессий и анализ файлов. Анализ пакетов обрабатывает протоколы более низкого уровня, начиная с канального уровня. При анализе сессий проверяются протоколы прикладного уровня, такие как HTTP, FTP и т.д. При анализе файлов анализируется содержимое файлов, передаваемых во время сессии. Движок событий предоставляет архитектуру плагинов, которые позволяют расширять возможности Zeek по мере необходимости.
Вторым основным компонентом Zeek является интерпретатор сценариев, который выполняет набор обработчиков событий, написанных на скриптовом языке Zeek. Данные скрипты могут мониторить разную активность в сети и в процессе, например, выполнить внешнюю программу (создать блокирующее правило в межсетевом экране).
Мониторинг сетевой активности с помощью Zeek
Zeek предназначен для просмотра сетевого трафика в режиме реального времени. Хотя Zeek может обрабатывать перехваченные пакеты, сохраненные в формате PCAP, большинство пользователей используют Zeek для прослушивания одного или несколько сетевых интерфейсов, получая соответствующие логи, а также содержимое извлеченных файлов.
В учебных целях пользователи могут запустить Zeek на отдельном компьютере, используемом для общих вычислительных целей, и отслеживать сетевой трафик, проходящий через этот компьютер. Это простой способ ознакомиться с журналами, которые создает Zeek. Этот подход аналогичен запуску Tcpdump или Wireshark на компьютере.
Сотрудники ИБ называют его «сенсором» и развертывают специально для наблюдения за сетевым трафиком.
Установка Zeek
Официальное сообщество разработчиков Zeek предоставляет большой набор вариантов установки на ОС Linux: установка официального образа docker, установка с помощью бинарных пакетов, либо сборка из исходников.
В данной статье рассматривается способ установки через бинарные пакеты для ОС Debian 12. Для установки Zeek необходимо в source.list.d прописать путь до официального репозитория Zeek, а также добавить публичный ключ.
echo 'deb http://download.opensuse.org/repositories/security:/zeek/Debian_12/ /' | sudo tee /etc/apt/sources.list.d/security:zeek.list
curl -fsSL https://download.opensuse.org/repositories/security:/zeek/Debian_12/Release.key | gpg --dearmor | sudo tee /etc/apt/trusted.gpg.d/security_zeek.gpg > /dev/null
sudo apt update
sudo apt install zeek-7.0.5
Для установки другими способами можно посмотреть на официальном сайте.
Работа с Zeek
Для запуска в командной строке Zeek можно выполнить такую команду, которая прослушивает трафик на интерфейсе: zeek –i eth0. Далее после начала прослушивания сетевого трафика, Zeek начинает писать логи в папку, в которой он запущен.
Теперь подробнее рассмотрим, какие логи могут встретиться. Zeek может писать следующие логи по умолчанию «из коробки»:
· conn.log
· dns.log
· http.log
· files.log
· ftp.log
· ssl.log
· x509.log
· smtp.log
· ssh.log
· pe.log
· dhcp.log
· ntp.log
· SMB Logs (plus DCE-RPC, Kerberos, NTLM)
· irc.log
· ldap.log and ldap_search.log
· postgresql.log
· quic.log
· rdp.log
· traceroute.log
· tunnel.log
· dpd.log
· known_*.log and software.log
· weird.log and notice.log
· capture_loss.log and reporter.log
Одним из главных файлов является conn.log. В нём содержится информация о соединениях транспортного уровня (TCP и UDP). Вся информация содержится в типе record Conn::Info. Эта структура очень похожа на структуру языка C.
По умолчанию логи записываются в табличном варианте в текстовый файл, который не очень удобен для анализа. Для начала рассмотрим логи в формате JSON, а потом в табличном. Чтобы получить записи трафика в формате JSON, необходимо выполнить следующую команду:
zeek -i enp0s3 LogAscii::use_json=T
Рис. 2 Логи в формате JSON
Теперь в табличном (по умолчанию).
Рис. 3 Логи в табличном формате
Ts – это время получения первого пакета, duration – показывает, как долго длилось соединение, proto – протокол транспортного уровня, conn_state – значение соединения (SF – это соединение установленное и уже завершенное), local_orig – логическое значение (T или F), которое показывает локальное (T) ли соединение или удаленное (F), local_resp - логическое значение (T или F), которое показывает ответ из локальной сети (T) или из удаленной (F).
В файле Ssl.log показан зашифрованный трафик.
Рис. 4 Пример ssl.log в формате JSON
Одной из мощных функций Zeek является возможность извлекать контент из сетевого трафика и записывать его на диск в виде файла с помощью плагина File Analysis. File.log - это запись о файлах, которые Zeek просматривал при проверке сетевого трафика. Аналитики должны настроить Zeek на извлечение файлов по типам, чтобы в последствии записать их на диск.
Пример получения файла с документации Zeek:
Рис. 5 Пример лога files.log
Про остальные логи более подробно описано в документации.
Применение скриптов для анализа трафика
Скрипты можно запускать из командной строки. Например, zeek –i enp0s8 /home/vas/zeekScript/scripts/main.zeek. В этой команде передаётся дополнительный скрипт помимо скриптов по умолчанию для более подробного анализа трафика.
Этот скрипт анализирует протокол TLS для того, чтобы узнать, какие сайты посещает пользователь. Также в скрипте прописан фильтр, который позволяет блокировать соединения пользователя при посещении определённых сайтов. Блокировка осуществляется путём вызова внешних команд, в данном случае утилиты iptables. С помощью iptables создаются правила для МЭ Netfilter с использованием модуля nDPI.
Скрипт для Zeek можно создать с помощью команды:
zkg create --packagedir <zeekApp>
После выполнения создается папка со скриптом, тестами и другой служебной информацией. В папке /scripts есть файл __load__.zeek - в него подключаются другие скрипты, а также файл main.zeek. В main.zeek пишется основной код программы.
Давайте рассмотрим его подробнее.
Листинг __load__.zeek
@load base/protocols/ssh
@load base/protocols/ssl
@load base/frameworks/netcontrol
@load policy/frameworks/netcontrol/catch-and-release.zeek
@load base/utils/exec.zeek
@load ./main
Листинг main.zeek
module App;
export {
# Create an ID for our new stream. By convention, this is
# called "LOG".
redef enum Log::ID += { LOG };
# Define the record type that will contain the data to log.
type Info: record {
time_hum: string &log;
id: conn_id &log;
server_name: string &log &optional;
};
}
event NetControl::init(){
local debug_plugin = NetControl::create_debug(T);
NetControl::activate(debug_plugin, 0);
}
event NetControl::log_netcontrol(rec: NetControl::Info){
print rec;
if (rec?$cmd==T && rec$cmd=="ADD" && rec$state==NetControl::SUCCEEDED && rec?$action==T && rec$action=="NetControl::DROP" && rec$entity_type=="NetControl::ADDRESS" && rec$target==NetControl::FORWARD){
local ipAdd=rec$entity;
when[ipAdd]((local resultAdd = Exec::run([$cmd="iptables -A FORWARD -j LOG --log-prefix=\"vk req from "+ipAdd+"\" && iptables -A FORWARD -m ndpi --proto vk -j DROP"])) && resultAdd$exit_code==0)
{
;
}
timeout 5sec
{
print "timeout";
}
}
if (rec?$cmd==T && rec$cmd=="REMOVE" && rec?$expire==T && interval_to_double(rec$expire)!=0.0 && rec$state==NetControl::SUCCEEDED && rec?$action==T && rec$action=="NetControl::DROP" && rec$entity_type=="NetControl::ADDRESS" && rec$target==NetControl::FORWARD){
local ipRemove=rec$entity;
when[ipRemove]((local resultRemove = Exec::run([$cmd="iptables -D FORWARD -j LOG --log-prefix=\"vk req from "+ipRemove+"\" && iptables -D FORWARD -m ndpi --proto vk -j DROP"])) && resultRemove$exit_code==0)
{
;
}
timeout 5sec
{
print "timeout";
}
}
}
event ssl_established(c: connection)
{
local format:string = "%F, %H:%M:%S";
Log::write(App::LOG, [$time_hum=strftime(format,network_time()),$id=c$id, $server_name=c$ssl$server_name]);
print fmt("A new ssl connection %s", c$ssl$server_name);
if ( c$ssl$server_name == "vk.ru" ) {
NetControl::drop_address(c$id$orig_h, 20sec);
print fmt("2A new ssl connection %s", c$id);
print fmt("3A new ssl connection %s", c$ssl$server_name);
}
}
event zeek_init()
{
Log::create_stream(App::LOG, [$columns=App::Info, $path="app"]);
}
Ключевое слово export нужно для объявления структуры (тип record) Info, к которой можно обращаться из разных модулей с указанием модуля, в котором она находится через двоеточие. В данному случае App:Info. Структура содержит три поля: time_hum, id и server_name. Server_name равно значению Server Name Indication (SNI), полученное из протокола TLS.
Также там есть ключевое слово redef, которое применятся для добавления новых констант в перечисление (enum). В данном случае это нужно для создания еще одного лог файла под названием app.log.
Далее идут особые функции с ключевым словом event. Они отличаются от функций следующими аспектами:
· Они могут быть запланированы по расписанию и выполнены позднее, так что их эффект может не проявиться непосредственно после их вызова.
· Они не возвращают значения, поскольку они не вызываются напрямую, а скорее запланированы для последующего выполнения.
· Zeek_init() – главная функция, которая стартует, как запускается Zeek.
В zeek_init() – создается новый поток ведения журнала с фильтром по умолчанию с помощью функции create_stream. Она принимает первым параметром id, который будет ассоциирован с новым потоком логирования. Втором параметром передаётся структура, в которую будут писаться логи после анализа сетевого трафика. Таким образом, в модуле App появляется новый поток логирования. Также в структуре (type Info: record) необходимо указывать атрибут &log для каждого поля структуры, иначе эти поля не попадут в поток. Наконец, чтобы оправить данные в поток необходимо вызвать функцию Log::write, которая запишет структуру с заполненными полями.
Рассмотрим следующий event - NetControl::init(), который будет идти сразу после zeek_init(). NetControl – это фреймворк для взаимодействия с маршрутизаторами, межсетевыми экранами и другими сетевыми устройствами.
Рис. 6 Архитектура NetControl
Базовая архитектура NetControl показана на рисунке выше. NetControl находится между пользовательскими скриптами (которые используют механизм событий (event)) и сетевым устройством (которое может быть как аппаратным, так и программным), используемым для реализации команд. NetControl поддерживает ряд высокоуровневых вызовов, таких как функция NetControl::drop_address или синтаксис правил более низкого уровня. После добавления правила в NetControl, он отправляет его на один или несколько своих backend серверов. Каждый backend сервер отвечает за взаимодействие с одним аппаратным или программным устройством. NetControl отслеживает правила на протяжении всего их жизненного цикла и сообщает о состоянии (например, об успешном выполнении, сбое или таймауте) пользовательским скриптам.
Для того, чтобы использовать NetControl должен быть включен хоть один backend сервер. В нашем случае мы будем использовать debug плагин, который все действия выводит в стандартный поток вывода. Backend инициализируется в NetControl::init(), вызывая функцию activate, принимающую аргументы: backend и значение приоритета вызова.
Событие NetControl::log_netcontrol срабатывает после выполнения функций или событий (event), принадлежащих фреймворку NetControl. В этом событии анализируется структура NetControl::Info. Проверяются два условия:
1. В первом условие проверятся успешное добавление правила с действием Drop по направлению FORWARD, то есть сетевые пакеты, идущие транзитом через сенсор. Если условие срабатывает, то в системе создается два правила МЭ с помощью утилиты iptables. Одно из них предназначено для создания записи в syslog о блокировании. Второе правило блокирует с помощью модуля nDPI.
2. Если пришло время удалять правило, то тогда срабатывает второе условие. Время определяется условием (rec?$expire==T && interval_to_double(rec$expire)!=0.0). В этом случае удаляются правила из МЭ, которые были созданы ранее через определённое время. В данном случае это время указано в функции NetControl::drop_address(c$id$orig_h, 20sec), то есть удаляются через 20 секунд.
Осталось последнее событие – это event ssl_established(c: connection). В нём перехватываются TLS соединения, которые впоследствии пишутся в лог app.log. Заполняются поля структуры: время, переведенное в человеко- читаемый вид, id, которое берется из TLS connection, а также server_name – SNI. Далее идёт условие, в котором проверяется SNI, равное vk.ru, если совпадает, то доступ блокируется на 20 секунд, как было описано выше. Также значение времени можно установить равным, например, 0 sec. В таком случае правило будет установлено без временных ограничений.
Схема сети, в которой была протестирована работа Zeek.
Рис. 7 Схема сети
На маршрутизаторе R2 стоял Zeek – сенсор. Он прослушивает интерфейс enp0s8. На маршрутизаторе R1 прописан маршрут до сети 192.168.11.0/24 через 192.168.1.101. Также необходимо создать правило на R2: iptables –t nat –A POSTROUTING –o enp0s3 –s 192.168.11.0/24 –j MASQUERADE. В качестве R2 была взята обычная машина с ОС Debian, на которой был настроена маршрутизация сетевых пакетов.
Рис. 8 Созданные блокирующие трафик правила
Рис. 9 Логи файла app.log
Как видно из лог-файла, Zeek успешно анализирует TLS трафик. Также NetControl пишет свой лог файл. В нём пишется информация о добавленных правилах, удаленных, а также о инициализации плагина.
Рис. 10 Записи в файле netcontrol.log
Описание Malcolm
Malcolm - инструмент с открытым исходным кодом для анализа и визуализации трафика. Принимает данные о сетевом трафике в формате дампов трафика (PCAP), логов Zeek и алертов Suricata. Данные автоматически нормализуются, обогащаются и коррелируются для анализа.
Обзор сетевых коммуникаций обеспечивается через два интуитивно понятных интерфейса: OpenSearch Dashboards, Arkime. Первый – это гибкий плагин визуализации данных с десятками готовых панелей мониторинга, обеспечивающий краткий обзор сетевых протоколов. Arkime — мощный инструмент для поиска и идентификации сессий, содержащих подозрительные инциденты безопасности.
Malcolm работает как кластер программных контейнеров – изолированных «песочниц», каждая из которых выполняет определенную функцию системы. Эта модель содержит простые скрипты для настройки и управления, поэтому Malcolm подходит для быстрого развертывания на различных платформах.
Передача логов в Malcolm, взаимодействие с веб-интерфейсом, осуществляется через защищенные каналы связи.
По сути он является объединением других распространенных инструментов, таких как: Zeek, Arkime, Moloch, Elasticsearch, Logstash, Filebeat, Kibana, ClamAV, Docker и другие.
Кратко опишем основные компоненты Malcolm:
· OpenSearch – ПО, которое позволяет проводить поиск и анализ метаданных в сетевом трафике.
· Logstash, Filebeat – ПО для разбора zeek логов и загрузки их в OpenSearch в формате, понятном Arkime.
· OpenSearch Dashboards – ПО для создания дополнительных специальных визуализаций и панелей мониторинга, помимо тех, что предоставляются Arkime viewer.
· Zeek – система обнаружения вторжений.
· Suricata – СОВ со встроенным движком обнаружения угроз.
· Yara – ПО, которое позволяет создавать правила для обнаружения вредоносных файлов.
· Capa – ПО, которое исследует исполняемые файлы, а после выдает подробный результат.
· ClamAV – антивирус для сканирования файлов, которые zeek извлёк из сетевого трафика.
· CyberChef – веб-приложение для шифрования, кодирования, сжатия и анализа данных.
· NetBox – ПО для моделирования и документирования сетевой карты.
· Nginx – reverse-proxy для доступа к компонентам Malcolm.
· GeoLite2 – база данных для определения местоположения ip.
Для наглядности разработчики предоставили таблицу компонентов, которые наполняют Malcolm.
Рис. 11 Компоненты экосистемы Malcolm
Установка Malcolm
Для установки Malcolm необходимо склонировать официальный репозиторий. Далее перейти в папку scripts и запустить файл install.py. В процессе конфигурирования будут заданы вопросы с выборами ответов да/нет. Более подробно они описаны в документации. После необходимо создать пользователя сервера Nginx для доступа в веб-консоль управления и ещё создать самоподписанные сертификаты. Все это делается с помощью скриптов, которые предоставляют разработчики Malcolm. После скачиваем образы docker.
Это может занять некоторое время. Далее с помощью всё тех же скриптов запускаем Malcolm.
Malcolm требует много ресурсов. Для минимальной работы ему нужно 16 ГБ оперативной памяти и 8 ядер процессора, согласно документации Elasticsearch. После установки и запуска Malcolm готов для полноценного исследования сетевых пакетов, сессий.
Рис. 12 Контейнеры, наполняющие Malcolm
Malcolm позволяет анализировать трафик в реальном времени, который идет на определённом интерфейсе. Так как в него входит модуль Zeek, то большинство лог файлов представлены в формате zeek, которые мы рассмотрели выше.
Рис. 13 Сводная информация о ситуации в сети
Malcolm предоставляет около 12 предустановленных информационных панелей (Dashboards). Например, есть информационная панель – соединения, которая показывает различные соединения, установленные за определенный промежуток времени. Можно распределить соединения по различным атрибутам, например, по источнику ip-адреса, по назначению ip-адреса, по протоколу, по GeoIP и другим.
Рис. 14 Сводная информация о соединениях из различных стран по протоколам
На рисунке 14 представлены на круговых диаграммах протоколы, а внизу подписаны страны.
На самом деле Malcolm предоставляет очень много визуализации. Можно также создать свою.
Arkime
В начальной конфигурации Arkime извлекают всю информацию о сессиях. При открытии Malcolm отображаются текущие сессии. Их можно фильтровать, например, по Zeek, Suricata фильтрам.
Рис. 15 Фильтрация сессий в Akrime
В connections можно посмотреть граф взаимодействия сетевых машин между собой. Также можно устанавливать фильтры по сессиям, которые будут отображать взаимодействие внутренних хостов с другими внутренними или внешними хостами. Отметим, что данный модуль требует много ресурсов.
Рис. 16 Отображение соединений по фильтру zeek.
Передача Zeek логов по протоколу Syslog
В начале статьи, где рассказывалось про Zeek, было настроено логирование TLS-сессий. В лог файл писалась информация о том, какие сайты посещает пользователь и в какое время. Данную информацию можно передать в Malcolm, например, по протоколу syslog. Для этого необходимо настроить rsyslog на клиенте, а при конфигурации Malcolm не забыть назначить порты для syslog (udp или tcp).
Сначала настроим передачу логов на удаленный сервер. Поэтому напишем следующий конфиг для rsyslog:
Рис. 17 Настройки rsyslog
В данном случае rsyslog считывает файл app.log и передаёт по протоколу udp на Malcolm сервер.
Для настройки в Malcolm syslog сервера необходимо в процессе конфигурации выбрать ответ на вопрос “Should Malcolm accept logs and metrics from a Hedgehog Linux sensor or other forwarder?” - customize. После задать udp/tcp порты для rsyslog. Также данные можно изменить в filebeat.env в папке config и перезагрузить Malcolm.
После настройки логи начнут отправляться на сервер Malcolm. Карта сети представлена на рисунке 18 ниже.
Рис. 18 Схема сети с Syslog сервером
Рис. 19 Соединение между Syslog сервером и клиентом
На данном графе можно увидеть какие клиенты отправляют логи по syslog.
Рис. 20 Сессии в модуле Arkime
Во вкладке сессии видно какая информация передаётся по протоколу syslog. Видно время обращение, с какого ip-адреса сделано обращение, порта.
Использование рассмотренных решений с продуктами Security Vision
Логи СОВ Zeek можно передавать, например, по протоколу syslog в NGSOAR. После попадания логов в NGSOAR, из них извлекается важная информация: название протокола, порты, ip-адреса источника и назначения, название приложения и так далее. Данная информация обрабатывается правилами корреляции, которые в случае срабатывания создают инцидент для последующего анализа аналитиками.
Выводы
В заключение хочется сказать, что было рассмотрено два механизма анализа трафика, причём каждый из них по-своему уникален. Zeek позволяет нам не только анализировать логи, а ещё включить способы реагирования на возросшую сетевую активность путём написания различных скриптов, например, для анализа и последующего блокирования сессий.
Второе решение Malcolm включает в себя массу свободного программного обеспечения по анализу и визуализации сетевой активности. Оно может стать одним из ключевых элементов в сетевой топологии, проверяя не только проходящий трафик, а также собирая его с других устройств. Но перед внедрением Malcolm необходимо позаботиться о достаточном количестве оперативной памяти.