Next.js is one of the most popular frameworks in the React ecosystem, powering countless web apps with its powerful server-side features. But in June 2024, a critical security vulnerability came to light: CVE-2024-34351, a Server-Side Request Forgery (SSRF) vulnerability lurking in Next.js Server Actions. In this long read, we’ll break down what happened, the technical details, show you sample code, and provide additional resources to keep your apps safe.

What is CVE-2024-34351?

CVE-2024-34351 is a SSRF vulnerability. SSRF happens when a web application fetches remote resources based on user input, but doesn’t properly check or sanitize what it’s told to fetch. If abused, attackers can make the server itself send requests to *internal* services or arbitrary endpoints on the Internet — all as if the requests came from your application.

Used Server Actions

3. Had Server Actions with redirects to a *relative path* (e.g., /dashboard) after an action

The Setup

A vulnerable Next.js app is running and exposes an endpoint that uses a Server Action. After the action, it issues a redirect(), like so:

// app/actions.ts

'use server';

import { redirect } from 'next/navigation';

export async function doSomething() {
  // Some logic...

  // Redirect to a relative path after the action
  redirect('/dashboard');
}

This pattern is pretty common — and previously, it looked safe.

The Attack

An attacker crafts an HTTP request to the Next.js server, but they *spoof* the Host header. Here's an example (using curl):

curl -X POST \
  -H "Host: 169.254.169.254" \
  https://your-app.com/_actions/doSomething

Why does this work? Because, if the following conditions are met

- Next.js is self-hosted: Meaning, you control your own server and aren’t behind a locked-down cloud provider.

Server Actions are used: Which lets the attacker trigger backend logic.

- Redirects to relative paths: The vulnerable server code issues redirect('/something') after processing.

Next.js’ internal logic could be tricked into making the redirect target resolve against the value of the *Host* header supplied, rather than the expected original domain. If the Host is set to something internal like 169.254.169.254 (which is used for AWS metadata services), the relative redirect would now target an endpoint on the internal network (from the server's point of view).

Depending on how your server, deployment, and permissions are set up, this could allow internal metadata theft, data exfiltration, or internal port scanning.

Here's an example of a minimal vulnerable action

// app/actions.ts
'use server';

import { redirect } from 'next/navigation';

export async function exploitMe() {
  // Simulate processing some form or input data

  // Vulnerable redirect
  redirect('/internal/path');
}

And to exploit it

curl -X POST \
  -H "Host: 169.254.169.254" \
  https://your-domain.com/_actions/exploitMe

If the server is running this on a cloud VM (e.g., AWS EC2), and the network is open, this could cause the Node.js process to request http://169.254.169.254/internal/path — which on AWS could expose the EC2 instance metadata!

How to Fix

Simple answer: Upgrade Next.js to 14.1.1 or later.
This version patched the issue so that the Host header is ignored for purposes of redirects, and relative redirects are always resolved as intended.

Official Next.js Advisory:

CVE-2024-34351 – SSRF in Next.js Server Actions

NIST CVE Database:

CVE-2024-34351 record

Next.js Release Notes:

Next.js 14.1.1 Changelog

Understanding SSRF Attacks:

PortSwigger: SSRF Explained

Bottom Line

If you run a self-hosted Next.js app and use Server Actions, you must upgrade to Next.js 14.1.1 or higher. This prevents attackers from leveraging malformed Host headers for SSRF attacks, which could compromise your infrastructure.

Patch quickly, and always validate untrusted data — including HTTP headers. Security is baked-in, not bolted-on!

Timeline

Published on: 05/14/2024 15:38:42 UTC
Last modified on: 05/14/2024 16:12:23 UTC