Статья CVE-2026-33032: эксплуатация уязвимости Nginx UI — от auth bypass до полного захвата сервера

Вскрытый одноплатный сервер на чёрном антистатическом коврике с подключённым UART-пробником. На дисплее — глитч-текст с идентификатором уязвимости, выжженная дорожка ведёт от сетевого разъёма к про...


Shodan-запрос по favicon hash инстанса Nginx UI (значение hash вычисляется через favfreak или favicon.py - между версиями оно плавает) возвращает публично доступные панели. Каждая непропатченная отдаёт полный контроль над nginx и всем трафиком за ним - за два HTTP-запроса без единого пароля. Два запроса. Ноль аутентификации. Полный ко нтроль.

Ниже - полный разбор цепочки: от fingerprinting уязвимого инстанса через nginx ui authentication bypass до постэксплуатации с перехватом трафика и кражей JWT-секрета.

Бизнес-логика атаки: зачем атакующему Nginx UI​

Nginx UI - open-source веб-интерфейс для управления Nginx с активным сообществом на GitHub и приличным числом загрузок из Docker Hub. Через панель администраторы правят конфигурацию виртуальных хостов, управляют SSL-сертификатами, перезагружают сервис. В типичном деплое nginx-ui стоит перед продакшн-трафиком, API-шлюзами и внутренними сервисами. Это не побочная утилита - это рубильник, через который идёт весь сетевой трафик. Подробнее - в нашем руководстве по cve эксплойт разработка.

По данным Mandiant M-Trends 2025, exploits остаются доминирующим вектором initial access - 38% всех случаев. CVE-2026-33032 - один из тех редких случаев, когда exploit не требует вообще ничего: ни привилегий (PR:N), ни действий пользователя (UI:N), ни сложных предусловий (AC:L). CISA SSVC подтверждает: Automatable: yes, Technical Impact: total. Скрипт на 50 строк Python - и оператор полностью контролирует конфигурацию nginx.

По данным IBM X-Force Threat Intelligence Index 2025, среднее время между публикацией CVE и устранением в организациях - 29 месяцев. Так что уязвимые инстансы nginx-ui будут попадаться на пентестах ещё долго после выхода патча. Для атакующего ценность цели определяется тем, что контроль над nginx даёт:
  • Перехват трафика целой инфраструктуры через манипуляцию upstream-блоками
  • Credential harvesting через injection кастомных директив логирования
  • Persistence через кражу ключа подписи JWT-токенов
  • Разведку внутренней топологии - upstream-хосты, backend-порты, TLS-сертификаты
Место в kill chain: чистый initial access (T1190, Exploit Public-Facing Application) с немедленным переходом в постэксплуатацию. Классический foothold - загрузка агента, получение reverse shell - не нужен. Атакующий управляет инфраструктурой через легитимный API панели. Зачем ломать дверь, если тебе дали ключи от диспетчерской?

Анатомия CVE-2026-33032: nginx ui cve разбор​

1783462293169.webp

Классификация, метрики и OWASP-контекст​

ПараметрЗначение
CVECVE-2026-33032
CVSS 3.19.8 (Critical)
ВекторAV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H
CWE (NVD)CWE-306 - Missing Authentication for Critical Function
Затронутые версииnginx-ui <= 2.3.5 (по данным NVD)
Вендор / продукт0xJacky / nginx-ui
GHSAGHSA-h6c2-x2m2-mwhf
EPSS0.3848, percentile 98.39%
CISA SSVCAutomatable: yes, Technical Impact: total

CVSS-вектор читается однозначно: атака выполняется удалённо по сети (AV:N), не требует сложных условий (AC:L), не требует ни привилегий (PR:N), ни действий со стороны жертвы (UI:N). Влияние - максимальное по всем трём осям: конфиденциальность (C:H), целостность (I:H), доступность (A:H). Scope не меняется (S:U) - формально атака ограничена компонентом nginx-ui, хотя через конфигурацию nginx последствия расползаются на все проксируемые сервисы.

Первичная классификация по NVD - CWE-306: отсутствие аутентификации для критической функции. В терминах OWASP Top 10 уязвимость ложится на A05:2021 - Security Misconfiguration: fail-open поведение IP whitelist при пустом списке - учебный пример небезопасного дефолта. Эксплуатация непропатченной версии попадает под A06:2021 - Vulnerable and Outdated Components.

В полной цепочке эксплуатации дополнительно проявляются CWE-22 (Improper Limitation of a Pathname to a Restricted Directory) и CWE-73 (External Control of File Name or Path): через MCP-инструмент nginx_config_add атакующий контролирует и имя создаваемого файла, и его содержимое. NVD присвоил только CWE-306 как корневую причину, но при оценке полного импакта стоит учитывать и эти аспекты.

Пропущенный AuthRequired() и fail-open whitelist​

Nginx UI интегрирует MCP (Model Context Protocol) - открытый стандарт для подключения AI-ассистентов к внешним системам. Идея: AI-ассистент настраивает nginx от имени пользователя. Звучит модно. На практике - получилась дыра размером с грузовой контейнер.

MCP-транспорт использует SSE (Server-Sent Events) с двухэндпоинтной архитектурой: GET /mcp открывает SSE-стрим и возвращает sessionID, POST /mcp_message принимает JSON-RPC вызовы MCP-инструментов. Оба эндпоинта маршрутизируются на один обработчик mcp.ServeHTTP(c).

Уязвимый код регистрации маршрутов в mcp/router.go (по данным advisory GHSA-h6c2-x2m2-mwhf):
Код:
func InitRouter(r *gin.Engine) {
    r.Any("/mcp", middleware.IPWhiteList(), middleware.AuthRequired(),
        func(c *gin.Context) { mcp.ServeHTTP(c) })
    r.Any("/mcp_message", middleware.IPWhiteList(),
        func(c *gin.Context) { mcp.ServeHTTP(c) })
}
Видите? Маршрут /mcp защищён двумя middleware: IPWhiteList() и AuthRequired(). Маршрут /mcp_message - только IPWhiteList(). Один пропущенный вызов функции. Именно /mcp_message - тот эндпоинт, через который клиент отправляет все деструктивные вызовы инструментов (запись конфигов, restart, reload). Привилегированный обработчик MCP открыт через незащищённый путь.

Вторая часть проблемы - fail-open поведение вайтлиста. Мидлварь IPWhiteList() в файле internal/middleware/ip_whitelist.go проверяет длину списка: если len(settings.AuthSettings.IPWhiteList) == 0 или clientIP равен 127.0.0.1/::1 - запрос пропускается без проверки (вызов c.Next()). Дефолтная конфигурация nginx-ui оставляет ip_whitelist пустым. Пустой вайтлист = разрешить всё. Это именно то, что OWASP называет Security Misconfiguration: safety control, который в дефолтном состоянии не защищает ничего.

Итог: любой сетевой атакующий вызывает все 12 MCP-инструментов без аутентификации. Среди них - деструктивные (создание, изменение, удаление конфигурационных файлов nginx, перезапуск, перезагрузка, остановка сервиса) и разведывательные (листинг конфигов, чтение файлов, статус nginx).

Recon: fingerprinting уязвимого Nginx UI на пентесте веб-сервера​

1783462391045.webp

[Применимо: внешний пентест - Shodan/Censys; внутренний пентест - port scan + HTTP probe]

Стандартный порт nginx-ui - 9000/tcp. На внешнем пентесте: Shodan-запрос по favicon hash (вычисляется через python3 favicon.py <url> от живого инстанса - конкретное значение проверяйте в момент разведки, оно плавает между версиями) показывает инстансы с характерным favicon. По открытым данным Shodan, инстансы раскиданы по разным регионам и облачным провайдерам.

На внутреннем пентесте после обнаружения открытого порта - быстрая верификация: curl -s http://target:9000/mcp_message -o /dev/null -w "%{http_code}". Код ответа 200 или 400 вместо 401/403 означает, что эндпоинт доступен без аутентификации и nginx ui уязвимость присутствует. Если прилетает 401 - мимо, идём дальше.

Для автоматизированного сканирования в официальном репозитории ProjectDiscovery доступен nuclei-темплейт: nuclei -t http/cves/2026/CVE-2026-33032.yaml -u http://target:9000. Есть и темплейт для связанной CVE-2026-27944 - обе проверки за один проход.

Дополнительный маркер: наличие эндпоинта GET /mcp, отвечающего SSE-стримом (Content-Type text/event-stream). Если оба эндпоинта отвечают - подтверждение того, что MCP-модуль активен.

Когда fingerprinting не даёт результата:
  • Nginx-ui за reverse proxy с IP-фильтрацией на уровне внешнего nginx/HAProxy - прямой доступ к порту 9000 закрыт
  • Нестандартный порт - потребуется полное сканирование TCP-портов
  • IP whitelist заполнен - IPWhiteList() отклонит запрос до MCP-обработчика, и curl вернёт 403

Nginx UI RCE: пошаговая эксплуатация nginx ui уязвимости удалённого выполнения кода​

1783462431353.webp

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

2. Из инфраструктуры при внутреннем пентесте. node_secret часто валяется в Docker Compose файлах, переменных окружения или Kubernetes secrets (T1552.001, Credentials In Files). При латеральном перемещении из скомпрометированного соседнего контейнера доступ к этим данным - вопрос стандартных техник.

Два запроса до захвата сервера через nginx​

Шаг 1. Установка SSE-сессии: GET /mcpnode_secret при необходимости). Сервер возвращает sessionID в потоке SSE-данных.

Шаг 2. Вызов привилегированных MCP-инструментов через POST /mcp_message - без Authorization, без JWT, без cookie:
HTTP:
POST /mcp_message?sessionId=XYZ HTTP/1.1
Host: target:9000
Content-Type: application/json

{"jsonrpc":"2.0","method":"tools/call",
 "params":{"name":"<config_add_tool>",
  "arguments":{"name":"evil.conf",
   "content":"server { listen 8443; location / { proxy_pass ... } }"}},
 "id":1}
MCP-инструмент для добавления конфигурации записывает файл на диск и инициирует перезагрузку nginx. Запись файла + применение конфигурации - в рамках одного вызова. Отдельный шаг для активации не нужен, конфиг вступает в силу мгновенно.

Помимо добавления конфигов, атакующему доступны MCP-инструменты для изменения и чтения конфигураций, перезагрузки и остановки nginx, управления сертификатами. Полный набор - запись и чтение файлов, управление сервисом - без единого пароля.

Постэксплуатация: nginx ui privilege escalation и lateral movement​

После получения контроля над MCP-инструментами атакующий переходит к извлечению максимальной ценности из захваченного nginx. Ниже - конкретные сценарии с привязкой к MITRE ATT&CK.

Перехват трафика. Создание серверного блока с proxy_pass на подконтрольный эндпоинт. Каждый HTTP-запрос, session cookie, API-токен, OAuth-код, проходящие через nginx, копируются атакующему. Особенно больно, если nginx фронтит API-шлюз с Bearer-авторизацией - один модифицированный upstream, и все токены утекают в реальном времени.

Credential harvesting через log injection (T1552.001, Credentials In Files). Внедрение кастомного log_format, включающего переменную $http_authorization, и привязка access_log к пути управления nginx-ui. Администраторы, входящие в панель после компрометации, автоматически сливают свои JWT-токены в лог-файл. Красота в том, что этот лог потом читается через MCP-инструмент read_file или nginx_config_get - повторная аутентификация не нужна.

Persistence через JwtSecret theft (T1078, Valid Accounts). Захватив admin JWT из логов, атакующий обращается к API настроек nginx-ui и извлекает JwtSecret - ключ подписи токенов. С этого момента - неограниченная подделка admin-сессий для любого пользователя. Эта persistence переживает откат конфигурации, смену паролей и даже перезапуск nginx-ui: скомпрометирован сам ключ подписи. Пока его не ротируют - атакующий внутри.

Разведка внутренней топологии (T1083, File and Directory Discovery). Инструменты nginx_config_list и nginx_config_get раскрывают полную карту: upstream-хосты с внутренними IP, backend-порты, пути к TLS-сертификатам, имена внутренних микросервисов. Готовый чертёж инфраструктуры для планирования lateral movement - без сканирования nmap и без шума в IDS.

Чтение чувствительных файлов (T1003.008). Через read_file - доступ к TLS private keys, /etc/passwd, конфигурационным файлам backend-сервисов с паролями к базам данных. Масштаб зависит от прав процесса nginx-ui в ОС.

Persistence через конфигурацию (T1505.003, Web Shell). Вместо классического web shell - создание серверного блока nginx, который проксирует определённый URI на reverse shell listener атакующего. Функционально это web shell, реализованный не через загруженный файл, а через легитимную конфигурацию nginx. Детектируется сложнее обычного web shell - потому что это не файл в webroot, а строчка в конфиге.

Denial of Service. Запись синтаксически невалидного конфига + reload_nginx. Nginx отказывается загружать конфигурацию - все проксируемые сервисы недоступны. Восстановление требует ручного SSH-доступа к серверу.

Полная kill chain: Initial Access (T1190) -> Credential Access (T1552.001, log injection) -> Persistence (T1078, JwtSecret theft; T1505.003, config-based web shell) -> Discovery (T1083, Logs reading) -> Lateral Movement (использование украденных upstream-адресов и backend credentials для атаки на внутренние сервисы)

Ограничения техники, детект и эксплуатация уязвимостей веб-интерфейса: чеклист​

Когда эксплуатация CVE-2026-33032 не работает​

  • IP whitelist заполнен - достаточно одного IP в ip_whitelist, чтобы middleware начал фильтрацию. Атакующий с адреса вне списка получит отказ на уровне IPWhiteList(), до MCP-обработчика запрос не дойдёт
  • MCP-модуль отключён - если модуль деактивирован в конфигурации nginx-ui, эндпоинты /mcp и /mcp_message не регистрируются в роутере. Нет маршрута - нет атаки
  • Пропатченная версия - в исправленных релизах AuthRequired() добавлен на оба маршрута
  • Сетевая изоляция - порт 9000 закрыт файрволом, доступ только через VPN или bastion host. Даже при уязвимой версии атака невозможна без сетевого доступа к порту управления
  • WAF/IPS перед nginx-ui - правила на JSON-RPC tools/call в теле запроса могут блокировать эксплуатацию. Нетипичная конфигурация для admin-панелей, но встречается в зрелых инфраструктурах с централизованным WAF

Индикаторы компрометации для Blue Team​

Ключевые IoC в логах и SIEM:
  • POST-запросы к /mcp_message без валидного JWT/session-header - на продакшне такие запросы аномальны всегда
  • Создание новых .conf файлов в conf.d/ без предшествующей аутентифицированной сессии в nginx-ui
  • Нестандартные log_format или access_log директивы с $http_authorization - признак credential harvesting
  • Перезагрузки nginx (nginx -s reload), не инициированные из UI с валидным токеном
Для Elastic 8.x+: корреляция событий с url.path: "/mcp_message" при отсутствии http.request.header.Authorization в том же событии. Для Sigma-правил: последовательность POST /mcp_message -> системный вызов nginx -s reload с интервалом менее 5 секунд. Для CrowdStrike Falcon: мониторинг создания файлов в директории конфигурации nginx процессом nginx-ui при отсутствии соответствующей записи в audit-логе аутентификации.

Чеклист ремедиации​

  1. Обновить nginx-ui до последней стабильной версии (по данным NVD, уязвимы версии <= 2.3.5)
  2. Если обновление невозможно немедленно - отключить MCP-модуль в конфигурации
  3. Заполнить ip_whitelist явным перечнем IP-адресов администраторов - пустой список = allow all
  4. Закрыть порт управления (9000) файрволом, доступ только через VPN или bastion host
  5. Ротировать node_secret, JwtSecret, SSL-ключи и все учётные данные, хранившиеся в панели
  6. Проверить конфигурации nginx на подозрительные access_log с $http_authorization, нестандартные proxy_pass, новые серверные блоки
  7. Проверить /api/backup на CVE-2026-27944 (CVSS 9.8, CWE-306 + CWE-311) - эти уязвимости эксплуатируются в связке
MCP-интеграции в admin-панелях - бомба замедленного действия, и nginx-ui стал первым громким детонатором. Каждый инструмент, встраивающий AI-ассистента в управление инфраструктурой, рискует наступить на те же грабли: новый протокол порождает новые эндпоинты, а разработчик забывает повесить старый middleware на свежий маршрут. При интеграции MCP протокол часто не наследует существующие security controls приложения - и это не баг конкретного проекта, а системная архитектурная проблема.

При аудите web-панелей управления - не только nginx-ui, но и аналогичных инструментов для HAProxy, Traefik, Envoy - я вижу один устойчивый паттерн: новые фичи приходят через отдельный роутер, и middleware основного пайплайна на него не распространяется. Повторяется в Go (gin, chi), в Express.js, в FastAPI. Разница только в импакте: nginx-ui управляет трафиком, и одна пропущенная строка в router.go превращается в CVSS 9.8 с полным захватом сервиса.

Прогноз: аналогичные CVE появятся в других admin-панелях, которые добавили MCP-интеграцию или LLM-управление. Протокол молодой, security hygiene вокруг него не сформирован, а разработчики торопятся воткнуть "AI-фичу" в следующий релиз. На HackerLab (https://hackerlab.pro) есть лаба, где auth bypass в admin-панели разворачивается от первого запроса до persistence - без подсказок.
 
Последнее редактирование модератором:
Мы в соцсетях:

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

🚀 Первый раз на Codeby?
Гайд для новичков: что делать в первые 15 минут, ключевые разделы, правила
Начать здесь →
🧭 Навигатор · ИБ 2026
Не знаешь, какой трек твой?
5 направлений ИБ, реальные зарплаты и точка входа для каждого — в одном треде.
JuniorSenior+
100K → 600K+ ₽ /мес
Открыть навигатор →
🔴 Свежие CVE, 0-day и инциденты
То, о чём ChatGPT ещё не знает — обсуждаем в реальном времени
Threat Intel →
💼 Вакансии и заказы в ИБ
Pentest, SOC, DevSecOps, bug bounty — работа и проекты от проверенных компаний
Карьера в ИБ →

HackerLab