====== DPI из подручных материалов ====== * [[https://habr.com/ru/articles/813799/|DPI из подручных материалов]] Всем привет! Однажды, много лет назад, во времена эпидемии вируса [[https://ru.wikipedia.org/wiki/Code_Red|Code Red]], я работал сисадмином в одном вузе и невежливо ответил на электронное письмо из какого то-банка с требованием немедленно прекратить атаку на их веб сервер, работающий под управлением Apache, через месяц пришло бумажное письмо от их службы безопасности, и завертелось. Так я познакомился с системой [[https://ru.wikipedia.org/wiki/Snort|Snort]], которая некоторое время защищала Интернет от наших студентов. Со временем, большая часть трафика стала https, и решение потеряло смысл, но, есть места, где он снова превращается в http, например после https прокси. Тут то мы и сможем его "подсмотреть", выявить атаки и заблокировать злоумышленника! Что бы было интереснее, не будем рассматривать [[https://youtu.be/oIczkkD-hOU?si=tb7ucLRAdH2rbSVL|реальный кейс]], а воспроизведем все "в домашних условиях". На единственной системе развернем https прокси, веб приложение за ним, и защитим от атак на основе анализа содержимого http запросов. Потребуется VirtualBox (или любой другой гипервизор) и дистрибутив Linux, например Ubuntu, там Snort имеется в виде пакета. Можно взять мой готовый ova образ: https://val.bmstu.ru/unix/img/My%20Documents/ubuntu_24.04_01.ova и выполнить 1-й шаг из [[https://habr.com/ru/articles/716454/|этой статьи]] ===== Шаг 2. Разворачиваем http приложение ===== Можно развернуть [[https://youtu.be/ykWLHQ2i_8E?si=VBVfi9w-vhl_bGDg|что-нибудь поинтереснее]], но, сути это не меняет, поэтому обойдемся простым вариантом: $ sudo -i # apt update # apt install docker.io # docker run --name http-app -d --restart=always httpd # docker inspect http-app -f {{.NetworkSettings.IPAddress}} # curl http://172.17.0.2 http приложение готово! ===== Шаг 2. Создаем сертификат для https прокси ===== Для "игрушечного" примера подойдет само подписанный сертификат c атрибутами "по умолчанию" # openssl genrsa -out /etc/ssl/private/http-app.key 2048 # openssl req -new -x509 -days 3650 -key /etc/ssl/private/http-app.key -out /etc/ssl/certs/http-app.crt На все "вопросы" последней команды достаточно нажать Enter (даже про Common Name, поскольку тестировать все будем по ip адресу) ===== Шаг 3. Разворачиваем https прокси ===== В качестве https прокси рассмотрим nginx (можно haproxy, суть не изменится). Поскольку тестировать все будем по ip адресу, настроим перенаправление любых запросов (server_name _) на 443 порт в наше http приложение. X-Forwarded-For в нашем случае нужен потому, что только в этом заголовке будет ip адрес клиента в трафике между https прокси и приложением. # apt install nginx # nano /etc/nginx/sites-available/http-app server { listen 443 ssl; server_name _; ssl_certificate /etc/ssl/certs/http-app.crt; ssl_certificate_key /etc/ssl/private/http-app.key; location / { proxy_pass http://172.17.0.2; proxy_set_header X-Forwarded-For $remote_addr; } } # ln -s /etc/nginx/sites-available/http-app /etc/nginx/sites-enabled/http-app # systemctl restart nginx.service Теперь наше http приложение должно быть доступно по URL: https://ip_адрес_виртульной_машины/ правда, браузер будет ругаться на сертификат и придется "перейти на сайт небезопасно" ===== Шаг 4. Разворачиваем IDS Snort ===== # apt install snort В вопросах инсталлятора про сетевые интерфейсы указываем docker0, в нашем случае именно через него идет трафик между https прокси и http приложением в контейнере. Остальные ответы "по умолчанию", результат работы инсталлятора записывается в файл: # less /etc/snort/snort.debian.conf ... DEBIAN_SNORT_INTERFACE="docker0" ... В основном файле конфигурации отключаем проверку контрольной суммы пакетов, поскольку эта функциональность актуальна только для "входящего" трафика, а в нашем случае, http трафик будет "выходить" из интерфейса docker0, добавляем опцию анализа заголовка X-Forwarded-For в http трафике и настраиваем вывод сообщений об обнаруженных атаках в syslog с типом сообщений auth и уровнем важности alert: # nano /etc/snort/snort.conf ... # Configure IP / TCP checksum mode config checksum_mode: none ... preprocessor http_inspect_server: server default \ ... enable_xff \ webroot no ... #################################################################### # Step #6: Configure output plugins ... output alert_syslog: LOG_AUTH LOG_ALERT ... # systemctl restart snort.service Для тестирования будем использовать тот самый злополучный Code Red, для которого, как раз, есть правило "из коробки": # less /etc/snort/rules/web-iis.rules ... alert tcp $EXTERNAL_NET any -> $HTTP_SERVERS $HTTP_PORTS (msg:"WEB-IIS CodeRed v2 root.exe access"; flow:to_server,established; uricontent:"/root.exe"; nocase; reference:url,www.cert.org/advisories/CA-2001-19.html; classtype:web-application-attack; sid:1256; rev:8;) ... Симулировать атаку можно обращаясь к нашему приложению по URL: https://ip_адрес_виртульной_машины/root.exe В журнале должны появляться характерные сообщения: # tail -f /var/log/auth.log ... 2024-05-12T18:06:07.467018+00:00 ubuntu snort[6978]: [1:1256:8] WEB-IIS CodeRed v2 root.exe access [Classification: Web Application Attack] [Priority: 1] {TCP} 172.17.0.1:40890 -> 172.17.0.2:80 ... Но, стоп, в них отсутствует адрес клиента, здесь только адрес прокси и самого приложения! Оказывается, информация из заголовка X-Forwarded-For попадает в двоичный файл, для анализа которого авторы Snort добавили специальную утилиту: # u2spewfoo /var/log/snort/snort.alert ... priority: 1 ip source: 172.17.0.1 ip destination: 172.17.0.2 ... type: 1 datatype: 1 bloblength: 12 Original Client IP: 192.168.1.100 ... Этот файл создается и непрерывно растет с момента запуска Snort, а утилита умеет выводить его только целиком. Для нашей следующей задачи будет удобнее, если полученная таким образом информация будет тоже последовательно писаться в журнал. Пришлось "сочинить" такого "крокодила" (ключи -с +1 команды tail из-за двоичного формата файла, u2spewfoo не умеет читать из STDIN, stdbuf отключает буферизацию ввода и вывода, logger все пишет в syslog от имени приложения snort с типом сообщений auth и уровнем важности info): # stdbuf -i0 -o0 u2spewfoo <(tail -c +1 -f /var/log/snort/snort.alert) | logger -t snort -p auth.info В журнале теперь будут появляться такие сообщения (понадобится вторая консоль): # tail -f /var/log/auth.log ... 2024-05-12T18:16:25.965360+00:00 ubuntu snort: #011type: 1#011datatype: 1#011bloblength: 12#011Original Client IP: 192.168.1.100 ... Можно оформить запуск "крокодила" через systemd # nano /etc/systemd/system/snort-alert-unified2-syslog.service [Unit] Description=Send snort alert_unified2 to syslog After=snort.service [Service] ExecStart=/bin/bash -c '/usr/bin/stdbuf -i0 -o0 /usr/sbin/u2spewfoo <(/usr/bin/tail -c +1 -f /var/log/snort/snort.alert) | /usr/bin/logger -t snort -p auth.info' [Install] WantedBy=multi-user.target # systemctl enable snort-alert-unified2-syslog --now ===== Шаг 5. Превращаем IDS в IPS ===== Теперь в журнале поваляются адреса клиентов, сигнатуры пакетов которых попадают в правила Snort (с правилами все печально, Snort принадлежит Cisco, были платные подписки или бесплатно с месячной задержкой, теперь только Community rules, в составе пакета, ну, и, можно писать свои) Для чтения журнала и блокировки злоумышленников будем использовать fail2ban Вообще, он ставится командой: # apt install fail2ban но, на текущий момент (май 2024) в 24-й ubuntu он не работает (надеюсь, починят) и приходится устанавливать его так: # wget https://launchpad.net/ubuntu/+source/fail2ban/1.1.0-1/+build/28291332/+files/fail2ban_1.1.0-1_all.deb # dpkg -i fail2ban_1.1.0-1_all.deb В любом случае, конфигурация выглядит так: # nano /etc/fail2ban/filter.d/snort_filter.conf [Definition] failregex = .*Original Client IP: .* # nano /etc/fail2ban/jail.d/snort_jail.conf [snort] enabled = true bantime = 300 filter = snort_filter maxretry = 3 logpath = /var/log/auth.log action = iptables-allports # systemctl restart fail2ban.service Вот тут я "забанил" сам себя и потерял history команд при подготовке статьи, так что лучше продолжать "атаки" с другого домашнего устройства, например с телефона :) https://ip_адрес_виртульной_машины/root.exe В журнале можно наблюдать реакцию fail2ban на "атаки": # tail -f /var/log/fail2ban.log А также снять блокировку: # fail2ban-client status snort # fail2ban-client set snort unbanip Спасибо что дочитали, надеюсь было интересно, буду рад ответить на вопросы!