SpringShell is a new vulnerability in Spring, the world’s most popular Java framework, which enables remote code execution (RCE) using ClassLoader access to manipulate attributes and setters. This issue was unfortunately leaked online without responsible disclosure before an official patch was available. This vulnerability has been assigned CVE-2022-22965.
At present, known exploitation of this vulnerability requires a combination of Spring, Java version 9 and up, and Tomcat; however, this is likely to change, due to the fact this exposure occurs in Spring and allows access to various sensitive components. It is therefore safest to assume all Spring Web instances are likely to be vulnerable.
Note that currently there is another critical RCE vulnerability making headlines around Spring Cloud, which involves a similar exploitation technique of accessing functions. This article does not cover that issue.
Technology Breakdown
The current focus at large is on the known exploitation of Spring, Java version 9 and up, and Tomcat.
Spring allows rapid and lightweight development for Java applications, particularly for web applications. Tomcat is a very popular webserver for Java applications, and is also embedded into Spring Boot. This means the combination of Spring and Tomcat is almost ubiquitous, making this vulnerability extremely common. Java 9 has been around for 5 years and is also a requirement for this issue.
Another requirement for the specific exploit is accepting POST requests with POJOs to trigger binding; there are very few Spring web-applications that do not.
Am I Vulnerable?
If you are using Spring Web which is exposed to the internet running on Java 9 and later – you are most likely exposed to this vulnerability. Current exploits available in the wild require a combination of Spring and Tomcat, but Tomcat is merely an instrument in a gadget used to trigger this RCE; more gadgets may be found as exposed by this vulnerability.
How Does It Work?
The best way to explain how this vulnerability is exploitable is by breaking down the available exploit. However – note that while this exploit affects a particular configuration of Spring, Tomcat, and Java – not having this particular configuration does not imply you are safe from exploitation, only from this particular variant.
The current RCE PoC exploit involves the following steps:
- Finding a POST endpoint in the Spring application
- Submitting a request to reconfigure Tomcat to output a log to an arbitrary JSP file in an accessible location which serves JSP files on the Tomcat server
- Triggering a write to this log of user-provided values, to create a JSP file with malicious code
- Execute the JSP file by requesting it via HTTP, as per standard JSP behavior
Let’s break it down.
ClassLoader Manipulation
It is possible to access ClassLoader variables via POST parameters prefixed by class.module.classLoader.* in Spring, due to parameter binding. Years ago, Spring allowed access to ClassLoader directly in this manner which led to other exploits (e.g., CVE-2010–1622). This access then made a deny-list for specific parameters as mitigation. However, starting with Java 9 — Modules were added which allowed reaching ClassLoader via class.getModule().getClassLoader(), which is precisely why the deny-list approach to accessing ClassLoader in the past could be bypassed by class.module.classLoader.
This manipulation exposes internal objects to user-provided values, and is the core of this vulnerability.
Tomcat Context Reconfiguration
Using this ClassLoader manipulation on a Tomcat web server, it is possible for attackers to directly access the Tomcat context, which in itself contains Tomcat configurations.
In this exploit, Tomcat is reconfigured to write logs to a new file on an attacker’s behest. This file, instead of just being a log file, will also double as an executable JSP file.
The following attributes are edited to write the arbitrary log file:
- class.module.classLoader.resources.context.parent.pipeline.first.directory — the path to which the log file is written. In standard Tomcat dev environments, webapps/ROOT will expose a root folder for the webserver itself; however, in more custom prod environments an attacker may need to figure out where exactly malicious JSP files can be written to be remotely accessible
- class.module.classLoader.resources.context.parent.pipeline.first.prefix — will determine the log file name
- class.module.classLoader.resources.context.parent.pipeline.first.suffix — will determine the log file extension — for the purpose of exploitation this will be an executable servlet type such as JSP, but attackers can come up with various other potentially executable file types
- class.module.classLoader.resources.context.parent.pipeline.first.pattern — this is the pattern that will be written to the log file; attackers will write malicious code instead of a pattern, such that on a logging event their malicious code will be written into the file
- class.module.classLoader.resources.context.parent.pipeline.first.fileDateFormat — this is the date format, which is purposefully left blank to remove the noisy timestamps from the output of the exploit
Arbitrary File Write of a Malicious JSP File
For example, the following POST request can be sent:
This will override the log configurations to create a JSP servlet at the Tomcat’s web application root (“/”), allowing attackers to execute the malicious code in “pattern” by simply browsing to /ohno.jsp
Mitigation & Conclusions
According to an update on the official Spring website, this issue is mitigated in Spring Framework versions 5.3.18 and 5.2.20. This article also contains a vendor-recommended workaround for those who cannot update at present.
From the looks of things and how analysis of this issue currently pans out — this vulnerability illustrates how the changes made to Java have incidentally made the Spring deny-list obsolete, in a way that has evaded detection for a significant amount of time. This highlights the ever-present issue of denying dangerous functionalities, rather than explicitly allowing safe ones, which is a behavior often prevalent in frameworks that offer a lot of dynamic and complex features.
Checkmarx SCA customers can scan their code for similar types of vulnerabilities and get the latest remediation guidance.