
Suche nach Spuren der Ausnutzung von CVE-2026-18963 (nicht authentifizierte Kontoübernahme in Keycloak) in der Keycloak-Datenbank
Ein psql-Skript, das eine Keycloak-PostgreSQL-Datenbank nach Spuren der
Ausnutzung von CVE-2026-18963 durchsucht (unauthentifizierte Kontoübernahme über
den Reset-Credentials-Flow).
Veröffentlicht von KYOS. Wir haben es während des Patchens der von uns betriebenen Keycloak-Deployments geschrieben, um zu überprüfen, ob während des Expositionszeitraums jemand übernommen wurde.
CVE-2026-18963 ist ein Fehler im Reset-Credentials-Flow von keycloak-services
(keycloak#51833). Ein
unauthentifizierter Angreifer kann den Passwort-Reset-Prozess für jeden Benutzer
abschließen, ohne den E-Mail-Verifizierungslink anzuklicken, und anschließend ein
neues Passwort für das Konto setzen. Es ist keine Benutzerinteraktion erforderlich.
Geprüft gegen Keycloak 26.7.1 auf einer Wegwerf-Instanz. Wir veröffentlichen keine Reproduktionsschritte; die folgenden Details sind diejenigen, die man zum Lesen der Abfragen benötigt.
Der Flow verfolgt, auf welchem Authenticator-Bildschirm er sich befindet, und zwar
auf eine Weise, die nicht an den Schritt gebunden ist, der ihn gesetzt hat. Dadurch
kann der Reset-Credentials-Flow beim E-Mail-Verifizierungsschritt erneut betreten
werden, wo die verwundbare ResetCredentialEmail.action() Erfolg zurückgibt, ohne
jemals nach einem Action-Token zu prüfen. Die Ausführung fährt dann mit dem
Update-Password-Formular fort.
Zwei Konsequenzen prägen jede Abfrage in diesem Repo:
SEND_RESET_PASSWORD-Event. Das Fehlen dieses Events ist keine Signatur.action() markiert die E-Mail-Adresse des Kontos als
verifiziert, bevor sie zurückkehrt. Der legitime Pfad erreicht action()
überhaupt nie, sodass dies eine Zustandsänderung ist, die nur die Umgehung
erzeugt. Q3 stützt sich darauf.Der Fix (keycloak#51844)
bindet den Bildschirmzustand an die Ausführung, die ihn gesetzt hat, und lässt
action() nur dann erfolgreich sein, wenn ein Action-Token für genau diesen
Benutzer vorhanden ist.
Schweregrad: Kritisch, CVSS v3.1 9.1 (AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:N),
laut Red Hat und
NVD. Die Ursache ist eine
unzureichende Zustandsvalidierung im Authentifizierungs-Flow, behoben in
keycloak#51844.
| Stream | Behoben in |
|---|---|
| 26.7.x | 26.7.2 (Release Notes) |
| 26.6.x | 26.6.6 |
| 26.4.x (LTS) | 26.4.15 |
| 26.8 | 26.8.0 |
Alles unterhalb dieser Versionen in den unterstützten Streams ist verwundbar. Releases außerhalb des Supports (26.5.x, 26.3 und älter) erhalten keinen Fix: Exposition annehmen und auf einen behobenen Stream aktualisieren. Red Hat führt Legacy-RH-SSO 7 als nicht betroffen; der Red Hat Build of Keycloak 26.4/26.6 ist in 26.4.15-1 / 26.6.6-1 behoben.
Das Deaktivieren des Self-Service-Passwort-Resets entfernt den verwundbaren
Einstiegspunkt: Admin-Konsole > Realm-Einstellungen > Anmeldung > „Passwort
vergessen" aus, für jeden Realm. Über die Admin-API: PUT /admin/realms/{realm}
mit {"resetPasswordAllowed": false}.
Dies blockiert den Endpunkt login-actions/reset-credentials, verhindert aber
auch, dass legitime Benutzer ihr eigenes Passwort zurücksetzen. Behandeln Sie es
daher als Übergangslösung, bis Sie aktualisieren. Beachten Sie, dass Red Hat keine
empfohlene Mitigation für diese CVE auflistet; das Patchen ist der einzige echte
Fix.
Die erste Version dieses Skripts markierte einen abgeschlossenen Reset, dem kurz
zuvor kein SEND_RESET_PASSWORD vorausging.
Das war falsch, und
vilmosnagy hat darauf hingewiesen,
nachdem er die CVE auf seiner eigenen Instanz reproduziert und beobachtet hatte, dass das Ereignis
trotzdem auftauchte. Der Grund ist die erste Konsequenz oben: Der Mail-Authenticator läuft
normal, sodass das Opfer eine echte Reset-Mail erhält und Keycloak ein gewöhnliches
SEND_RESET_PASSWORD protokolliert. Die Prüfung war invertiert. Sie hätte jedes
kompromittierte Konto, das sie untersuchte, freigegeben. Sie ist entfernt.
Zeitbasierte Verfahren haben ein kleineres, aber reales Problem. Der Ansatz in
thomasdelorges Hunt-Skript
korreliert SEND_RESET_PASSWORD mit UPDATE_PASSWORD über eine gemeinsame code_id
und markiert eine kurze Zeitspanne. Der Korrelationsschlüssel ist richtig, und der Autor stellt ausdrücklich
klar, dass der Schwellenwert eine Heuristik ist. Unsere Tests sagen dasselbe: Ein umgangener Reset
und ein legitimer, im selben Browser abgeschlossener Reset erzeugen identische Ereignistypen,
identische Detail-Schlüssel und dieselbe code_id. Nur die Verzögerung unterscheidet sich,
was bedeutet, dass der Schwellenwert das gesamte Urteil trägt. Wer es nicht eilig hat, bleibt
darunter. Echte Nutzer lösen ihn aus, weil die code_id nur dann gleich bleibt, wenn der
Link in dem Browser geöffnet wird, der den Vorgang gestartet hat – was auch der Fall ist,
in dem die Mail wahrscheinlich bereits geöffnet vorliegt.
Wir fanden kein Ereignis, kein Ereignisdetail und keinen Fehler, der die beiden trennt. Es gibt kein „Mail-Schritt übersprungen“-Ereignis, nach dem man suchen könnte. Was es gibt, ist ein Nebeneffekt im Zustand, und diesen nutzt Q3.
cve-2026-18963-keycloak-hunt.sql führt sechs schreibgeschützte Abfragen aus:
| Abfrage | Was sie findet |
|---|---|
| Q0 | Ob der Realm überhaupt Ereignisse speichert, deren TTL und ob Ereignis-Details persistiert werden. Q2 korreliert über das code_id-Detail, sodass Q2 blind ist, wenn Details fehlen, und sein Schweigen nichts bedeutet. |
| Q1 | Jede Passwort-Anmeldedaten-Setzung innerhalb des Expositionsfensters (credential.created_date). Dies ist die Übernahme selbst, und sie überlebt den Ablauf der Ereignisse. |
| Q2 | Jede abgeschlossene Anmeldedaten-Aktualisierung, korreliert mit der Reset-Mail derselben Authentifizierungssitzung, und klassifiziert. Siehe unten. |
| Q3 | Der deterministische Nebeneffekt: Benutzer, die email_verified sind, ohne legitime Ursache. |
| Q4 | Admin-API-Anmeldedaten-Resets und Benutzerschreibvorgänge, um Q1- und Q3-Zeilen zu erklären und die admin-gesteuerte Route auszuschließen. |
| Q5 | Rohe Zeitlinie der Reset-/Anmeldedaten-Ereignisse, um einen einzelnen Fall manuell zu lesen. |