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
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
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.
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.
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.
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.
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:
public/
static/
resources/
META-INF/resources/
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.
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.
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.
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 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 :) )