
Una sola llamada a función faltante en el registro de rutas fue suficiente para convertir la interfaz MCP en una puerta de enlace RCE sin autenticación.
Herramienta de detección no destructiva para la omisión de autenticación MCP de nginx-ui conocida públicamente como MCPwn. Permite la toma de control no autenticada de cualquier instancia de nginx-ui que ejecute una versión vulnerable mediante dos peticiones HTTP.
nginx-ui expone una interfaz de Protocolo de Contexto de Modelo (MCP) que permite a un operador autenticado ejecutar herramientas destructivas como ediciones de configuración de nginx, comandos de reinicio y operaciones de copia de seguridad a través de JSON-RPC.
El endpoint /mcp está protegido por el middleware AuthRequired(), mientras
que su endpoint asociado /mcp_message, que realmente recibe las invocaciones
de herramientas, fue desplegado sin el middleware. Cualquier cliente que
pueda alcanzar la interfaz web a través de la red puede:
/mcp y
recibir un sessionID nuevo sin presentar ninguna credencial.sessionID para invocar cualquier herramienta MCP registrada
enviando un POST a /mcp_message, aún sin autenticación.El atacante obtiene control total del proceso de nginx: editar bloques de servidor para redirigir tráfico, extraer claves privadas TLS mediante lecturas de rutas, recargar o detener nginx, e implantar puertas traseras persistentes.
// vulnerable (pre-2.3.4)
r.GET("/mcp", AuthRequired(), mcpHandler)
r.POST("/mcp_message", mcpMessageHandler) // middleware ausente
// corregido en 2.3.4
r.GET("/mcp", AuthRequired(), mcpHandler)
r.POST("/mcp_message", AuthRequired(), mcpMessageHandler)
Una única llamada a función ausente en el registro de rutas fue suficiente para convertir la interfaz MCP en una puerta de entrada de RCE no autenticada.
Atacante nginx-ui (<2.3.4)
| 1) GET /mcp (sin autenticación) |
| --------------------------------------> |
| 2) event: endpoint data: /mcp_message?sessionID=XYZ
| <-------------------------------------- |
| 3) POST /mcp_message?sessionID=XYZ |
| body: JSON-RPC call_tool "nginx_reload" o
| "edit_config {...}" |
| --------------------------------------> |
| 4) 200 OK; herramienta ejecutada con privilegios completos
| <-------------------------------------- |
Este repositorio evita intencionalmente cualquier acción destructiva. El
detector solo utiliza métodos MCP de solo lectura (tools/list). La lógica:
> Paso 1 Identificar nginx-ui mediante
> GET / (título HTML, paquetes JS)
> GET /api/settings (JSON que referencia claves de nginx-ui)
> Extraer versión mediante regex en cabecera / cuerpo
> Paso 2 Abrir flujo SSE hacia /mcp
> Analizar el primer sessionID del evento "endpoint"
> Paso 3 POST /mcp_message?sessionID=<id>
> Body: {"jsonrpc":"2.0","method":"tools/list","params":{}}
> Sin cabecera Authorization
> Paso 4 Vulnerable si estado 200 y el cuerpo contiene un manifiesto de herramientas
> Parcheado si estado 401 / 403 / 404
> No concluyente en cualquier otro caso
El método JSON-RPC tools/list es de solo lectura. Enumera qué
herramientas conoce el servidor MCP pero no invoca ninguna de ellas. El script
se niega a enviar POST con cualquier otro método y nunca construye cargas
útiles para herramientas destructivas.
git clone https://github.com/your-org/CVE-2026-33032-detector.git
cd CVE-2026-33032-detector
python3 --version # 3.9 o superior
# No se requieren paquetes de terceros.
Para el componente Nmap NSE, copie nginx-ui-mcpwn.nse en su directorio
local de scripts y actualice la base de datos de scripts:
cp nginx-ui-mcpwn.nse /usr/share/nmap/scripts/
sudo nmap --script-updatedb
# Objetivo único
python3 detect_nginx_ui_mcpwn.py --target https://nginx-ui.internal
# Escaneo masivo desde archivo
python3 detect_nginx_ui_mcpwn.py --targets targets.txt --workers 20
# Salida JSON (NDJSON) adecuada para canalizar a jq
python3 detect_nginx_ui_mcpwn.py --target 10.0.0.5:9000 --json | jq .
Referencia de línea de comandos:
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 Detector MCPwn de nginx-ui > no destructivo
[!] VULNERABLE https://nginx-ui.internal version=2.3.2 evidencia=estado=200; vista_previa_cuerpo={"jsonrpc":"2.0","id":"...","result":{"tools":[{"name":"edit_config",...
[+] parcheado https://nginx-ui-patched:9000 version=2.3.4 evidencia=estado=401; vista_previa_cuerpo={"error":"unauthorized"}
[.] no es nginx-ui https://example.com evidencia=huella negativa
Resumen: 1/3 objetivos marcados como vulnerables
{"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 aceptado sin credenciales
CVE-2026-27944 (la descarga no autenticada de /api/backup que filtra
la clave AES en la cabecera X-Backup-Security) se encadena limpiamente con
MCPwn: el archivo de copia de seguridad expone el node_secret, que puede
usarse para autenticarse en /mcp incluso después de que se aplique el
parche para 33032, hasta que los operadores roten el secreto.
El detector complementario para 27944 reside en un directorio hermano de este proyecto de investigación.
node_secret, los hashes de contraseñas de administrador y cualquier
clave privada TLS que fuera accesible para el proceso de nginx-ui./mcp_message
sea alcanzable.Esta herramienta se publica para ayudar a los defensores a identificar instancias sin parchear dentro de entornos que están autorizados a probar. No la utilice contra sistemas que no posea o para los que no tenga permiso explícito de evaluación. Los autores declinan toda responsabilidad por el uso indebido.
Publicado bajo la Licencia MIT. Consulte las cabeceras individuales de cada script para los avisos por archivo.
| Campo | Valor |
|---|
| ID CVE | CVE-2026-33032 |
| Alias | MCPwn |
| CVSS 3.1 | 9.8 / Crítico (AV:N / AC:L / PR:N / UI:N / S:U / C:H/I:H/A:H) |
| CWE | CWE-306 Autenticación Ausente para Función Crítica |
| Producto afectado | nginx-ui (github.com/0xjacky/nginx-ui) |
| Versiones afectadas | Todas las versiones anteriores a 2.3.4 |
| Versión corregida | 2.3.4 |
| Estado de explotación | Activa en la naturaleza (Picus Security, Recorded Future) |
| Exposición en Shodan | ~2.689 instancias expuestas a internet |
| Fecha de publicación | 2026-04-15 |
| Herramienta MCP | Efecto en el servidor nginx |
|---|
edit_config | Reescribir bloques de servidor arbitrarios, insertar upstream del atacante |
reload_nginx | Aplicar configuración del atacante sin acción manual |
stop_nginx | Denegación de servicio |
read_file | Exfiltrar claves privadas TLS, credenciales de rutas montadas |
create_cert | Re-emitir certificados TLS bajo control del atacante |
list_backups / download | Extraer copia de seguridad completa de nginx-ui incluyendo node_secret y hashes |
| Flag | Propósito |
|---|
--target | URL única o host[:puerto] |
--targets | Archivo de objetivos separados por nueva línea |
--timeout | Tiempo de espera HTTP, 10 segundos por defecto |
--workers | Trabajadores concurrentes para escaneos masivos, 10 por defecto |
--verify-tls | Forzar verificación de certificado TLS (desactivada por defecto) |
--json | Emitir NDJSON, un registro por objetivo |
--no-banner | Suprimir el banner ASCII |