
Uma única chamada de função ausente no registro de rotas foi suficiente para transformar a interface MCP em um gateway de RCE não autenticado.
Ferramenta de detecção não destrutiva para a bypass de autenticação MCP do nginx-ui conhecida publicamente como MCPwn. Permite a tomada de controlo não autenticada de qualquer instância nginx-ui a executar uma versão vulnerável, através de dois pedidos HTTP.
| 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 Falta de Autenticação para Função Crítica |
| Produto afetado | nginx-ui (github.com/0xjacky/nginx-ui) |
| Versões afetadas | Todas as versões anteriores a 2.3.4 |
| Versão corrigida | 2.3.4 |
| Estado de exploração | Ativa no terreno (Picus Security, Recorded Future) |
| Exposição no Shodan | ~2.689 instâncias expostas à Internet |
| Data de publicação | 2026-04-15 |
O nginx-ui expõe uma interface Model Context Protocol (MCP) que permite a um operador autenticado acionar ferramentas destrutivas, como edições de configuração do nginx, comandos de reinício e operações de backup, através de JSON-RPC.
O endpoint /mcp é protegido pelo middleware AuthRequired(), enquanto
o seu endpoint emparelhado /mcp_message, que na realidade recebe as
invocações das ferramentas, foi implementado sem o middleware.
Qualquer cliente que consiga alcançar a interface através da rede pode:
/mcp e receber um
sessionID novo sem apresentar qualquer credencial.sessionID para invocar qualquer ferramenta MCP registada,
fazendo POST para /mcp_message, ainda sem autenticação.O atacante obtém controlo total do processo nginx: editar blocos de servidor para redirecionar tráfego, extrair chaves privadas TLS através de leituras de caminhos, recarregar ou parar o nginx, e implantar backdoors persistentes.
// vulnerável (pré-2.3.4)
r.GET("/mcp", AuthRequired(), mcpHandler)
r.POST("/mcp_message", mcpMessageHandler) // middleware em falta
// corrigido em 2.3.4
r.GET("/mcp", AuthRequired(), mcpHandler)
r.POST("/mcp_message", AuthRequired(), mcpMessageHandler)
Uma única chamada de função em falta no registo da rota foi suficiente para transformar a interface MCP num portal de RCE não autenticado.
Atacante nginx-ui (<2.3.4)
| 1) GET /mcp (sem auth) |
| --------------------------------------> |
| 2) event: endpoint data: /mcp_message?sessionID=XYZ
| <-------------------------------------- |
| 3) POST /mcp_message?sessionID=XYZ |
| body: JSON-RPC call_tool "nginx_reload" ou
| "edit_config {...}" |
| --------------------------------------> |
| 4) 200 OK; ferramenta executada com privilégios totais
| <-------------------------------------- |
| Ferramenta MCP | Efeito no servidor nginx |
|---|---|
edit_config | Reescrever blocos de servidor arbitrários, inserir upstream do atacante |
reload_nginx | Aplicar configuração do atacante sem ação manual |
stop_nginx | Negação de serviço |
read_file | Exfiltrar chaves privadas TLS, credenciais de caminhos montados |
create_cert | Reemitir certificados TLS sob controlo do atacante |
list_backups / download | Descarregar o backup completo do nginx-ui, incluindo node_secret e hashes |
Este repositório evita intencionalmente qualquer ação destrutiva. O
detetor usa apenas métodos MCP de leitura (tools/list). A lógica:
> Passo 1 Identificar nginx-ui através de
> GET / (título HTML, bundles JS)
> GET /api/settings (JSON com referências a chaves do nginx-ui)
> Extrair versão via regex no cabeçalho / corpo
> Passo 2 Abrir stream SSE para /mcp
> Analisar o primeiro sessionID do evento "endpoint"
> Passo 3 POST /mcp_message?sessionID=<id>
> Body: {"jsonrpc":"2.0","method":"tools/list","params":{}}
> Sem cabeçalho Authorization
> Passo 4 Vulnerável se status 200 e o corpo contiver um manifesto de ferramentas
> Corrigido se status 401 / 403 / 404
> Inconclusivo caso contrário
O método JSON-RPC tools/list é apenas de leitura. Enumera as
ferramentas que o servidor MCP conhece, mas não invoca nenhuma delas. O
script recusa-se a fazer POST de qualquer outro método e nunca constrói
payloads para ferramentas destrutivas.
git clone https://github.com/your-org/CVE-2026-33032-detector.git
cd CVE-2026-33032-detector
python3 --version # 3.9 ou mais recente
# Não são necessários pacotes de terceiros.
Para o componente Nmap NSE, copie nginx-ui-mcpwn.nse para o seu
diretório local de scripts e atualize a base de dados de scripts:
cp nginx-ui-mcpwn.nse /usr/share/nmap/scripts/
sudo nmap --script-updatedb
# Alvo único
python3 detect_nginx_ui_mcpwn.py --target https://nginx-ui.internal
# Análise em massa a partir de ficheiro
python3 detect_nginx_ui_mcpwn.py --targets targets.txt --workers 20
# Saída JSON (NDJSON) adequada para canalizar para jq
python3 detect_nginx_ui_mcpwn.py --target 10.0.0.5:9000 --json | jq .
Referência da linha de comandos: