[keycloak-user] Possible LDAP injection issue found - '(' character in user name is not escaped before LDAP query (as found by OWASP ZAP security tool)

Edgar Vonk - Info.nl Edgar at info.nl
Wed Oct 5 10:37:16 EDT 2016


Hi,

We are using the OWASP ZAP tool (https://www.owasp.org/index.php/OWASP_Zed_Attack_Proxy_Project) to run basic security testing against our web portal of which Keycloak is a key part. When ZAP runs the Keycloak log fills up quickly with all kinds of stack traces. One of them is the one below.

In this case the ZAP tool attempts to login on the Keycloak login page securing our custom realm with the following username:

ZAP') UNION ALL select NULL --


It seems from the stacktrace below that Keycloak uses this ‘username’ as is without any escaping when querying LDAP(/AD) This results in an incorrect LDAP query because the parenthesis are now ‘unbalanced’. I think all special characters in a username should be escaped before the LDAP query is done? It seems that this is a case of LDAP Injection (https://www.owasp.org/index.php/LDAP_injection)


14:06:37,437 ERROR [org.keycloak.federation.ldap.idm.store.ldap.LDAPOperationManager] (default task-21) Could not query server using DN [ou=Users,ou=Customers,dc=graydon-test,dc=hf,dc=info,dc=nl] and filter [(&(userPrincipalname=ZAP') UNION ALL select NULL -- )(objectclass=person)(objectclass=organizationalPerson)(objectclass=user)(objectclass=graydonCustomerPerson))]: javax.naming.directory.InvalidSearchFilterException: Unbalanced parenthesis; remaining name 'ou=Users,ou=Customers,dc=graydon-test,dc=hf,dc=info,dc=nl'
at com.sun.jndi.ldap.Filter.findRightParen(Filter.java:694)
at com.sun.jndi.ldap.Filter.encodeFilterList(Filter.java:733)
at com.sun.jndi.ldap.Filter.encodeComplexFilter(Filter.java:657)
at com.sun.jndi.ldap.Filter.encodeFilter(Filter.java:104)
at com.sun.jndi.ldap.Filter.encodeFilterString(Filter.java:74)
at com.sun.jndi.ldap.LdapClient.search(LdapClient.java:546)
at com.sun.jndi.ldap.LdapCtx.doSearch(LdapCtx.java:1985)
at com.sun.jndi.ldap.LdapCtx.searchAux(LdapCtx.java:1844)
at com.sun.jndi.ldap.LdapCtx.c_search(LdapCtx.java:1769)
at com.sun.jndi.toolkit.ctx.ComponentDirContext.p_search(ComponentDirContext.java:392)
at com.sun.jndi.toolkit.ctx.PartialCompositeDirContext.search(PartialCompositeDirContext.java:358)
at com.sun.jndi.toolkit.ctx.PartialCompositeDirContext.search(PartialCompositeDirContext.java:341)
at javax.naming.directory.InitialDirContext.search(InitialDirContext.java:267)
at javax.naming.directory.InitialDirContext.search(InitialDirContext.java:267)
at org.keycloak.federation.ldap.idm.store.ldap.LDAPOperationManager$2.execute(LDAPOperationManager.java:169)
at org.keycloak.federation.ldap.idm.store.ldap.LDAPOperationManager$2.execute(LDAPOperationManager.java:166)
at org.keycloak.federation.ldap.idm.store.ldap.LDAPOperationManager.execute(LDAPOperationManager.java:536)
at org.keycloak.federation.ldap.idm.store.ldap.LDAPOperationManager.search(LDAPOperationManager.java:166)
at org.keycloak.federation.ldap.idm.store.ldap.LDAPIdentityStore.fetchQueryResults(LDAPIdentityStore.java:160)
at org.keycloak.federation.ldap.idm.query.internal.LDAPQuery.getResultList(LDAPQuery.java:165)
at org.keycloak.federation.ldap.idm.query.internal.LDAPQuery.getFirstResult(LDAPQuery.java:176)
at org.keycloak.federation.ldap.LDAPFederationProvider.loadLDAPUserByUsername(LDAPFederationProvider.java:510)
at org.keycloak.federation.ldap.LDAPFederationProvider.getUserByUsername(LDAPFederationProvider.java:305)
at org.keycloak.models.UserFederationManager.getUserByUsername(UserFederationManager.java:237)
at org.keycloak.models.utils.KeycloakModelUtils.findUserByNameOrEmail(KeycloakModelUtils.java:273)
at org.keycloak.authentication.authenticators.browser.AbstractUsernameFormAuthenticator.validateUserAndPassword(AbstractUsernameFormAuthenticator.java:127)
at org.keycloak.authentication.authenticators.browser.UsernamePasswordForm.validateForm(UsernamePasswordForm.java:56)
at org.keycloak.authentication.authenticators.browser.UsernamePasswordForm.action(UsernamePasswordForm.java:49)
at org.keycloak.authentication.DefaultAuthenticationFlow.processAction(DefaultAuthenticationFlow.java:84)
at org.keycloak.authentication.DefaultAuthenticationFlow.processAction(DefaultAuthenticationFlow.java:75)
at org.keycloak.authentication.AuthenticationProcessor.authenticationAction(AuthenticationProcessor.java:759)
at org.keycloak.services.resources.LoginActionsService.processFlow(LoginActionsService.java:356)
at org.keycloak.services.resources.LoginActionsService.processAuthentication(LoginActionsService.java:338)
at org.keycloak.services.resources.LoginActionsService.authenticateForm(LoginActionsService.java:383)
at sun.reflect.GeneratedMethodAccessor480.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.jboss.resteasy.core.MethodInjectorImpl.invoke(MethodInjectorImpl.java:139)
at org.jboss.resteasy.core.ResourceMethodInvoker.invokeOnTarget(ResourceMethodInvoker.java:295)
at org.jboss.resteasy.core.ResourceMethodInvoker.invoke(ResourceMethodInvoker.java:249)
at org.jboss.resteasy.core.ResourceLocatorInvoker.invokeOnTargetObject(ResourceLocatorInvoker.java:138)
at org.jboss.resteasy.core.ResourceLocatorInvoker.invoke(ResourceLocatorInvoker.java:101)
at org.jboss.resteasy.core.SynchronousDispatcher.invoke(SynchronousDispatcher.java:395)
at org.jboss.resteasy.core.SynchronousDispatcher.invoke(SynchronousDispatcher.java:202)
at org.jboss.resteasy.plugins.server.servlet.ServletContainerDispatcher.service(ServletContainerDispatcher.java:221)
at org.jboss.resteasy.plugins.server.servlet.HttpServletDispatcher.service(HttpServletDispatcher.java:56)
at org.jboss.resteasy.plugins.server.servlet.HttpServletDispatcher.service(HttpServletDispatcher.java:51)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:790)
at io.undertow.servlet.handlers.ServletHandler.handleRequest(ServletHandler.java:85)
at io.undertow.servlet.handlers.FilterHandler$FilterChainImpl.doFilter(FilterHandler.java:129)
at org.keycloak.services.filters.KeycloakSessionServletFilter.doFilter(KeycloakSessionServletFilter.java:90)
at io.undertow.servlet.core.ManagedFilter.doFilter(ManagedFilter.java:60)
at io.undertow.servlet.handlers.FilterHandler$FilterChainImpl.doFilter(FilterHandler.java:131)
at io.undertow.servlet.handlers.FilterHandler.handleRequest(FilterHandler.java:84)
at io.undertow.servlet.handlers.security.ServletSecurityRoleHandler.handleRequest(ServletSecurityRoleHandler.java:62)
at io.undertow.servlet.handlers.ServletDispatchingHandler.handleRequest(ServletDispatchingHandler.java:36)
at org.wildfly.extension.undertow.security.SecurityContextAssociationHandler.handleRequest(SecurityContextAssociationHandler.java:78)
at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43)
at io.undertow.servlet.handlers.security.SSLInformationAssociationHandler.handleRequest(SSLInformationAssociationHandler.java:131)
at io.undertow.servlet.handlers.security.ServletAuthenticationCallHandler.handleRequest(ServletAuthenticationCallHandler.java:57)
at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43)
at io.undertow.security.handlers.AbstractConfidentialityHandler.handleRequest(AbstractConfidentialityHandler.java:46)
at io.undertow.servlet.handlers.security.ServletConfidentialityConstraintHandler.handleRequest(ServletConfidentialityConstraintHandler.java:64)
at io.undertow.security.handlers.AuthenticationMechanismsHandler.handleRequest(AuthenticationMechanismsHandler.java:60)
at io.undertow.servlet.handlers.security.CachedAuthenticatedSessionHandler.handleRequest(CachedAuthenticatedSessionHandler.java:77)
at io.undertow.security.handlers.NotificationReceiverHandler.handleRequest(NotificationReceiverHandler.java:50)
at io.undertow.security.handlers.AbstractSecurityContextAssociationHandler.handleRequest(AbstractSecurityContextAssociationHandler.java:43)
at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43)
at org.wildfly.extension.undertow.security.jacc.JACCContextIdHandler.handleRequest(JACCContextIdHandler.java:61)
at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43)
at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43)
at io.undertow.servlet.handlers.ServletInitialHandler.handleFirstRequest(ServletInitialHandler.java:284)
at io.undertow.servlet.handlers.ServletInitialHandler.dispatchRequest(ServletInitialHandler.java:263)
at io.undertow.servlet.handlers.ServletInitialHandler.access$000(ServletInitialHandler.java:81)
at io.undertow.servlet.handlers.ServletInitialHandler$1.handleRequest(ServletInitialHandler.java:174)
at io.undertow.server.Connectors.executeRootHandler(Connectors.java:202)
at io.undertow.server.HttpServerExchange$1.run(HttpServerExchange.java:793)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
at java.lang.Thread.run(Thread.java:745)

14:06:37,439 WARN  [org.keycloak.events] (default task-21) type=LOGIN_ERROR, realmId=graydon-customers, clientId=account, userId=null, ipAddress=172.23.6.21, error=invalid_user_credentials, auth_method=openid-connect, auth_type=code, redirect_uri=https://gry-test.hf.info.nl/auth/realms/graydon-customers/account/login-redirect, code_id=7ee2f340-5bf8-42a2-b1ef-32890a78c305, username='ZAP') UNION ALL select NULL -- '




More information about the keycloak-user mailing list