Всем привет!
Моя работа связана с анализом сетевого трафика и написанием детектирующих правил Suricata. Я хочу поделиться с Вами опытом работы с данным инструментом. В рамках цикла статей разберёмся в тонкостях работы этого ids/ips решения, научимся писать сигнатурные правила, а также понимать как их писать для выявления нелегитимной активности.
Базовую информацию об инструменте (каким образом Suricata анализирует пакеты, чем она лучше Snort, какие модули захвата может использовать) Вы сможете и без меня найти на просторах интернета. Также предполагаю, что у Вас есть базовые знания по сетям и умеете пользоваться Wireshark-ом.
Теорию буду рассказывать по ходу изложения текста – приступим сразу к практике:
Как-то мне подсказали один интересный и полезный инструмент для тестирования Suricata — Dalton. Можно было бы установить только Suricata и через терминал запускать ее. Dalton мне приглянулся наличием веб интерфейса и удобством тестирования правил на пкапах. Соответственно хочу и Вас познакомить с ним.
Установка Dalton
Dalton будем ставить на виртуалке убунте. Итак, ставим убунту и выделяем для нее 2 интерфейса (первый интерфейс с типом NAT, а второй интерфейс с типом доступа «Сетевой мост»). Выделите для нее 4 гига оперативки, 2 ядра и 50 гб постоянной памяти.
Как поставите убунту, установите сразу гостевые дополнения, wireshark и git, а далее следуете нижеописанным инструкциям:
root@ sam-VirtualBox:/home/sam/Desktop/# git clone https://github.com/secureworks/dalton.git
ставим докер:
root@sam-VirtualBox:/home/sam/Desktop/dalton# apt install ca-certificates curl
root@sam-VirtualBox:/home/sam/Desktop/dalton# install -m 0755 -d /etc/apt/keyrings
root@sam-VirtualBox:/home/sam/Desktop/dalton# sudo curl -fsSL https://download.docker.com/linux/ubuntu/gpg -o /etc/apt/keyrings/docker.asc
root@sam-VirtualBox:/home/sam/Desktop/dalton# chmod a+r /etc/apt/keyrings/docker.asc root@sam-VirtualBox:/home/sam/Desktop/dalton# echo \
«deb [arch=$(dpkg —print-architecture) signed-by=/etc/apt/keyrings/docker.asc] https://download.docker.com/linux/ubuntu \ $(. /etc/os-release && echo «${UBUNTU_CODENAME:-$VERSION_CODENAME}») stable» | \ sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
root@sam-VirtualBox:/home/sam/Desktop/dalton# apt-get update
root@sam-VirtualBox:/home/sam/Desktop# sudo apt-get install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
Проверяем, что докер поставился и всё чётко:
root@sam-VirtualBox:/home/sam/Desktop# sudo docker run hello-world
root@sam-VirtualBox:/home/sam# curl -L «https://github.com/docker/compose/releases/latest/download/docker-compose-$(uname -s)-$(uname -m)» -o /usr/local/docker-compose
root@sam-VirtualBox:/home/sam# chmod +x /usr/bin/docker-compose
root@sam-VirtualBox:/home/sam# docker-compose –version
Далее идем в файл root@sam-VirtualBox:/home/sam/Desktop/dalton# nano docker-compose.yml и комментируем строчки, которые относятся к инсталляции Snort (потому что Snort из РФ не скачать).

Далее выполняем скрипт по инструкции репозитория далтона: root@sam-VirtualBox:/home/sam/Desktop#./start-dalton.sh в конце будет вот так:

Помните, что у нас 2 интерфейса на виртуалке?! – на том интерфейсе, который с типом «сетевой мост» установите статический ip-адрес из вашей локальной сети компьютера. Таким образом Вы сможете заходить в утилиту Dalton просто введя адрес http://192.168.1.150/dalton/ в браузере вашей хостовой машины. А виртуалку просто свернуть (при необходимости – мы ее используем).
Также на данном моменте не забудьте сделать снимок состояния машины. Потому что докер потом может заполонить место и если не получится норм расчистить, то можно будет просто вернуться в исходное состояние. Знаю, возникает мысль а зачем тогда ставить десктопную версию убунты, можно было бы и серверную CLI поставить и с локального хоста работать — нуууу решил так. В любом случае гайд есть и можно аналогично сделать и с версией ubuntu server.
На момент написания статьи была установлена Suricata версии 8.0.1
Итог успешной установки:

Что делать с Dalton-ом
Давайте проведём некий экскурс Dalton-а. Зайдя на главную страницу, давайте перейдем в Suricata через кнопку «Go»:

Итак, мы видим: есть возможность выбрать файл с пкапом для загрузки и тестирования. Можно выбрать несколько пкапов. Версию Suricata оставим 8. «Use a difined ruleset» — будем выключать. Для тестирования собственных правил, необходимо будет поставить галочку на «Use custom rules», откроется окошко куда и будем записывать правила. Другие настройки не трогаем. При запуске Suricat-ы нам необходимо будет выбрать pcap, написать правило и нажать на кнопку «Submit». А во вкладке «Config Files» можно найти файл конфигурации сурикаты:

Всё обучение будет ссылаться на документацию.
Наш путь по изучению Suricata мы начнем с 8 пункта 1 подпункта вышеуказанной документации.
Формат правила

Красным цветом выделено действие, которое Suricata должна будет предпринять в случае совпадения фрагмента трафика с условиями правила. Действия бывают следующими:
alert — генерирует алерт.
pass — останавливает дальнейший разбор сессии/пакета.
drop — отбрасывает пакеты и генерирует алерт.
reject — отправляет RST/ICMP ошибку недоступности получателю, на пакет которого возникла сработка.
rejectsrc — то же что и reject.
rejectdst — отправляет RST/ICMP ошибку недоступности отправителю, на пакет которого возникла сработка.
rejectboth — отправляет RST/ICMP ошибку недоступности обоим участникам сетевого взаимодействия.
Хочу обратить Ваше внимание, что если suricata НЕ настроена на работу в режиме IPS, то работать будут alert и pass. В рамках моего обучения будет затронута в основном функция alert.
Далее разберём выделенное зелёным цветом «http $HOME_NET any → $EXTERNAL_NET any». Сначала указывается протокол (не буду здесь перечислять возможные протоколы, которые может определять suricata, посмотрите в документации), а далее указывается информация об участниках соединения. Схема следующая: адрес_источника порт_источника → адрес_получателя порт_получателя. Что адреса, что порты можно указывать в единственном числе: перечислить либо через переменные.
Примеры:
$HOME_NET any → $EXTERNAL_NET 123
!1.1.1.1 any → 2.2.2.2 $ORACLE_PORTS
[1.1.1.1, 1.1.1.2] any -> $EXTERNAL_NET [80, 81, 82]
Переменные задаются в конфигурационном файле:

Вы сами можете создавать свои переменные и вносить в них ip‑адреса, подсети, порты.
А теперь важный символ — направление «→». Здесь остановимся, и немного подробнее поговорим о направлении соединения. В сети у нас всегда есть инициатор и получатель.

Так вот знак направления «->» устанавливает совпадение сигнатуры по направлению потока пакетов. Важно уметь подразделять понятия: «пакеты», «сессия» — и понимать разницу:
-
Сессия — определение установленного соединения между двумя узлами сети. По большей части касается протокола TCP, который гарантирует доставку данных.
-
Пакеты — некий структурированный блок данных, на который разбивается информация для передачи по сети.
В данном случае мы говорим о направлении потока пакетов. Соответственно если мы выставим условие в правиле 1.2.3.4 -> 5.6.7.8, то сигнатура будет определять совпадения по пакетам, идущим по направлению только от клиента 1.2.3.4 к серверу 5.6.7.8.
Также нужно понимать, что в рамках сессии между двумя участниками сети, пакеты могут идти в обоих направлениях. Давайте поясним, опять обратимся к вышеуказанной схеме где клиент 1.2.3.4 иницирует соединение к серверу 5.6.7.8. Если мы рассматриваем соединение по протоколу UDP, то пакеты в рамках одного соединения будут идти только в направлении от клиента к серверу. Если мы рассматриваем ситуацию, когда клиент инициирует соединение к серверу по протоколу TCP, то у них уже устанавливается TCP сессия. А в рамках установленной TCP сессии хосты друг другу отправляют пакеты для подтверждения данных. Соответственно, при инициировании соединения клиента к серверу по протоколу TCP, направление пакетов может быть как от клиента к серверу, так и от сервера к клиенту, в рамках их TCP сессии. Направление пакета определяется по его заголовкам, где указывается отправитель и получатель. Отправителем и получателем может быть любой участник сетевого взаимодействия, будь это клиент или сервер в рамках TCP-сессии. В дальнейшем с практикой мы закрепим эти знания
Важно замечание: обратного обозначения направления «<-» suricata не поддерживает.
Возможные варианты:
source -> destination – будут совпадать пакеты с таким направлением
source => destination – относительно новая функция, на момент написания статьи. Работает также как и вышеуказанная, но может работать и с двунаправленным соединением.
source <> destination – будут совпадения двунаправленые.
Далее, после указания участников сети, у нас идут условия правила (выделено синим цветом).
Давайте посмотрим как пишутся правила, как правильно ставить получателя и источника сетевого взаимодействия, как ставить направление и так далее…. Разберемся с базовыми понятиями, так сказать. Идем сюда и скачиваем http.cap. Откройте его в wireshark, зайдите в далтон в раздел сурикаты, выберите этот пкап через кнопку «Выбрать файл».
Просмотрите внимательно пкап:

У нас два участника сети 145.254.160[.]237 и 65.208.228[.]223. Давайте напишем правило на http-запрос:
alert tcp 145.254.160.237 any -> 65.208.228.223 80 (msg:»Test Http request»; content:»GET»; content:»download.html»; sid:1;)
Кратко по работе правила: сигнатура генерирует алерт на TCP соединение от 145.254.160.237 к 65.208.228.223 по 80 порту. Как нам известно, транспортный протокол 4 уровня модели OSI используется для гарантированной передачи данных от отправителя получателю. Соответственно в TCP пакетах в полезной нагрузке передаются HTTP-запросы (как в нашем примере). А мы через модификатор content ищем «GET» и «download.html» в полезной нагрузке. Тем самым просим suricata сгенерировать алерт, при нахождении последовательности симовлов GET и “download.html” в полезной нагрузке, с хоста 145.254.160[.]237 на хост 65.208.228.223 по 80 порту.
Давайте запустим правило и посмотрим сработки. Копируем вышеуказанное правило и вставляем в окошко под фразой «Use custom rules». И не забудьте галочку поставить. Жмем на «submit».
У нас 1 алерт:

Перейдем во вкладку «Alert Debug». Там мы можем увидеть распаршенные логи и посмотреть сработки.

Здесь как раз таки доступно много полезной информации. Опишу ключевые поля:
PCAP PKT NUM — номер пакета в pcap-e, на который сработала сигнатура. Это значение доступно, когда suricata запускается при проверке pcap-файла с трафиком для того чтобы выполнять поиск в дампе трафика в Wireshark. По крайней мере, так написано в документации, но если мы посмотрим на 7 фрейм в ваершарке, то увидим, что в нем нет полезной нагрузки с HTTP запросом. Но 7 фрейм (пакет) относится к TCP-сессии, в рамках которой производился HTTP-запрос и есть фрагмент сработки по нашей сигнатуре. Номер сработавшего пакета нам подскажет id сессии, где в последствии можно будет целиком ее изучить;
SRC IP,DST IP — ip источника и получателя пакета соответственно;
SRC PORT, DST PORT — порт источника и получателя пакета соответственно;
TCP SEQ, TCP ACK — TCP sequence и acknowledgement number соответственно в пакете, на который сработала сигнатура;
FLOW — поле, в котором содержится информация о том в каком направлении шел пакет: от сервера к клиенту или от клиента к серверу. В нашем случае от клиента к серверу (to_server: TRUE);
ALERT CNT — количество алертов или сработавших правил на пакет/сессию;
ALERT SID — SID сработавшего правила;
ALERT MSG — наименование сработавшего правила;
PACKET — здесь представляется пакет в ASCII. Как если бы вы смотрели в Wireshark в область по байтового представления пакета;
STREAM DATA — здесь представляется часть TCP-потока, на который была вызвана сработка. Как ее посмотреть? Откройте Wireshark нажмите по 7 фрейму правой кнопкой мыши и нажмите Отслеживать -> TCP-поток. Ниже на картинке выделил какая часть STREAM-а (потока) представлена в выводе у Dalton-а.

Таким образом, наше правило Suricata “alert tcp 145.254.160.237 any -> 65.208.228.223 80 (msg:»Test Http request»; content:»GET»; content:»download.html»; sid:1;)”, нашло в дампе трафика HTTP-запрос, который имеет метод GET и также содержит в запросе URI “download.html”. В выводе Dalton-а подтверждается соответствующими значениями в вышеуказанных полях.
А еще, хочу сказать, Suricata умеет работать с правилами на прикладные протоколы. У самой сурикаты есть внутренние механизмы, благодаря которым по заголовкам пакетов определяются протоколы в них. В wireshark, например, есть диссекторы, благодаря которым мы можем анализировать заголовки пакетов. Эти диссекторы также могут использовать и другие ПО анализаторы трафика. В сурикате можно добавлять код диссектора для своих кастомных протоколов, например. Так вот если у вас будет сетевое взаимодействие по протоколу HTTP, но не по 80 порту, а по порту 3380, то суриката также определит его. Можем дополнить вышеуказанное правило и конкретизировать его следующим образом:
alert http 145.254.160.237 any -> 65.208.228.223 80 (msg:»Test Http request»; flow:established,to_server; content:»GET»; content:»download.html»; sid:1;)
Можете самостоятельно запустить в Dalton. Вывод работы правила не совсем будет отличаться от предыдущего. Давайте лучше поговорим о добавленном модификаторе «flow:established,to_server;«. Данный модификатор указывает выполнять поиск пакетов в установленных соединениях (речь о TCP-соединениях) и чтобы пакеты были направлены от клиента к серверу. Укажу все возможные варианты flow:
to_client – совпадения будут на пакеты, направленные клиенту
to_server – совпадения будут на пакеты, направленные серверу
from_client – совпадения будут на пакеты, от клиента (аналогично to_server)
from_server – совпадения будут на пакеты, от сервера (аналогично to_client)
established – совпадения будут на пакеты из установленных соединений
not_established – совпадения будут на пакеты, не относящихся к установленным соединениям
stateless — совпадения будут на пакеты потока (TCP‑поток, UDP‑потоки ….). Пакеты, не относящиеся к потоку, не будут подходить под условия.
only_stream — совпадения будут на пересобранные пакеты (reassembled). Такие пакеты Вы можете увидеть в ваершарке в правом нижнем углу, где представлено побайтовое представление пакета. Там будет вкладка «reassembled». Пересобранные пакеты появляются в том случае, если в ходе передачи данных были помехи и данные пришли не полностью — их надо пересобрать. Или, например, передавалось несколько фрагментов данных, после чего их необходимо пересобрать.
no_stream – совпадения будут на пакеты, не относящиеся к пересобранным.
only_frag – совпадения будут на пакеты, которые были собраны из фрагментов
no_frag – совпадения будут на пакеты, которые не были собраны из фрагментов
Также возможно составное использование вышеуказанных переменных:
flow:to_client, established
flow:to_server, established, only_stream
flow:to_server, not_established, no_frag
Посмотрите как работают. Можете сами поэкспериментировать с другими правилами. Пробуйте, ошибайтесь, еще раз пробуйте.
Важные замечания:
— msg значения могут быть одинаковыми. Главное, чтобы были разными sid значения. Sid — это идентификатор правила. Если в файле с правилами будут два и более правил с одинаковыми сидами, суриката откажется запускаться;
— неправильно собранный трафик, неправильно разделенный пкап, отсутствие syn, ack пакетов в пкапе не позволят запустить проигрывание правил сурикатовских по пкапу;
— если Вы захотите использовать символы «;», «»», то их нужно экранировать. Символы могут быть указаны в модификаторе msg или content, например. в модификаторе msg можно экранировать следующим образом:” msg:»Test Http \; request»; “. Также можно и в content, но я бы рекомендовал вместо вышеописанных символов использовать байтовое их представление — такой вариант более надежный и правильный.
На этом первая часть окончена. Всем спасибо за внимание! Критика приветствуется. Буду очень благодарен за неё.
ссылка на оригинал статьи https://habr.com/ru/articles/1047246/