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
CVE-2026-18963 — Docker-basiertes Lab und Python-Exploit für CVE-2026-18963, eine Umgehung des Keycloak-Reset-Credentials-Flows, die Account-Übernahme durch Umgehung der E-Mail-Verifizierung ermöglicht. | Kitploit
Tools/GitHubGitHub/ivanesk315/cve-2026-18963
SchwachstellenanalyseExploitationWebanwendungs-ExploitationWebsicherheitPenetrationstestsIdentitäts- & Zugriffsmanagement (IAM)AuthentifizierungLernen & BildungLabs & Praxis
GitHubivanesk315/cve-2026-18963

CVE-2026-18963

Docker-basiertes Lab und Python-Exploit für CVE-2026-18963, eine Umgehung des Keycloak-Reset-Credentials-Flows, die Account-Übernahme durch Umgehung der E-Mail-Verifizierung ermöglicht.

vor 0 TagenNoch nicht geprüft
Repository anzeigen

Beliebteste

Alle anzeigen →

Entdecken Sie die meistgenutzten Tools unserer Community.

Alle Tools erkunden

Durchsuchen Sie unsere Tool-Sammlung

Alle Tools anzeigen →
Teilen

CVE-2026-18963 — Keycloak Reset-Credentials Flow Bypass Lab

Überblick

Lab simuliert die Schwachstelle CVE-2026-18963 (CVSS 9.1) in Keycloak, die es einem Angreifer ermöglicht, die Kontrolle über ein beliebiges Konto zu übernehmen, indem die E-Mail-Verifizierung im Passwort-Reset-Flow umgangen wird.

Nur für Sicherheitsforschung und Bildungszwecke.

Voraussetzungen

  • Docker & Docker Compose
  • Python 3.8+
  • pip

Anleitung

1. Verwundbaren Keycloak starten

root@kitploit:~
docker-compose up -d

Warten, bis Keycloak gestartet ist (~30-60 Sekunden).

2. Lab einrichten

root@kitploit:~
pip install -r requirements.txt
python setup-lab.py

Das Skript erstellt:

  • Realm vuln-lab mit aktiviertem reset-password
  • SMTP-Konfiguration (MailHog) zum Versenden von E-Mails
  • Benutzer victim ([email protected] / VictimPass123!)

3. Exploit ausführen

root@kitploit:~
python exploit.py -u http://127.0.0.1:8080 -r vuln-lab -t victim -p Pwned123!

Optionen:

  • -u / --url: Keycloak-URL (Standard: http://127.0.0.1:8080)
  • -r / --realm: Realm-Name (Standard: vuln-lab)
  • -t / --target: Ziel-Benutzername (Standard: victim)
  • -p / --password: Neues Passwort (Standard: Pwned123!)
  • -v / --verbose: Debug-Ausgabe aktivieren

4. E-Mail ansehen (optional)

MailHog UI: http://127.0.0.1:8025 — zeigt die während des Exploits versendete reset-password-E-Mail.

5. Aufräumen

root@kitploit:~
docker-compose down -v

Technische Details

Ursache

Zwei kombinierte Fehler in Keycloak bilden die Angriffskette:

Fehler 1 — Selector-State-Korruption (DefaultAuthenticationFlow.java): Wenn der Benutzer auf "Try Another Way" klickt, wird die Auth-Notiz AUTHENTICATION_SELECTOR_SCREEN_DISPLAYED als "true" (Boolean-String) statt als Execution-Model-ID gespeichert. Der Wert "true" ist an keine bestimmte Execution gebunden, daher bleibt er über die Schritte im Flow hinweg bestehen und führt dazu, dass der Selector im falschen Kontext angezeigt wird.

Fehler 2 — Bedingungsloser Action-Erfolg (ResetCredentialEmail.java): Die Methode action() von ResetCredentialEmail ruft context.success() bedingungslos auf, ohne das Action-Token zu prüfen. Normalerweise wird action() nur aufgerufen, wenn der Benutzer auf den Link in der E-Mail klickt (mit Action-Token). Wenn der Selector jedoch korrumpiert ist, kann der Angreifer action() direkt über die Flow-Verarbeitung auslösen.

Detaillierter Angriffsablauf

root@kitploit:~
Angreifer                             Keycloak
   │                                     │
   │─── GET /auth (OIDC + PKCE) ────────>│  1. Auth-Session initialisieren
   │<── Login-Seite + Cookies ───────────│
   │                                     │
   │─── GET /reset-credentials ─────────>│  2. Zum Reset-Flow wechseln
   │<── Benutzername-Formular ──────────│
   │                                     │
   │─── POST tryAnotherWay=on ─────────>│  3. Selector-State korrumpieren
   │<── Authenticator-Selector ─────────│     SELECTOR_DISPLAYED = "true"
   │                                     │
   │─── POST username=victim ──────────>│  4. Benutzername über Selector senden
   │<── "Check your email"-Seite ───────│     E-Mail gesendet, CURRENT_EXEC = email_id
   │                                     │
   │─── GET /reset-credentials ────────>│  5. Reset-Flow erneut betreten
   │<── Korrumpierter Selector (!!!) ───│     processFlow() sieht SELECTOR="true"
   │                                     │     → zeigt Selector für E-Mail-Schritt an
   │                                     │
   │─── POST {} (leerer Body) ─────────>│  6. BYPASS: action() auslösen
   │<── 302 → UPDATE_PASSWORD ─────────│     processAction() findet kein
   │                                     │     authenticationExecution im Formular
   │─── GET /required-action ──────────>│     → fällt in den action()-Zweig
   │<── Passwort-Update-Formular ──────│     ResetCredentialEmail.action()
   │                                     │     → context.success() (bedingungslos!)
   │                                     │     → Flow wechselt zu ResetPassword
   │                                     │
   │─── POST password-new=Pwned! ──────>│  7. Neues Passwort setzen
   │<── 302 → /account/ ──────────────│     Account-Übernahme abgeschlossen
   │                                     │
   └── Mit neuem Passwort anmelden ─────┘

Warum funktioniert Schritt 6?

In DefaultAuthenticationFlow.processAction() beim Empfang eines POST:

  1. Prüft tryAnotherWay im Formular → NEIN (Formular leer)
  2. Prüft authenticationExecution im Formular → NEIN (Formular leer)
  3. Fällt in den letzten Zweig: ruft authenticator.action(result) auf dem Model aus der URL auf

Da die URL execution=<email_exec_id> enthält (aus der Selector-Formular-Action), wird ResetCredentialEmail.action() aufgerufen → gibt context.success() zurück → Flow wechselt zu ResetPassword → zeigt das Formular zum Setzen des Passworts an.

Betroffene Versionen

ProduktBetroffenGepatcht
Keycloak (upstream)< 26.7.226.7.2+
RHBK 26.4.x< 26.4.1526.4.15+
RHBK 26.6.x< 26.6.626.6.6+

Patch (PR #51844)

DefaultAuthenticationFlow.java:

  • setAuthNote(SELECTOR_DISPLAYED, "true") → setAuthNote(SELECTOR_DISPLAYED, model.getId())
  • processFlow() prüft selector.equals(lastExecutionId) statt Boolean.parseBoolean()
  • Bei Nichtübereinstimmung → removeAuthNote(SELECTOR_DISPLAYED)

ResetCredentialEmail.java:

  • action() prüft ACTION_TOKEN_USER_ID vor dem Aufruf von context.success()
  • Wenn kein gültiges Action-Token vorhanden → context.failure(INVALID_USER)

Referenzen

  • NVD - CVE-2026-18963
  • Red Hat CVE Page
  • Keycloak Issue #51833
  • Fix PR #51844
  • Kudelski Security Research
  • The Hacker News
Tool herunterladen