FortiGuard Labs Threat Research
A Uniform Resource Locator (URL), colloquially termed a web address, comprises five components: scheme, authority, path, query, and fragment. Each element is shown in this example: http://host-authority/path/?query-param=1#fragment
In the web application world, an URL path is always used to map a web request to a designated web service on the backend. As a security precaution, a web application typically has a path filter mechanism to prevent an unauthorized user from exploiting an unintended functionality via URL.
The Java web framework is one of the most widely deployed web services on the Internet. Based on our experience, many web servlets also rely on path filters to prevent unintended service access. (A servlet is a Java programming language class that extends the capabilities of servers that host applications that are accessed using a request-response programming model.) Because of this, we decided to perform a code audit on some popular Java open source projects. During our assessment, we found some interesting bypass vulnerabilities on two open source projects, Apache Shiro and dotCMS. These vulnerabilities have been designated as CVE-2021-41303 and CVE-2022-35740:
In the next section, we will walk through the path filter bypass methods we discovered.
Apache Shiro™ is a powerful and easy-to-use Java security framework that performs authentication, authorization, cryptography, and session management.
There are two ways to use Apache Shiro: SSH and Web (when integrated into a web framework, like Spring and Spring Boot). In this article, we will talk about an authentication bypass vulnerability for Apache Shiro when using Spring Boot.
In the following demo, we create a Spring Boot application with Apache Shiro that protects the /admin/ path to prevent unauthorized user access.
When we try to access the “/admin/” path endpoint, we are redirected to the “/login” page. This is working as expected since we are unauthorized.
However, the vulnerability exists due to the difference in how Apache Shiro and Spring Boot parse the URL Path. To verify this, we analyzed how a normal request to “/admin/aaa” is parsed.
When accessing the path in Figure 4, the pathMatches method in Apache Shiro will be called. In Figures 5 and 6, we can see that it compares the pattern “/admin/*” with our input path “/admin/aaa” and returns true.
Since it matches the admin route, but we are currently unauthorized, we are redirected to the login page. So far, this is all normal behavior.
Now we will look at what happens when the malformed bypass request “/admin/%2e%2e” is sent.
The pathMatches function is called, but this time it treats our input path as “/”, not “/admin/%2e%2e”
This is because when Apache Shiro tries to decode this URL path, it translates to “/admin/..” and hence goes back to the root directory. This bypasses the authentication check, as Apache Shiro treats it as equivalent to “/” (which is supposed to be publicly accessed). Apache Shiro then forwards the request to Spring Boot for processing.
However, this same input is treated differently in Spring Boot Path Mapping. In this case, it sees this as an endpoint under “/admin/” and serves up the protected content to the attacker, as seen in Figure 11.
Due to the difference in parsing between Apache Shiro and Spring Boot, we managed to successfully bypass the authentication mechanism of Apache Shiro.
dotCMS is an Open Source Hybrid CMS (content management system) built on Java. While assessing dotCMS, we found several CORS Attack, Cross-Site Request Forgery, and Cross-Site Scripting issues that could lead to critical threats if users with admin privilege access them.
However, we also realized that these issues might not be exploitable since dotCMS has XSS Prevention enabled globally by default on all their administrative endpoints.
A quick look at the documentation shows that dotCMS blocks direct access to all files under the administrative directories (e.g.,/html, /dotAdmin, etc.) unless a request is sent with a valid Referer or Origin header.
To verify this, we tried to access one of the endpoints with an XSS payload.
The application redirects the user back to /dotAdmin/ due to the absence of a Referer or Origin header.
To better understand how the path filter mechanism works in dotCMS, we decided to dive into the code to see if there is a way to bypass it.
Looking at the dotCMS version 22.05 source code, in com/dotcms/filters/interceptor/dotcms/XSSPreventionWebInterceptor.java from line 28, we find that it defines which paths are protected by default.
Any incoming request that matches the protected path will be intercepted and passed to securityUtils.validateReferer() in com/dotcms/util/SecurityUtils.java.
Basically, this method checks whether:
If true, the request will proceed. Otherwise, it sets the status to 401 Unauthorized to the response or redirects to an exception page.
Instead of attempting to bypass the Origin/Referer header, we thought of an easier approach. Why not perform a bypass on PATH instead? In this case, if the path doesn’t match the Protected Path, we no longer need to deal with the validation.
With that idea in mind, we found the bypass using matrix parameters, which are an alternative to query parameters but more flexible and can be accepted anywhere in the path.
For example, given a query parameter of:
We can transform it into a matrix parameter with the same meaning:
Knowing this, we can transform our intended payload into a matrix parameter, effectively bypassing the whitelist.
As seen in Figure 16, the request successfully bypassed the XSS protection, and the unsanitized XSS payload is reflected in the output.
In conclusion, path filter mechanisms can go wrong easily, and it takes significant effort to implement a comprehensive filter mechanism. In addition to the two examples we presented here, we have seen numerous examples provided by other researchers on how a path filter can be trivially escaped.
However, another important lesson learned is that when developers create a product that is being integrated into or relies on another framework, they should make sure they fully understand the nature of the framework. This will help ensure they do not inadvertently introduce a vulnerability like the one we described on Apache Shiro.
FortiGuard Labs released the following IPS signatures, which cover all the vulnerabilities mentioned:
Users are also strongly urged to apply the latest patched from the vendors:
Apache Shiro: https://shiro.apache.org/download.html
NOTE: If you are interested in this kind of assessment for your software or application, FortiGuard Labs provides a tailor-made vulnerability assessment and penetration testing service that can help you improve the security of your products. Visit us here for more information.
Learn more about Fortinet’s FortiGuard Labs threat research and global intelligence organization and Fortinet’s FortiGuard AI-powered Security Services portfolio. Sign up to receive our threat research blogs.