
Одного пропущенного вызова функции при регистрации маршрута было достаточно, чтобы превратить интерфейс MCP в шлюз для неаутентифицированного удалённого выполнения кода (RCE).
Неразрушающий инструмент обнаружения для обхода аутентификации MCP в nginx-ui, известного публично как MCPwn. Позволяет за два HTTP-запроса без аутентификации получить полный контроль над любым экземпляром nginx-ui, работающим на уязвимой версии.
nginx-ui предоставляет интерфейс Model Context Protocol (MCP), который позволяет аутентифицированному оператору управлять разрушительными инструментами, такими как редактирование конфигурации nginx, команды перезапуска и операции резервного копирования, через JSON-RPC.
Конечная точка /mcp защищена промежуточным ПО AuthRequired(), в то время как
её парная конечная точка /mcp_message, которая фактически принимает вызовы
инструментов, была развёрнута без этого промежуточного ПО. Любой клиент, который
может получить доступ к веб-интерфейсу по сети, может:
/mcp и получить новый
sessionID без предъявления каких-либо учётных данных.sessionID для вызова любого зарегистрированного MCP-инструмента,
отправив POST-запрос к /mcp_message, по-прежнему без аутентификации.Атакующий получает полный контроль над процессом nginx: редактирует серверные блоки для перенаправления трафика, извлекает закрытые ключи TLS через чтение путей, перезагружает или останавливает nginx, а также внедряет постоянные бэкдоры.
// уязвимая версия (до 2.3.4)
r.GET("/mcp", AuthRequired(), mcpHandler)
r.POST("/mcp_message", mcpMessageHandler) // отсутствует промежуточное ПО
// исправлено в 2.3.4
r.GET("/mcp", AuthRequired(), mcpHandler)
r.POST("/mcp_message", AuthRequired(), mcpMessageHandler)
Одного пропущенного вызова функции при регистрации маршрута было достаточно, чтобы превратить интерфейс MCP в шлюз неаутентифицированного RCE.
Атакующий nginx-ui (<2.3.4)
| 1) GET /mcp (без аутентификации) |
| --------------------------------------> |
| 2) event: endpoint data: /mcp_message?sessionID=XYZ
| <-------------------------------------- |
| 3) POST /mcp_message?sessionID=XYZ |
| тело: JSON-RPC call_tool "nginx_reload" или
| "edit_config {...}" |
| --------------------------------------> |
| 4) 200 OK; инструмент выполнен с полными привилегиями
| <-------------------------------------- |
Этот репозиторий намеренно избегает любых разрушительных действий. Детектор
использует только методы MCP, доступные для чтения (tools/list). Логика:
> Шаг 1 Определение nginx-ui через
> GET / (HTML-заголовок, JS-бандлы)
> GET /api/settings (JSON со ссылками на ключи nginx-ui)
> Извлечение версии через заголовок / регулярное выражение в теле
> Шаг 2 Открытие SSE-потока к /mcp
> Извлечение первого sessionID из события "endpoint"
> Шаг 3 POST /mcp_message?sessionID=<id>
> Тело: {"jsonrpc":"2.0","method":"tools/list","params":{}}
> Без заголовка Authorization
> Шаг 4 Уязвим, если статус 200 и тело содержит манифест инструментов
> Исправлен, если статус 401 / 403 / 404
> Неопределённо в остальных случаях
Метод JSON-RPC tools/list доступен только для чтения. Он перечисляет, какие
инструменты известны MCP-серверу, но не вызывает ни один из них. Скрипт
отказывается отправлять любые другие методы и никогда не формирует полезные
нагрузки для разрушительных инструментов.
git clone https://github.com/your-org/CVE-2026-33032-detector.git
cd CVE-2026-33032-detector
python3 --version # 3.9 или новее
# Сторонние пакеты не требуются.
Для компонента Nmap NSE скопируйте nginx-ui-mcpwn.nse в локальный
каталог скриптов и обновите базу данных скриптов:
cp nginx-ui-mcpwn.nse /usr/share/nmap/scripts/
sudo nmap --script-updatedb
# Одиночная цель
python3 detect_nginx_ui_mcpwn.py --target https://nginx-ui.internal
# Массовое сканирование из файла
python3 detect_nginx_ui_mcpwn.py --targets targets.txt --workers 20
# Вывод в формате JSON (NDJSON), подходящий для передачи в jq
python3 detect_nginx_ui_mcpwn.py --target 10.0.0.5:9000 --json | jq .
Справочник по параметрам командной строки:
nmap -p 80,443,9000 --script nginx-ui-mcpwn 10.0.0.0/24
nmap -p 443 --script nginx-ui-mcpwn --script-args "nginx-ui-mcpwn.timeout=8" host.example.com
_ _ _ _ _ ___ __ __ ____ ____
| \ | | __ _(_)_ __ __ __ | | | ||_ _| | \/ |/ ___| _ \__ ___ __
| \| |/ _` | | '_ \\ \/ /_____| | | | | | | |\/| | | | |_) \ \ /\ / / '_ \
| |\ | (_| | | | | |> <|_____| |__| | | | | | | | |___| __/ \ V V /| | | |
|_| \_|\__, |_|_| |_/_/\_\ |_____|_||___| |_| |_|\____|_| \_/\_/ |_| |_|
|___/
CVE-2026-33032 nginx-ui MCPwn Детектор > неразрушающий
[!] УЯЗВИМ https://nginx-ui.internal версия=2.3.2 доказательство=status=200; body_preview={"jsonrpc":"2.0","id":"...","result":{"tools":[{"name":"edit_config",...
[+] ИСПРАВЛЕН https://nginx-ui-patched:9000 версия=2.3.4 доказательство=status=401; body_preview={"error":"unauthorized"}
[.] не nginx-ui https://example.com доказательство=отрицательный fingerprint
Итог: 1/3 целей помечены как уязвимые
{"target":"https://nginx-ui.internal","reachable":true,"is_nginx_ui":true,"mcp_endpoint_present":true,"session_id_obtained":true,"mcp_message_unauthenticated":true,"vulnerable":true,"nginx_ui_version":"2.3.2","evidence":"status=200; body_preview=...","error":null}
PORT STATE SERVICE
9000/tcp open http
| nginx-ui-mcpwn:
| status: VULNERABLE
| version: 2.3.2
| session_id: abc123
|_ evidence: tools/list accepted without credentials
CVE-2026-27944 (неаутентифицированная загрузка /api/backup, которая раскрывает
ключ AES в заголовке X-Backup-Security) хорошо сочетается с
MCPwn: архив резервной копии раскрывает node_secret, который можно
использовать для аутентификации к /mcp даже после выхода исправления для 33032,
пока операторы не сменят секрет.
Сопутствующий детектор для 27944 находится в соседнем каталоге этого исследовательского проекта.
node_secret, хэши паролей администратора и любые закрытые ключи
TLS, которые были доступны процессу nginx-ui./mcp_message
станет доступен.Этот инструмент опубликован, чтобы помочь защитникам выявлять незапатченные экземпляры в средах, которые им разрешено тестировать. Не используйте его против систем, которыми вы не владеете или на проверку которых у вас нет явного разрешения. Авторы снимают с себя всякую ответственность за ненадлежащее использование.
Выпущено под лицензией MIT. Смотрите заголовки отдельных скриптов для уведомлений по каждому файлу.
| Поле | Значение |
|---|
| CVE ID | CVE-2026-33032 |
| Псевдоним | MCPwn |
| CVSS 3.1 | 9.8 / Критический (AV:N / AC:L / PR:N / UI:N / S:U / C:H/I:H/A:H) |
| CWE | CWE-306 Отсутствие аутентификации для критической функции |
| Затронутый продукт | nginx-ui (github.com/0xjacky/nginx-ui) |
| Затронутые версии | Все версии до 2.3.4 |
| Исправленная версия | 2.3.4 |
| Статус эксплуатации | Активная эксплуатация в дикой природе (Picus Security, Recorded Future) |
| Доступность в Shodan | ~2 689 экземпляров, доступных из интернета |
| Дата публикации | 2026-04-15 |
| MCP-инструмент | Эффект на сервер nginx |
|---|
edit_config | Перезапись произвольных серверных блоков, вставка апстрима атакующего |
reload_nginx | Применение конфигурации атакующего без ручных действий |
stop_nginx | Отказ в обслуживании |
read_file | Экфильтрация закрытых ключей TLS, учётных данных из смонтированных путей |
create_cert | Перевыпуск TLS-сертификатов под контролем атакующего |
list_backups / download | Выгрузка полной резервной копии nginx-ui, включая node_secret и хэши |
| Флаг | Назначение |
|---|
--target | Одиночный URL или host[:port] |
--targets | Файл с целями, разделёнными переводами строки |
--timeout | HTTP-таймаут, по умолчанию 10 секунд |
--workers | Параллельные рабочие процессы для массовых сканирований, по умолчанию 10 |
--verify-tls | Включить проверку TLS-сертификатов (по умолчанию выключена) |
--json | Вывод в формате NDJSON, одна запись на цель |
--no-banner | Подавить ASCII-баннер |