High severity8.1NVD Advisory· Published Oct 9, 2024· Updated Apr 15, 2026
CVE-2024-3656
CVE-2024-3656
Description
A flaw was found in Keycloak. Certain endpoints in Keycloak's admin REST API allow low-privilege users to access administrative functionalities. This flaw allows users to perform actions reserved for administrators, potentially leading to data breaches or system compromise.
Affected packages
Versions sourced from the GitHub Security Advisory.
| Package | Affected versions | Patched versions |
|---|---|---|
org.keycloak:keycloak-servicesMaven | < 24.0.5 | 24.0.5 |
Patches
1d9f0c84b7975Missing auth checks in some admin endpoints (#166)
5 files changed · +42 −7
federation/ldap/src/main/java/org/keycloak/services/resources/admin/TestLdapConnectionResource.java+1 −2 modified@@ -16,9 +16,7 @@ */ package org.keycloak.services.resources.admin; -import org.jboss.logging.Logger; import org.jboss.resteasy.reactive.NoCache; -import org.keycloak.common.ClientConnection; import org.keycloak.models.KeycloakSession; import org.keycloak.models.LDAPConstants; import org.keycloak.models.RealmModel; @@ -89,6 +87,7 @@ public Response testLDAPConnection(@FormParam("action") String action, @FormPara @NoCache @Consumes(MediaType.APPLICATION_JSON) public Response testLDAPConnection(TestLdapConnectionRepresentation config) { + auth.realm().requireManageRealm(); try { LDAPServerCapabilitiesManager.testLDAP(config, session, realm); return Response.noContent().build();
rest/admin-ui-ext/src/main/java/org/keycloak/admin/ui/rest/UserResource.java+6 −2 modified@@ -17,9 +17,9 @@ import jakarta.ws.rs.core.MediaType; import org.jboss.resteasy.reactive.NoCache; import org.keycloak.models.KeycloakSession; -import org.keycloak.models.RealmModel; import org.keycloak.models.UserModel; import org.keycloak.representations.userprofile.config.UPConfig; +import org.keycloak.services.resources.admin.permissions.AdminPermissionEvaluator; import org.keycloak.userprofile.UserProfile; import org.keycloak.userprofile.UserProfileProvider; import org.keycloak.utils.StringUtil; @@ -30,10 +30,12 @@ public class UserResource { private final KeycloakSession session; + private final AdminPermissionEvaluator auth; private final UserModel user; - public UserResource(KeycloakSession session, UserModel user) { + public UserResource(KeycloakSession session, AdminPermissionEvaluator auth, UserModel user) { this.session = session; + this.auth = auth; this.user = user; } @@ -42,6 +44,8 @@ public UserResource(KeycloakSession session, UserModel user) { @NoCache @Produces(MediaType.APPLICATION_JSON) public Map<String, List<String>> getUnmanagedAttributes() { + auth.users().requireView(user); + UserProfileProvider provider = session.getProvider(UserProfileProvider.class); UserProfile profile = provider.create(USER_API, user);
rest/admin-ui-ext/src/main/java/org/keycloak/admin/ui/rest/UsersResource.java+1 −1 modified@@ -40,6 +40,6 @@ public UserResource getUser(@PathParam("id") String id) { else throw new ForbiddenException(); } - return new UserResource(session, user); + return new UserResource(session, auth, user); } }
services/src/main/java/org/keycloak/services/resources/admin/ClientRegistrationPolicyResource.java+1 −0 modified@@ -74,6 +74,7 @@ public ClientRegistrationPolicyResource(KeycloakSession session, AdminPermission @Tag(name = KeycloakOpenAPI.Admin.Tags.CLIENT_REGISTRATION_POLICY) @Operation( summary="Base path for retrieve providers with the configProperties properly filled") public Stream<ComponentTypeRepresentation> getProviders() { + auth.realm().requireViewRealm(); return session.getKeycloakSessionFactory().getProviderFactoriesStream(ClientRegistrationPolicy.class) .map((ProviderFactory factory) -> { ClientRegistrationPolicyFactory clientRegFactory = (ClientRegistrationPolicyFactory) factory;
testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/PermissionsTest.java+33 −2 modified@@ -24,6 +24,7 @@ import org.junit.Test; import org.keycloak.admin.client.Keycloak; import org.keycloak.admin.client.resource.AuthorizationResource; +import org.keycloak.admin.client.resource.BearerAuthFilter; import org.keycloak.admin.client.resource.RealmResource; import org.keycloak.common.Profile; import org.keycloak.models.AdminRoles; @@ -51,6 +52,7 @@ import org.keycloak.representations.idm.RequiredActionProviderRepresentation; import org.keycloak.representations.idm.RequiredActionProviderSimpleRepresentation; import org.keycloak.representations.idm.RoleRepresentation; +import org.keycloak.representations.idm.TestLdapConnectionRepresentation; import org.keycloak.representations.idm.UserRepresentation; import org.keycloak.representations.idm.authorization.PolicyRepresentation; import org.keycloak.representations.idm.authorization.ResourcePermissionRepresentation; @@ -73,6 +75,8 @@ import org.keycloak.userprofile.DeclarativeUserProfileProvider; import jakarta.ws.rs.ClientErrorException; +import jakarta.ws.rs.client.Client; +import jakarta.ws.rs.core.MediaType; import jakarta.ws.rs.core.Response; import java.lang.reflect.Method; import java.util.Arrays; @@ -375,7 +379,11 @@ public void invoke(RealmResource realm) { invoke(new InvocationWithResponse() { public void invoke(RealmResource realm, AtomicReference<Response> response) { - response.set(realm.testLDAPConnection("nosuch", "nosuch", "nosuch", "nosuch", "nosuch", "nosuch")); + TestLdapConnectionRepresentation config = new TestLdapConnectionRepresentation( + "nosuch", "nosuch", "nosuch", "nosuch", "nosuch", "nosuch"); + response.set(realm.testLDAPConnection(config.getAction(), config.getConnectionUrl(), config.getBindDn(), + config.getBindCredential(), config.getUseTruststoreSpi(), config.getConnectionTimeout())); + response.set(realm.testLDAPConnection(config)); } }, Resource.REALM, true); @@ -1458,6 +1466,21 @@ public void invoke(RealmResource realm) { realm.users().get(user.getId()).toRepresentation(); } }, Resource.USER, false); + invoke(new InvocationWithResponse() { + public void invoke(RealmResource realm, AtomicReference<Response> response) { + // no-op + } + public void invoke(Keycloak keycloak, RealmResource realm, AtomicReference<Response> response) { + try (Client client = Keycloak.getClientProvider().newRestEasyClient(null, null, true)) { + Response resp = client.target(suiteContext.getAuthServerInfo().getContextRoot().toString() + "/auth") + .path("/admin/realms/" + realm.toRepresentation().getRealm() + "/ui-ext/users/" + user.getId() + "/unmanagedAttributes") + .register(new BearerAuthFilter(keycloak.tokenManager())) + .request(MediaType.APPLICATION_JSON) + .get(); + response.set(resp); + } + } + }, Resource.USER, false); invoke(new Invocation() { public void invoke(RealmResource realm) { realm.users().get(user.getId()).update(user); @@ -1757,6 +1780,11 @@ public void invoke(RealmResource realm) { realm.components().query("nosuch"); } }, Resource.REALM, false); + invoke(new Invocation() { + public void invoke(RealmResource realm) { + realm.clientRegistrationPolicy().getProviders(); + } + }, Resource.REALM, false); invoke(new InvocationWithResponse() { public void invoke(RealmResource realm, AtomicReference<Response> response) { response.set(realm.components().add(new ComponentRepresentation())); @@ -1945,7 +1973,7 @@ private void invoke(InvocationWithResponse invocation, Keycloak client, boolean int statusCode; try { AtomicReference<Response> responseReference = new AtomicReference<>(); - invocation.invoke(client.realm(REALM_NAME), responseReference); + invocation.invoke(client, client.realm(REALM_NAME), responseReference); Response response = responseReference.get(); if (response != null) { statusCode = response.getStatus(); @@ -2054,6 +2082,9 @@ public interface InvocationWithResponse { void invoke(RealmResource realm, AtomicReference<Response> response); + default void invoke(Keycloak keycloak, RealmResource realm, AtomicReference<Response> response) { + invoke(realm, response); + } } private void assertGettersEmpty(RealmRepresentation rep) {
Vulnerability mechanics
Generated by null/stub on May 9, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.
References
12- github.com/advisories/GHSA-2cww-fgmg-4jqcnvdADVISORY
- nvd.nist.gov/vuln/detail/CVE-2024-3656ghsaADVISORY
- access.redhat.com/errata/RHSA-2024:3572nvdWEB
- access.redhat.com/errata/RHSA-2024:3575nvdWEB
- access.redhat.com/security/cve/CVE-2024-3656nvdWEB
- bugzilla.redhat.com/show_bug.cginvdWEB
- github.com/hnsecurity/vulns/blob/main/HNS-2024-08-Keycloak.mdnvdWEB
- github.com/keycloak/keycloak/commit/d9f0c84b797525eac55914db5f81a8133ef5f9b1ghsaWEB
- github.com/keycloak/keycloak/security/advisories/GHSA-2cww-fgmg-4jqcghsaWEB
- news.ycombinator.com/itemnvdWEB
- security.humanativaspa.it/an-analysis-of-the-keycloak-authentication-systemghsaWEB
- security.humanativaspa.it/an-analysis-of-the-keycloak-authentication-system/nvd
News mentions
0No linked articles in our index yet.