
CVE-2026-23552 - Cross-Realm Token Acceptance in camel-keycloak
KeycloakSecurityPolicy в Apache Camel не проверяет утверждение iss (эмитент) JWT-токенов на соответствие настроенному realm. Это означает, что токен, выданный одним realm Keycloak, молча принимается политикой, настроенной для совершенно другого realm, нарушая изоляцию арендаторов.
Затронутые версии: 4.15.0, 4.16.0, 4.17.0
Отслеживается в: https://issues.apache.org/jira/browse/CAMEL-22854
В KeycloakSecurityHelper.parseAccessToken(), когда открытый ключ явно не указан (что является конфигурацией по умолчанию), токен только декодируется из Base64 -- он никогда не проверяется:
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();
}
}
Поскольку путь выполнения по умолчанию попадает в ветвь else, три вещи остаются непроверенными:
iss никогда не сравнивается с ожидаемым {serverUrl}/realms/{realm}Проверка ролей всё равно проходит, потому что она смотрит только на имена ролей в полезной нагрузке токена. Если имя роли (tenant-user) совпадает между realm -- что часто встречается в мультитенантных конфигурациях, -- запрос пропускается.
В мультитенантном приложении, где каждый арендатор сопоставляется с отдельным realm Keycloak, пользователь арендатора A может получить доступ к маршрутам, защищённым для арендатора B. А именно:
Этот проект демонстрирует уязвимость с использованием Apache Camel 4.17.0 и локального экземпляра Keycloak.
jbang app install camel@apache/camel)camel infra под капотом)Запустите локальный Keycloak:
camel infra run keycloak
Это запускает Keycloak на localhost:8080 с учётными данными администратора admin/admin.
mvn verify
Интеграционный тест (CrossRealmTokenBypassIT) делает следующее:
acme и globextenant-user в обоих realmalice (пароль alice123) в realm acme и назначает ей роль tenant-userdirect:globex-protected), защищённый политикой KeycloakSecurityPolicy, привязанной к realm globexalice из realm acme (эмитент: http://localhost:8080/realms/acme)Запрос успешно выполняется. Токен acme проходит политику globex без каких-либо ошибок.
| Тест | Результат | Значение |
|---|---|---|
В исправленной версии (4.18.0+) второй тест завершился бы ошибкой, а третий -- успешно.
camel infra stop keycloak
Тест также удаляет realm acme и globex в @AfterAll.
KeycloakSecurityPolicy должен отклонять токены, в которых утверждение iss не соответствует {serverUrl}/realms/{realm}. Исправление отслеживается в CAMEL-22854 и будет включено в Camel 4.18.0 (следующий выпуск LTS).
testAcmeTokenIsObtainable| PASS |
| Контрольная проверка -- получение токена работает |
testCrossRealmTokenAccepted | PASS | Подтверждает наличие уязвимости |
testCrossRealmTokenShouldBeRejected | FAIL | Описывает корректное поведение -- в 4.17.0 исключение не выбрасывается |