
CVE-2026-23552 - Aceitação de Token Entre Reinos no camel-keycloak
O KeycloakSecurityPolicy do Apache Camel não valida a declaração iss (emissor) dos tokens JWT em relação ao realm configurado. Isso significa que um token emitido por um realm do Keycloak é silenciosamente aceito por uma política configurada para um realm totalmente diferente, quebrando o isolamento entre tenants.
Versões afetadas: 4.15.0, 4.16.0, 4.17.0
Rastreado em: https://issues.apache.org/jira/browse/CAMEL-22854
Em KeycloakSecurityHelper.parseAccessToken(), quando nenhuma chave pública é fornecida explicitamente (que é a configuração padrão), o token é apenas decodificado do Base64 -- nunca é verificado:
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();
}
}
Como o caminho de código padrão atinge o ramo else, três coisas não são verificadas:
iss nunca é comparada com a esperada {serverUrl}/realms/{realm}A verificação de papel (role) ainda passa porque ela apenas analisa os nomes de papéis dentro do payload do token. Se o nome do papel (tenant-user) coincidir entre os realms -- o que é comum em configurações multi-tenant -- a solicitação passa.
Em uma aplicação multi-tenant onde cada tenant mapeia para um realm separado no Keycloak, um usuário do tenant A pode acessar rotas protegidas para o tenant B. Concretamente:
Este projeto demonstra a vulnerabilidade usando Apache Camel 4.17.0 e uma instância local do Keycloak.
jbang app install camel@apache/camel)camel infra)Inicie um Keycloak local:
camel infra run keycloak
Isso inicia o Keycloak em localhost:8080 com credenciais de administrador admin/admin.
mvn verify
O teste de integração (CrossRealmTokenBypassIT) faz o seguinte:
acme e globextenant-user em ambos os realmsalice (senha alice123) no realm acme e atribui a ela o papel tenant-userdirect:globex-protected) protegida por um KeycloakSecurityPolicy vinculado ao realm globexalice do realm acme (emissor: http://localhost:8080/realms/acme)A requisição é bem-sucedida. O token do acme passa pela política do globex sem nenhum erro.
| Test | Result | Meaning |
|---|---|---|
testAcmeTokenIsObtainable | PASS | Verificação de sanidade -- a obtenção do token funciona |
testCrossRealmTokenAccepted | PASS | Confirma que a vulnerabilidade está presente |
testCrossRealmTokenShouldBeRejected | FAIL | Documenta o comportamento correto -- no 4.17.0 nenhuma exceção é lançada |
Em uma versão corrigida (4.18.0+), o segundo teste falharia e o terceiro passaria.
camel infra stop keycloak
O teste também remove os realms acme e globex no @AfterAll.
O KeycloakSecurityPolicy deve rejeitar tokens em que a declaração iss não corresponda a {serverUrl}/realms/{realm}. A correção é rastreada em CAMEL-22854 e será lançada com o Camel 4.18.0 (a próxima versão LTS).