Как стать автором
Поиск
Написать публикацию
Обновить

DPI из подручных материалов

Уровень сложностиСредний
Время на прочтение5 мин
Количество просмотров5.7K

Всем привет!

Однажды, много лет назад, во времена эпидемии вируса Code Red, я работал сисадмином в одном вузе и невежливо ответил на электронное письмо из какого то‑банка с требованием немедленно прекратить атаку на их веб сервер, работающий под управлением Apache, через месяц пришло бумажное письмо от их службы безопасности, и завертелось. Так я познакомился с системой Snort, которая некоторое время защищала Интернет от наших студентов. Со временем, большая часть трафика стала https, и решение потеряло смысл, но, есть места, где он снова превращается в http, например после https прокси. Тут то мы и сможем его «подсмотреть», выявить атаки и заблокировать злоумышленника!

Что бы было интереснее, не будем рассматривать реальный кейс, а воспроизведем все «в домашних условиях». На единственной системе развернем https прокси, веб приложение за ним, и защитим от атак на основе анализа содержимого http запросов. Потребуется VirtualBox (или любой другой гипервизор) и дистрибутив Linux, например Ubuntu, там Snort имеется в виде пакета. Можно взять мой готовый ova образ:

https://val.bmstu.ru/unix/img/My%20Documents/ubuntu_24.04_01.ova

и выполнить 1-й шаг из этой статьи:

Шаг 2. Разворачиваем http приложение

Можно развернуть что-нибудь поинтереснее, но, сути это не меняет, поэтому обойдемся простым вариантом:

$ 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: <HOST>.*

# 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 <IP>

Спасибо что дочитали, надеюсь было интересно, буду рад ответить на вопросы!

Теги:
Хабы:
Всего голосов 2: ↑2 и ↓0+4
Комментарии4

Публикации

Ближайшие события