
CVE-2026-23552 - Aceptación de tokens entre reinos en camel-keycloak
La KeycloakSecurityPolicy de Apache Camel no valida la reclamación iss (emisor) de los tokens JWT contra el reino configurado. Esto significa que un token emitido por un reino de Keycloak es aceptado silenciosamente por una política configurada para un reino completamente diferente, rompiendo el aislamiento entre inquilinos.
Versiones afectadas: 4.15.0, 4.16.0, 4.17.0
Seguimiento en: https://issues.apache.org/jira/browse/CAMEL-22854
En KeycloakSecurityHelper.parseAccessToken(), cuando no se proporciona explícitamente una clave pública (que es la configuración predeterminada), el token solo se decodifica desde Base64 -- nunca se verifica:
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();
}
}
Dado que la ruta de código predeterminada llega a la rama else, tres cosas quedan sin comprobar:
iss nunca se compara con el esperado {serverUrl}/realms/{realm}La comprobación de roles sigue pasando porque solo examina los nombres de los roles dentro del payload del token. Si el nombre del rol (tenant-user) coincide entre reinos -- lo cual es común en configuraciones multiinquilino -- la solicitud pasa.
En una aplicación multiinquilino donde cada inquilino se asigna a un reino de Keycloak separado, un usuario del inquilino A puede acceder a rutas protegidas para el inquilino B. Concretamente:
Este proyecto demuestra la vulnerabilidad usando Apache Camel 4.17.0 y una instancia local de Keycloak.
jbang app install camel@apache/camel)camel infra internamente)Inicie un Keycloak local:
camel infra run keycloak
Esto inicia Keycloak en localhost:8080 con las credenciales de administrador admin/admin.
mvn verify
La prueba de integración (CrossRealmTokenBypassIT) hace lo siguiente:
acme y globextenant-user en ambos reinosalice (contraseña alice123) en el reino acme y le asigna el rol tenant-userdirect:globex-protected) protegida por una KeycloakSecurityPolicy vinculada al reino globexalice del reino acme (emisor: http://localhost:8080/realms/acme)La solicitud tiene éxito. El token de acme pasa la política de globex sin ningún error.
| Test | Resultado | Significado |
|---|
En una versión parcheada (4.18.0+), la segunda prueba fallaría y la tercera pasaría.
camel infra stop keycloak
La prueba también elimina los reinos acme y globex en @AfterAll.
La KeycloakSecurityPolicy debería rechazar los tokens donde la reclamación iss no coincida con {serverUrl}/realms/{realm}. La corrección está registrada en CAMEL-22854 y se incluirá con Camel 4.18.0 (la próxima versión LTS).
testAcmeTokenIsObtainable | PASS | Comprobación de cordura -- la obtención del token funciona |
testCrossRealmTokenAccepted | PASS | Confirma que la vulnerabilidad está presente |
testCrossRealmTokenShouldBeRejected | FAIL | Documenta el comportamiento correcto -- en 4.17.0 no se lanza ninguna excepción |