
PoC di loopback per una vulnerabilità del broker SAML di Keycloak 26.8.1: un nome SAMLResponse duplicato con codifica percentuale aggira la verifica della firma di reindirizzamento, consentendo l'accesso come un altro utente.
Chi non ha un account Keycloak può completare il login SAML aziendale come un'altra persona. Effettua l'accesso una volta presso l'identity provider upstream, conserva quel redirect firmato e antepone un secondo documento SAML sotto un nome codificato in percentuale. Keycloak verifica la firma autentica e poi effettua l'accesso con il nome presente nel documento falsificato. Questo richiede un broker SAML che firmi le risposte HTTP-Redirect, con la validazione della firma attiva e le firme delle assertion disattivate, che è ciò che configura l'importazione dei metadati. Non è la suddivisione tramite punto e virgola della issue #53354.
Classe: OAuth leftover Portata: Remota (non autenticato verso Keycloak; richiede un broker SAML che firmi i redirect)
Keycloak 26.8.1 (24ed1dad) - Red Hat
| ID | nessuna CVE al momento |
| Classe | OAuth leftover |
| Portata | Remota (nessun account Keycloak; richiede una firma HTTP-Redirect autentica dall'IdP) |
| CWE | CWE-287 / CWE-347 / CWE-116 |
| CVSS | Alto: 7.4 CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:H/I:H/A:N |
| Prodotto | Keycloak |
| Affetto | 26.8.1 (24ed1dadf3f246a555adb6d3d4a99e9b3003fb3b); Quarkus 3.40.1; immagine quay.io/keycloak/keycloak:26.8.1 |
| Auth | nessuna su Keycloak. Richiede un broker identity-provider SAML con validateSignature=true e wantAssertionsSigned assente o false. |
| Licenza | GNU Affero GPL v3.0 |
| Lab | solo 127.0.0.1:18084 |
Richiede il NameID della vittima (di solito un'email) e un redirect HTTP-Redirect realmente firmato da quell'IdP. Non richiede una password Keycloak. Non richiede una casella di posta. Un IdP solo POST non fornisce quella firma. L'ACS GET resta montato anche quando l'importazione dei metadati preferisce POST.
| Privilegio | Metodo / sink | Recon / integrità / disponibilità | Provato in lab o dedotto |
|---|---|---|---|
| Associare un documento SAML falsificato mentre la firma autentica viene comunque verificata | ACS del broker GET con SAML%52esponse=<forged> prima del SAMLResponse firmato | Integrità (autenticazione) | Provato in lab. Email di controllo [email protected]. Email dell'attacco [email protected] |
| Creare l'utente vittima tramite first-broker-login | callback.authenticated sul NameID falsificato | Integrità (creazione account) | Provato in lab. Conteggio vittime 0 prima della query suddivisa, 1 dopo |
| Sessione come utente esistente brokerato, incluso un admin che usa lo stesso IdP | Stesso ACS, NameID di quell'utente | Integrità (compromissione account) | Dedotto. Il lab ha creato la vittima al primo login |
| Mantenere RelayState e la sessione di autenticazione | RelayState resta il valore firmato | Integrità | Sorgente. La firma copre RelayState |
| Controllo negativo | Redirect firmato autentico, nessun parametro aggiuntivo | n/d | Provato in lab. Il controllo termina con l'email dell'attaccante |
Resta chiuso su questo leftover
| Asse | Metodo / sink | Perché è chiuso |
|---|---|---|
| Integrità | Suddivisione con punto e virgola SAMLResponse=...;SAMLResponse=... | issue #53354. quarkus.http.use-semicolon-as-query-param-delimiter=false |
| Integrità | Assertion non firmata quando wantAssertionsSigned=true | handleLoginResponse richiede quindi una firma dell'assertion |
| Integrità | Nessun broker SAML, o IdP solo POST senza firma del redirect | L'attaccante non ottiene mai SigAlg + Signature su una GET |
| Integrità | RCE sull'host, Admin REST non autenticato | Fuori classe |
| Integrità | Forma del nome predefinita VERIFY_PROFILE | Provato in lab come passaggio di completamento, non come confutazione. Il form contiene già l'email brokerata |
Ho fissato Keycloak 26.8.1. RESTEasy Reactive prende @QueryParam("SAMLResponse") da Vert.x, che decodifica percentualmente i nomi dei parametri di query, quindi SAML%52esponse collassa su SAMLResponse e vince il primo valore. verifyRedirectSignature ricostruisce la stringa firmata da getQueryParameters(false) sulla query grezza, dove quel nome resta una chiave diversa.
Vicoli ciechi già registrati: trattare #53354 come questo residuo (nome percent-encoded, non punto e virgola); seguire i 302 dell'ACS nel client di laboratorio e perdere AUTH_SESSION_ID; leggere firstName/lastName vuoti su VERIFY_PROFILE come un mancato riscontro (l'email è già il NameID intermediato); una reverse shell. Teatro.
Python 3.11+ con cryptography. Docker richiesto.
python3 keycloak-saml-redirect-param-split-Abraxas-Labs.py
o:
cd lab
./run.sh
Prendi di mira solo http://127.0.0.1:18084. Immagine quay.io/keycloak/keycloak:26.8.1. Il launcher esegue chdir in lab/ ed esegue run.sh. L'IdP del lab è in-process. Non comunica mai con un vero identity provider.
IOC image=quay.io/keycloak/keycloak:26.8.1 label-version=26.8.1
IOC serverinfo-version=26.8.1
IOC validate-signature=true want-assertions-signed=absent
IOC review-profile=DISABLED
IOC [email protected]
IOC victim-before=0
IOC [email protected]
IOC victim-after=1
SUCCESS KC-H04-SAML-REDIRECT kcs04b8n1
Verificare lo stesso documento di query che l'endpoint analizza. Decodificare percentualmente i nomi dei parametri prima della ricostruzione della firma, oppure rifiutare una query che contiene più di un SAMLResponse dopo la decodifica. Attivare wantAssertionsSigned per i broker di redirect, incluso il percorso di importazione dei metadati.
24ed1dadf3f246a555adb6d3d4a99e9b3003fb3b)SAMLEndpoint.redirectBinding (SAMLEndpoint.java:182-183, :779-813, :896-914)SamlProtocolUtils.verifyRedirectSignature (SamlProtocolUtils.java:216-249)KeycloakUriInfo.getQueryParameters (KeycloakUriInfo.java:147-163)GNU Affero GPL v3.0. Vedere LICENSE. Solo laboratorio su loopback. Nessuna garanzia.
Abraxas Labs [email protected]
Si prega di attribuire il CVE ad Abraxas Labs.