Security

Spring WebFlux Authorization Bypass: CVE-2024-38821 Explained

Spring announced on October 25, 2024, CVE-2024-38821, a critical vulnerability allowing attackers to access restricted resources under certain circumstances. The vulnerability specifically impacts Spring WebFlux's static resource serving. For it to affect an application, all of the following must be true: It must be a WebFlux application. It

5 min read
Spring WebFlux Authorization Bypass: CVE-2024-38821 Explained

Spring announced on October 25, 2024, CVE-2024-38821, a critical vulnerability allowing attackers to access restricted resources under certain circumstances.

The vulnerability specifically impacts Spring WebFlux's static resource serving. For it to affect an application, all of the following must be true:

It must be a WebFlux application.
It must be using Spring’s static resources support.
It must have a non-permitAll authorization rule applied to the static resources support.

In this article, we will delve into the details of this vulnerability and examine why it impacts only static resources.

A PoC can be found at :https://github.com/mouadk/cve-2024-38821/tree/main

The Vulnerability

In this section, we delve into the details of the vulnerability, including some background.

If you don't like reading, here is a figure demonstrating the vulnerability flow.

The WebFilterChainProxy class

Spring security performs most of its core logic using security filters. Usually when we define multiple security filters, and to facilitate the delegation, a filter chain comes on the top and would be responsible to forward responses to next filters.

The DefaultWebFilterChain is actually the default implementation of WebFilterChain. WebFilterChainProxy is a filter used to delegate to a list of SecurityWebFilterChain instances.

WebFilterChainProxy

We can have multiple security filters configured in our application. Only when all the filters accept the request, the request can continue its journey in the application.

The Dispatcher Handler Class

DispatcherHandler is similar to DispatcherServlet in Spring MVC and is responsible for handling http requests. Through its initialisation phase, it will discover special beans to which tasks would be delegated based on the received requests. The handling logic is actually implemented in the DispatcherHandler’s handle method shown below.

This basically happens:

Given an http request (encapsulated in a ServerWebExchange), getHandler is actually responsible for resolving a handler for this request.

AbstractHandlerMapping

When a request arrives, the DispatcherHandler is invoked only if the security filters pass. If the security filter chain allows or fails to deny a request, the DispatcherHandler identifies the appropriate handler (by sequentially evaluating potential matches and choosing the first successful one).

One can leverage a crafted URL path to bypass the security filter, avoiding checks on protected resources. For instance, if you want to secure /index.html, an attacker can manipulate the URL to //index.html. Since the security filter performs strict path matching, it won’t apply in this case, potentially leaving the resource unprotected. If all security filters are bypassed, unrestricted access may result.

Once through the security filters, a specific handler processes the request. A particular handler, the ResourceWebHandler (an HttpRequestHandler), is added by default in Spring to serve static resources like images, HTML, and YAML files from specific locations defined in the ResourceHandlerRegistry, including:

For example, using the path ..//index.html, the request’s path is resolved using exchange.getRequiredAttribute(HandlerMapping.PATH_WITHIN_HANDLER_MAPPING_ATTRIBUTE), which results in index.html. Thus, the attacker could exploit this mechanism.

ResourceWebHandler

Why Non-Static Resources Are Not Affected

Non-static resources behave differently. Handlers for these routes use predicates to validate the requests even if all security filters are bypassed. For example, PathPatternPredicate strictly matches paths and will reject requests that fail this match, resulting in an HTTP 400 NOT FOUND rather than granting unintended access.

RequestPredicates

Attack Flow

The attacker’s path through the application is as follows: DispatcherHandler -> SimpleHandlerAdapter -> ResourceWebHandler -> PathResourceResolver -> Resource -> Attacker Access

This vulnerability was responsibly reported by d4y1ightl@gmail.com.

The Demo

A PoC can be found at :https://github.com/mouadk/cve-2024-38821/tree/main

Let’s configure the following setup to secure access to specific paths, including /secure/hello/index.html, and /application.yaml:

Next, let’s configure the following route:

We can confirm that this configuration works as expected for non-malicious requests.

However, with a slight modification such as adding a backslash (/) an attacker can bypass the filter and gain access to the static resources.

In contrast, accessing dynamic resources (like /secure/hello) with this modification results in a "NOT FOUND" error, as explained earlier.

The Fix

https://github.com/spring-projects/spring-security/commit/4ce7cde15599c0447163fd46bac616e03318bf5b#diff-dd76f194f47c99da94b2808df1bf614d087a8ebbbd1fca1fea9a096ea9bbd176R11

The solution involves enhanced query validation. Specifically, a firewall was introduced in the security chain to validate requests before they reach the filter chain. You can view the commit here (above): GitHub Commit. This update introduces a ServerWebExchangeFirewall (specifically StrictServerWebExchangeFirewall) with additional validation methods.

It’s highly recommended to upgrade your Spring dependency and, moving forward, adopt a “deny by default” approach. Additionally, consider using declarative security, which is more challenging for attackers to bypass, as they often manipulate the security filter chain.

If we retry the previous requests, we get a "Bad Request" error:

This also demonstrates that while RASP can be helpful, it may not catch this vulnerability. As for ADRs, their effectiveness may vary.

BE HARD, BE STRICT (with attackers :) )

Share This Post

Check out these related posts

CVE-2022-21587(Oracle E-Business Suite RCE): Could RASP or ADR Have Prevented It? And How?

Runtime SCA and ADRs: Focusing On What Matters

Profiling Libraries With eBPF: Detecting Zero-Day Exploits and Backdoors