Skip to content
KitploitKITPLOIT
StrumentiBlog
Invia
StrumentiBlog
Invia

Strumenti di Hacking, PenTest e Cybersecurity per il tuo Arsenale di Sicurezza!

Kitploit è una directory di strumenti di hacking, cybersecurity e pentesting. Scopri gli ultimi aggiornamenti dei progetti per trovare vulnerabilità, analizzare sistemi, automatizzare i test e rafforzare la tua sicurezza.

··Feed·Contatto·Privacy·© 2026 Kitploit

Directory degli strumenti

Categorie

Vedi tutte le categorie
Loading categories
Strumenti/GitHubGitHub/snizi/cve-2026-18963-exploit
Autenticazione e AutorizzazioneAnalisi delle VulnerabilitàExploitSfruttamento di Applicazioni WebPenetration Testing
GitHubsnizi/cve-2026-18963-exploit

CVE-2026-18963-Exploit

Vedi Repository

Più Popolari

Vedi tutti →

Scopri gli strumenti più utilizzati dalla nostra community.

Esplora tutti gli strumenti

Sfoglia la nostra collezione di strumenti

Vedi tutti gli strumenti →

Informazioni

714 giorni faNon ancora revisionato

Exploit per Keycloak CVE-2026-18963 che consente il takeover non autenticato dell'account tramite bypass del reset delle credenziali. Include rilevamento sicuro, prova non distruttiva, takeover completo, enumerazione degli username e un laboratorio con versioni vulnerabili e corrette.

Condividi

CVE-2026-18963 — Bypass di reset-credentials di Keycloak → account takeover non autenticato

CVE Affected Python Dependencies

Conoscendo solo un nome utente o un indirizzo e-mail, un attaccante non autenticato imposta una password arbitraria su qualsiasi account Keycloak. L'e-mail di reset della password viene consegnata alla vittima reale e non è mai necessaria — l'attaccante non legge mai una casella di posta, non fa mai clic su un link e non possiede alcuna credenziale o sessione precedente.

Interessati: Keycloak 26.0.0 – 26.7.1. Corretto in 26.7.2.


Sono vulnerabile?

Un solo comando. Nessun nome utente valido richiesto e nessun effetto collaterale — non invia alcuna e-mail, non scrive su alcun account e si ferma prima del passaggio sfruttabile.```bash git clone https://github.com/Snizi/CVE-2026-18963-Exploit cd CVE-2026-18963-Exploit

python3 cve_2026_18963_poc.py
--base https://sso.example.com --realm YOUR_REALM
--client-id account
--redirect-uri https://sso.example.com/realms/YOUR_REALM/account/
--safe-check

root@kitploit:~
Python 3.9+, solo libreria standard. Niente da installare.

| Exit | Verdetto | Significato |
|:---:|---|---|
| `0` | 🔴 **VULNERABILE** | il gate e-mail parcheggiato è stato servito — il bug stesso |
| `2` | 🟢 **CORRETTO** | il flusso è diramato al login e vi è rimasto (fix #51844 presente) |
| `2` | 🟡 **MITIGATO** | reset-credentials irraggiungibile — *Password dimenticata* è disattivato. **Non è una patch.** |
| `3` | ⚪ **INCONCLUSIVO** | risposta non riconosciuta — **non interpretarlo come un passaggio** |

Eseguilo per ogni realm — *Password dimenticata* è un'impostazione per realm, e `master` conta.
Dettagli, e perché il controllo non richiede utente e non tocca nulla, in
[§4a](#4a-safe-detection---safe-check--start-here).

**Sai già di essere esposto?** Vai a [rimedio](#8-remediation) e
[rilevamento / threat hunting](#9-detection).

### Provalo senza un target

Il repo include un lab che avvia una versione vulnerabile **26.7.1** e una corretta **26.7.2**
affiancate contro un realm identico, più una casella di posta per osservare l'e-mail di reset
arrivare e restare non letta mentre l'account viene compromesso:```bash
cd lab && docker compose up -d

python3 ../cve_2026_18963_poc.py --base http://localhost:8080 \
  --realm poc --client-id poc-app --safe-check   # VULNERABLE
python3 ../cve_2026_18963_poc.py --base http://localhost:8100 \
  --realm poc --client-id poc-app --safe-check   # PATCHED

⚠️ Solo test autorizzati

Questo repository esiste per difensori, responder agli incidenti e penetration tester autorizzati. Eseguilo solo su sistemi di tua proprietà o per i quali disponi di un'autorizzazione scritta al test. Tutto ciò che contiene è fornito con un laboratorio vulnerabile autonomo (lab/), quindi non è necessario toccare nulla di esterno per imparare come funziona il bug. Puntarlo verso infrastrutture di terze parti senza autorizzazione è illegale nella maggior parte delle giurisdizioni e non è un'attività supportata da questo progetto.

Riferimenti: keycloak#51833 · GHSA-4gv3-mc9p-5wqc · fix keycloak#51844


Indice

  • 1. Causa principale
  • 2. Versioni interessate (incluse le linee legacy)
  • 3. Il laboratorio
  • 4. Utilizzo
    • 4a. Rilevamento sicuro (--safe-check) — inizia qui
    • 4b. Prova non distruttiva (--check)
    • 4c. Compromissione completa
    • 4d. Enumerazione degli username (--enum)
  • 5. Temi di login personalizzati
  • 6. Lacuna nota — PKCE
  • 7. Validazione eseguita
  • 8. Rimedio
  • 9. Rilevamento
  • Autore

1. Causa principale

Due difetti concatenati. Nessuno dei due è sfruttabile da solo.

Difetto 1 — un flag non limitato e persistente

services/src/main/java/org/keycloak/authentication/DefaultAuthenticationFlow.java

processAction() — qualsiasi POST che trasporti la chiave del form tryAnotherWay:```java processor.getAuthenticationSession().setAuthNote( AuthenticationProcessor.AUTHENTICATION_SELECTOR_SCREEN_DISPLAYED, "true"); return createSelectAuthenticatorsScreen(model);

root@kitploit:~
La nota è un **booleano nudo senza alcuna registrazione di quale set di esecuzione l'abbia impostata**. Viene
azzerata solo nel ramo che gestisce un parametro `authenticationExecution` inviato. Ometti quel parametro — come fa questo PoC per tutto il tempo — e il flag rimane
impostato per tutta la durata della sessione di autenticazione.

`processFlow()` — finché il flag è truthy, la normale valutazione del flusso viene saltata:```java
if (Boolean.parseBoolean(authSession.getAuthNote(AUTHENTICATION_SELECTOR_SCREEN_DISPLAYED))) {
    String lastExecutionId = authSession.getAuthNote(CURRENT_AUTHENTICATION_EXECUTION);
    if (lastExecutionId != null) {
        AuthenticationExecutionModel executionModel =
            realm.getAuthenticationExecutionById(lastExecutionId);
        if (executionModel != null)
            return createSelectAuthenticatorsScreen(executionModel);   // <-- attacker-usable form
    }
}

Esegue il rendering di un modulo inviabile destinato a qualunque esecuzione sia attualmente in attesa, invece di mantenere la sessione bloccata su "in attesa dell'e-mail".

Il collante è processResult() case FORK: — quando Send Reset Email viene attivato, timbra CURRENT_AUTHENTICATION_EXECUTION = <reset-credential-email execution id> e dirama il browser alla pagina di login. L'esecuzione in attesa è precisamente il gate dell'e-mail.

Difetto 2 — il gate dell'e-mail non verifica mai il token di azione

`services/src/main/java/org/keycloak/authentication/authenticators/resetcred/ResetCredentialEmail.java````java @Override public void action(AuthenticationFlowContext context) { context.getUser().setEmailVerified(true); context.success(); }

root@kitploit:~
Unconditional. Nothing verifies that the flow was resumed by a valid action token,
so *reaching* `action()` is treated as equivalent to proving mailbox control.

### The chain```
tryAnotherWay POST            → sticky AUTHENTICATION_SELECTOR_SCREEN_DISPLAYED="true"
submit victim identifier      → mail sent to victim, e-mail execution parked (FORK)
re-enter reset-credentials    → sticky flag serves a form targeting the parked e-mail execution
POST that form                → ResetCredentialEmail.action() → success() → gate bypassed
                              → flow advances to UPDATE_PASSWORD → attacker sets the password

Sei richieste HTTP, nessuna autenticazione, nessun parametro authenticationExecution in nessun punto.

La correzione (PR #51844)

  • La nota ora memorizza model.getId(), e processFlow() la rispetta solo quando è uguale a CURRENT_AUTHENTICATION_EXECUTION, altrimenti la rimuove. Nell'attacco i due valori differiscono (id di choose-user vs. id di e-mail-gate) — esattamente ciò che la patch rileva, ed esattamente il segnale su cui si basa --safe-check.
  • ResetCredentialEmail.action() ora richiede context.getUser().getId().equals(authNote(ACTION_TOKEN_USER_ID)) e in caso contrario fallisce con INVALID_USER.

2. Versioni interessate (incluse le linee legacy)

Cosa significa "legacy" per questa CVE

  • Le release legacy non sono automaticamente sicure — sono sicure per un motivo specifico. La nota booleana sticky è stata introdotta in 26.0.0 dal commit 6a9e60bb, che ha aggiunto la schermata del selettore di autenticazione "Try another way" al flusso di reset. Qualsiasi versione precedente semplicemente non ha quel percorso di codice. Questo include le vecchie distribuzioni basate su WildFly e RH-SSO 7.x, che non sono interessate da questo bug pur rimanendo a fine vita e vulnerabili a molti altri. Rimanere su una build legacy non è una mitigazione.
  • Le linee legacy 26.x sono il vero problema. 26.7.2 è l'unica release corretta pubblicata per il ramo community. Se una distribuzione si trova su 26.0 – 26.6, non esiste alcuna release di patch su quella linea — la correzione richiede un upgrade di versione minore, non una release point. I tag 26.4.15 / 26.6.6 sono backport del vendor e non sono intercambiabili con le immagini community.
  • Poiché molte distribuzioni di lunga durata sono ancorate a una 26.x più vecchia per motivi di compatibilità, "siamo completamente patchati sulla nostra linea" è un'ipotesi comune e scorretta in questo caso. Controlla la build in esecuzione, non la policy di aggiornamento.

Prerequisiti: il realm ha Forgot password abilitato e il suo flusso di reset-credentials associato usa l'authenticator integrato reset-credential-email.


3. Il laboratorio

Il repo include sia un Keycloak vulnerabile sia uno patchato, che importano lo stesso realm, oltre a Mailpit per catturare la mail di reset — così puoi vederla arrivare e rimanere non letta mentre l'account viene compromesso.```bash cd lab docker compose up -d

root@kitploit:~
| Servizio | URL | Versione |
|---|---|---|
| `kc-vuln` | http://localhost:8080 | 26.7.1 — **vulnerabile** |
| `kc-patched` | http://localhost:8100 | 26.7.2 — **controllo corretto** |
| `kc-mailpit` | http://localhost:8025 | casella di posta della vittima |

Realm `poc`, client pubblico `poc-app`, utente `victim` / `OriginalPassw0rd!`, amministratore
Keycloak `admin` / `admin`.

Fissa diverse build con `KC_VULN_VERSION` / `KC_PATCHED_VERSION`:```bash
KC_VULN_VERSION=26.5.7 docker compose up -d keycloak-vuln

Tra le esecuzioni, lab/reset-victim.sh ripristina la password della vittima (KC=http://localhost:8100 lab/reset-victim.sh punta all'istanza patchata).

lab/legit_reset.py esegue un reset genuino estraendo il link con action-token da Mailpit e cliccandolo. È il campione di controllo per il lavoro di rilevamento in §9 — esegui sia questo che l'exploit contro lo stesso realm, poi confronta le tracce.

Teardown: docker compose down -v.


4. Utilizzo

Python 3.9+, solo libreria standard — nessuna dipendenza, si installa su qualsiasi jump box.``` --base Keycloak base URL (e.g. https://sso.example.com) --realm realm name --client-id any enabled public client with the standard flow --redirect-uri a URI permitted by that client (default http://localhost:9999/callback) --insecure skip TLS verification --verbose log every HTTP request --dump FILE write the response body of a failing step to FILE

root@kitploit:~
`--client-id` può essere qualsiasi client pubblico abilitato con il flusso standard. Il client integrato
`account` esiste in ogni realm ed è la scelta affidabile, ma limita
gli URI di reindirizzamento, quindi `--redirect-uri` **deve** quindi essere
`<base>/realms/<realm>/account/` — il valore predefinito viene rifiutato e il passaggio 1 fallisce.

### 4a. Rilevamento sicuro (`--safe-check`) — inizia qui

Non richiede **alcun nome utente valido** e **non ha effetti collaterali**. Questa è la sonda da usare
quando non devi disturbare il target.```bash
python3 cve_2026_18963_poc.py \
  --base https://sso.example.com --realm corp \
  --client-id account \
  --redirect-uri https://sso.example.com/realms/corp/account/ \
  --safe-check

Perché non richiede un utente e non invia alcuna e-mail. ResetCredentialEmail.authenticate() si dirama anche per un utente sconosciuto:```java if (user == null) { context.forkWithSuccessMessage(EMAIL_SENT); return; }

root@kitploit:~
`processResult()` `case FORK:` quindi mette in pausa `CURRENT_AUTHENTICATION_EXECUTION`
sull'esecuzione e-mail **anche se non è stato trovato nessuno** — e nessuna mail viene inviata,
perché non c'è nessuno a cui inviarla. La sonda si ferma al discriminatore e non
POSTa mai il gate, quindi `action()` non viene mai eseguita: nessuna NPE sul target, nessuna scrittura
di `emailVerified`, nessuna mail, nessun account toccato.

**Asserisce solo sul segnale positivo.** VULNERABILE ⟺ il passo 5 restituisce un form
ancora dentro `login-actions/reset-credentials` la cui `execution` differisce dall'esecuzione
di choose-user. Questo *è* il bug: la nota obsoleta
`AUTHENTICATION_SELECTOR_SCREEN_DISPLAYED` che serve il gate e-mail in pausa.
Entrambe le metà contano — il percorso prova che siamo ancora nel flusso di reset, l'id
di esecuzione diverso prova che è il gate e-mail e non un re-render.

Qualsiasi altra cosa **non** viene silenziosamente dichiarata patched. PATCHED richiede la propria evidenza
(fork verso `login-actions/authenticate` *e* un campo password presente); tutto il resto
è INCONCLUSIVE e richiede un intervento umano. Un design precedente trattava "non il
form del gate" come patched, trasformando silenziosamente ogni tema personalizzato, pagina di errore, blocco WAF
e interstiziale in un falso certificato di salute.

### 4b. Prova non distruttiva (`--check`)

Guida l'intera catena ma si ferma al form Update Password. Raggiungere quel form
senza un action token è conclusivo.```bash
python3 cve_2026_18963_poc.py \
  --base https://sso.example.com --realm corp \
  --client-id account \
  --redirect-uri https://sso.example.com/realms/corp/account/ \
  --victim [email protected] --check

Due effetti collaterali sono inevitabili, perché avvengono a monte del modulo della password — dichiarali nell'ambito dell'engagement:

  • una e-mail di reimpostazione della password viene consegnata alla vittima reale (il passaggio 4 è una richiesta di reimpostazione genuina), e
  • la vulnerabile action() imposta emailVerified = true sull'account.

Nessuna credenziale viene modificata. Preferisci un account di test dedicato.

4c. Compromissione totale

Solo in laboratorio o in una dimostrazione esplicitamente autorizzata.```bash python3 cve_2026_18963_poc.py
--base http://localhost:8080 --realm poc --client-id poc-app
--victim victim --new-password 'PoCPassw0rd!1'

root@kitploit:~
Esci `0` vulnerabile · `2` non sfruttabile · `1` password cambiata ma la conferma
grant non è riuscita (punta `--verify-client-id` a un client con Direct Access Grants).

Completare il flusso restituisce anche un **codice di autorizzazione OIDC per la vittima**, quindi
il takeover è immediato — non è richiesto un secondo login con la nuova password.

### 4d. Enumerazione degli username (`--enum`)

La stessa falla è un oracolo per gli username, e più potente di quanto Keycloak normalmente
consenta. `ResetCredentialEmail.authenticate()` restituisce deliberatamente un identico
*"You should receive an email shortly"* per utenti reali e sconosciuti, quindi il modulo di reset
stesso non può essere usato per enumerare — quella difesa regge ancora al passo 4. Si rompe
al **passo 6**, dove `action()` dereferenzia l'utente incondizionatamente
(`context.getUser().setEmailVerified(true)`).

| Identificatore | Passo 6 | Verdetto |
|---|---|---|
| utente reale | `200`, raggiunge il modulo Update Password | VALIDO |
| utente sconosciuto | `400` (pagina di errore NPE) | NON VALIDO |```bash
python3 cve_2026_18963_poc.py \
  --base http://localhost:8080 --realm poc --client-id poc-app \
  --enum candidates.example.txt

Non modifica mai una password. Esce con 0 se un qualsiasi identificatore viene risolto, 2 altrimenti.

Costo per sonda — leggere prima di eseguire. Raggiungere l'oracolo richiede il completamento del passaggio 4, quindi ogni sonda contro un account reale invia a quella persona una vera e-mail di reimpostazione della password e imposta emailVerified = true sul suo record. Non è un controllo silenzioso: è visibile al titolare dell'account e muta i suoi dati. Una wordlist di 5.000 nomi equivale a 5.000 e-mail a persone reali e 5.000 account mutati.

Usalo per dimostrare che l'oracolo esiste su una manciata di identificatori per il report — non per raccogliere una directory. Le protezioni sono deliberatamente prudenti:

  • --enum-max N rifiuta liste più lunghe di N (default 25)
  • --enum-delay SEC mette in pausa tra le sonde (default 2.0)

Alzare uno dei due dovrebbe essere una decisione consapevole registrata nelle note dell'engagement.

Angolo di reporting: questo sconfigge un controllo anti-enumerazione che Keycloak ha implementato di proposito. Vale la pena scriverlo come finding a sé stante insieme al takeover, e annulla "i nostri username non sono indovinabili" come fattore mitigante.


5. Tema di login personalizzati

Qualsiasi deployment serio include un tema di login personalizzato, e i temi personalizzati rinominano o eliminano gli id degli elementi standard (kc-form-login, kc-reset-password-form, kc-select-credential-form, kc-passwd-update-form). Uno strumento che si basa su quegli id riporta un falso negativo proprio sui deployment che contano di più — questo lo faceva, prima di essere riscritto. I temi visti in produzione usano id come id="login-form" e includono un'ancora password dimenticata con un href vuoto.

Questa PoC quindi non si basa su nulla che sia controllato dal tema:

  • Solo gli URL di azione dei form. Ogni decisione viene presa dall'action= dei form sulla pagina — login-actions/reset-credentials, login-actions/authenticate, login-actions/required-action — e dal parametro di query execution al loro interno. Questi percorsi sono generati dal LoginActionsService di Keycloak stesso, non dal tema.
  • Nessun id di elemento. grep del sorgente: non c'è un solo id kc-* al suo interno.
  • Nessun testo di messaggio. Le stringhe di risposta sono localizzate — un realm tedesco risponde "Reset Credential nicht erlaubt", e il match su "You should receive an email" fallisce su ogni realm non inglese.
  • Non segue mai un link "Password dimenticata" del tema. Il link può essere assente, vuoto, guidato da JavaScript, o puntare completamente fuori da Keycloak — nessuna di queste cose dice qualcosa sulla raggiungibilità dell'endpoint. Lo strumento costruisce /realms/<realm>/login-actions/reset-credentials?client_id=…&tab_id=… e lo sonda direttamente, prendendo tab_id da qualunque form la pagina di login esponga.

Se un target restituisce ancora INCONCLUSIVE, esegui con --verbose --dump out.html e leggi la risposta — lo strumento rifiuta deliberatamente di fare supposizioni.


6. Lacuna nota — PKCE

Un client che applica PKCE rifiuta il passaggio 1 con Missing parameter: code_challenge_method. Questo viene riportato come INCONCLUSIVE (exit 3), mai come superato. Finché non arriva il supporto PKCE, un realm il cui unico client pubblico utilizzabile impone PKCE non può essere verificato con questo strumento — prova il client integrato account, che normalmente non lo impone.


7. Validazione eseguita

Ogni esecuzione qui sotto è contro il lab in questo repo, usando il codice come pubblicato.

Due finding che vale la pena segnalare oltre al testo dell'advisory:

  1. Gli account senza indirizzo e-mail sono sfruttabili. ResetCredentialEmail.authenticate() prende il percorso forkWithSuccessMessage quando user.getEmail() è null, che comunque parcheggia l'esecuzione tramite case FORK:. Lo stesso vale per un errore di invio SMTP — un server di posta rotto o assente non è una mitigazione. Questo conta direttamente per i realm federati AD/LDAP, dove gli account spesso non hanno alcun attributo mail.
  2. Completare il flusso fa accedere l'attaccante come vittima. Il redirect finale trasporta un codice di autorizzazione OIDC valido, quindi l'account è compromesso nel momento in cui viene inviato il form della password.

L'MFA non è una mitigazione. Il flusso di reset-credentials predefinito non contiene alcun passaggio OTP, e una volta superato, l'attaccante può rimuovere i fattori registrati della vittima.


8. Rimedio

Fix: aggiornare. 26.7.2 per le build community, o il backport del vendor corrispondente alla tua sottoscrizione. Tutto il resto è un ripiego.

Mitigazioni provvisorie, dalla migliore in giù:

  1. Disattiva Password dimenticata per realm (Realm settings → Login). Confermato efficace — il flusso restituisce HTTP 400 e non può essere avviato. Controlla ogni realm, incluso master.
  2. Disattiva l'esecuzione Reset Password nel flusso reset-credentials associato. Funziona, ma la pagina di login offre ancora il link, quindi l'UX è scadente. Utile dove un tema personalizzato ignora l'interruttore del realm.
  3. Aggiungi un autenticatore obbligatorio (OTP/WebAuthn) dopo il passaggio e-mail nel flusso di reset. Questo non chiude il bypass — limita solo il takeover completo agli account che hanno effettivamente registrato quel fattore.

I realm il cui flusso di reset associato è completamente personalizzato e non invoca mai reset-credential-email non sono sfruttabili tramite questo percorso.


9. Rilevamento

Keycloak non emette alcun evento "action token saltato", quindi il rilevamento è euristico. Esegui lab/legit_reset.py insieme all'exploit per generare entrambe le tracce e confrontarle.

  • Log del reverse-proxy / ingress — il segnale più forte. Un reset legittimo mostra una GET /login-actions/action-token?... (la vittima che clicca la mail) prima del cambio password. Il bypass non ha tale GET. Mostra invece una POST su login-actions/reset-credentials il cui corpo contiene tryAnotherWay, seguita da una seconda POST sullo stesso percorso con corpo vuoto, poi il form della password. Una POST tryAnotherWay dentro il flusso di reset non è qualcosa che l'UI standard produce nell'uso normale.
  • Eventi admin: SEND_RESET_PASSWORD seguito da UPDATE_PASSWORD che condividono lo stesso code_id entro pochi secondi — sub-secondo nel lab. Anche un utente con la mail già aperta può sembrare veloce, quindi conferma con i log del proxy.
  • Account il cui emailVerified è passato a true senza un corrispondente evento VERIFY_EMAIL sono un indicatore di supporto utile, e uno che l'attaccante non può evitare di lasciare.

L'assenza di eventi non prova nulla se il logging o la conservazione degli eventi era disattivata. Controlla la finestra di conservazione prima di concludere che un deployment non sia stato colpito.


Autore

Snizi — github.com/Snizi — [email protected]

Rilasciato sotto Licenza MIT. Issue e PR benvenuti — in particolare supporto PKCE e ulteriori stranezze dei temi reali.

Scarica lo strumento
LineaVulnerabileFix community
Legacy (Keycloak basato su WildFly, ≤ 17)non interessata—
Quarkus 17 – 25.xnon interessata—
26.026.0.0 – 26.0.17nessuno
26.126.1.0 – 26.1.5nessuno
26.226.2.0 – 26.2.16nessuno
26.326.3.0 – 26.3.5nessuno
26.426.4.0 – 26.4.1426.4.15 (tag di backport del vendor)
26.526.5.0 – 26.5.7nessuno
26.626.6.0 – 26.6.526.6.6 (tag di backport del vendor)
26.726.7.0 – 26.7.126.7.2
ExitVerdictSignificato
0VULNERABILEè stato servito il gate e-mail in attesa — il bug stesso
2PATCHEDil flusso si è diramato verso il login e vi è rimasto (fix #51844 presente)
2MITIGATOreset-credentials irraggiungibile — Forgot password è disattivato. Non è una patch.
3INCONCLUSIVOrisposta non riconosciuta — non interpretarlo come un passaggio
TestTargetRisultato
--safe-check26.7.1VULNERABILE, exit 0 — gate e-mail servito (execution ≠ choose-user)
--safe-check26.7.2CORRETTO, exit 2 — diramato al login e rimasto lì
--safe-check, Password dimenticata disattivata26.7.2MITIGATO, exit 2 — HTTP 400, flusso irraggiungibile
Takeover completo26.7.1exit 0 — password impostata, codice OIDC emesso, password grant conferma
Takeover completo26.7.2exit 2 — bloccato al passaggio 5, account intatto
--check26.7.1raggiunto UPDATE_PASSWORD; password verificata invariata dopo
--enum26.7.1victim e [email protected] VALIDI, does-not-exist NON VALIDO
Stato credenziali dopo il takeover26.7.1nuova password → 200, vecchia password → 400
Stato credenziali dopo esecuzione bloccata26.7.2vecchia password → 200, password dell'attaccante → 400
Casella di posta della vittimaMailpite-mail di reset consegnate e non lette; il link con action-token non viene mai recuperato