
CVE-2026-23552 - Accettazione di token cross-realm in camel-keycloak
La KeycloakSecurityPolicy di Apache Camel non valida il claim iss (issuer) dei token JWT rispetto al realm configurato. Ciò significa che un token emesso da un realm Keycloak viene silenziosamente accettato da una policy configurata per un realm completamente diverso, rompendo l'isolamento tra tenant.
Versioni interessate: 4.15.0, 4.16.0, 4.17.0
Tracciato su: https://issues.apache.org/jira/browse/CAMEL-22854
In KeycloakSecurityHelper.parseAccessToken(), quando non viene fornita esplicitamente alcuna chiave pubblica (che è la configurazione predefinita), il token viene solo decodificato da Base64 -- non viene mai verificato:
public static AccessToken parseAccessToken(String tokenString, PublicKey publicKey)
throws VerificationException {
if (publicKey != null) {
return TokenVerifier.create(tokenString, AccessToken.class)
.publicKey(publicKey)
.verify()
.getToken();
} else {
// no signature verification, no issuer check
return TokenVerifier.create(tokenString, AccessToken.class).getToken();
}
}
Poiché il percorso di codice predefinito raggiunge il ramo else, tre cose restano senza controllo:
iss non viene mai confrontato con il valore atteso {serverUrl}/realms/{realm}Il controllo dei ruoli passa comunque perché guarda solo ai nomi dei ruoli all'interno del payload del token. Se il nome del ruolo (tenant-user) corrisponde tra i diversi realm -- cosa comune in configurazioni multi-tenant -- la richiesta viene accettata.
In un'applicazione multi-tenant in cui ogni tenant corrisponde a un realm Keycloak separato, un utente del tenant A può accedere alle route protette per il tenant B. Nello specifico:
Questo progetto dimostra la vulnerabilità usando Apache Camel 4.17.0 e un'istanza Keycloak locale.
jbang app install camel@apache/camel)camel infra internamente)Avvia un Keycloak locale:
camel infra run keycloak
Questo avvia Keycloak su localhost:8080 con credenziali admin admin/admin.
mvn verify
Il test di integrazione (CrossRealmTokenBypassIT) fa quanto segue:
acme e globextenant-user in entrambi i realmalice (password alice123) nel realm acme e le assegna il ruolo tenant-userdirect:globex-protected) protetta da una KeycloakSecurityPolicy legata al realm globexalice dal realm acme (issuer: http://localhost:8080/realms/acme)La richiesta viene accettata. Il token di acme supera la policy di globex senza alcun errore.
| Test | Risultato | Significato |
|---|
Su una versione corretta (4.18.0+), il secondo test fallirebbe e il terzo passerebbe.
camel infra stop keycloak
Il test rimuove anche i realm acme e globex in @AfterAll.
La KeycloakSecurityPolicy dovrebbe rifiutare i token in cui il claim iss non corrisponde a {serverUrl}/realms/{realm}. Il fix è tracciato in CAMEL-22854 e sarà incluso in Camel 4.18.0 (la prossima release LTS).
testAcmeTokenIsObtainable | PASS | Controllo di sanità -- l'acquisizione del token funziona |
testCrossRealmTokenAccepted | PASS | Conferma che la vulnerabilità è presente |
testCrossRealmTokenShouldBeRejected | FAIL | Documenta il comportamento corretto -- su 4.17.0 non viene lanciata alcuna eccezione |