Lab Walkthrough - Exploiting Spring4Shell (CVE-2022–22965)
Logo by Daniel Christensen
In our lab walkthrough series, we go through selected lab exercises on our INE Platform. Subscribe or sign up for a 7-day, risk-free trial with INE and access this lab and a robust library covering the latest in Cyber Security, Networking, Cloud, and Data Science!
What is Spring4Shell?
In late March 2022, a severe vulnerability was uncovered in Spring applications running Java 9. It resulted due to a change was committed to Java 9. The vulnerability has been dubbed Spring4Shell and assigned a CVE identifier CVE-2022–22965.
The issue happened due to exposure of a method on the Class object, from Java 9 onwards. This exposure of a new public method to the Class interface added a new way to dynamically trigger the class loader of the JVM. This opens the possibility of performing RCE on the affected Spring applications!
Many public off-the-shelf exploits are available for this vulnerability, adding to the severity of this vulnerability.
In this lab writeup, we will learn how an affected version of Tomcat (using JDK version 9) leads to remote code execution on the remote server, with all but a simple Python-based script.
Read more: National Vulnerability Database, MITRE
Challenge Details
Lab Environment
In this lab environment, the user is going to get access to a Kali GUI instance. A vulnerable app is deployed on http://demo.ine.local. The web app is running Tomcat utilizing the JDK version 9, which is vulnerable to Spring4Shell vulnerability.
Mission
Exploit the Spring4Shell vulnerability to get code execution on the remote server and retrieve the flag!
Technical Difficulty: Proficient
Challenge Link: https://my.ine.com/CyberSecurity/courses/ebd09929/cyber-security-vulnerabilities-training-library/lab/7896c1a8-aae9-40f3-86db-200c617c92ce
Acknowledgements
The base setup code, and the detection and exploitation scripts are taken from the following sources:
Tools
The best tools for this lab are:
dirb
Nmap
Python
A web browser
Solution
Step 1: Open the lab link to access the Kali GUI instance.
Step 2: Check if the provided machine/domain is reachable.
Command:
ping -c3 demo.ine.local
The provided machine is reachable.
Step 3: Check open ports on the provided machine.
Command:
nmap -sS -sV demo.ine.local
Port 80 is open. A website is served on this port (as highlighted in the above image).
Step 4: Locate interesting endpoints/pages in the provided website.
We will be using dirb to look for any interesting pages on the provided website:
Command:
dirb http://demo.ine.local
dirb was able to find two pages:
Note: This step is not that relevant after all, but we have added it to show you a methodology of a pentester, that is, performing recon on the target and gaining valuable insights before jumping onto it and running random exploits against it.
Step 5: Explore the identified web pages.
We know that there is some website being served over port 80. We also discovered two more endpoints using dirb. Let’s see what these pages contain.
Open the following URL in the browser:
A web page is being served over it.
Visit /login endpoint:
URL: http://demo.ine.local/login
The same web page is being served over /login.
Visit /error endpoint:
URL: http://demo.ine.local/error
An error page is being served here. It must be shown after an invalid login.
Step 6: Visit an endpoint to trigger a backend error.
Visit the following URL (/%2f endpoint):
URL: http://demo.ine.local/%2f
Notice that an error was triggered, and we got back a 400 — Bad Request page from the Apache Tomcat server.
The version of Apache Tomcat is indicated on the error page: Apache Tomcat/9.0.59
Step 7: Identify the Java version used by Apache Tomcat version 9.0.59.
For this, we can send the following search request (outside the lab browser, since there is no internet access to the Kali GUI instance):
Search Query:
tomcat/9.0.59 java version
The response indicates that Java version 8 or later must be used by the target server.
Step 8: Detect the presence of Spring4Shell vulnerability.
Spring4Shell vulnerability is applicable for the deployments using JDK version 9 and newer.
The provided target server might be vulnerable, provided that it is running JDK version 9 or newer. To test for that, we will use the following Python script:
Reference: https://cybersecurityworks.com/blog/vulnerabilities/spring4shell-the-next-log4j.html
Save the above script as detect.py.
Check the help message for the script:
Command:
python3 detect.py --help
We will use the — url flag to pass the target URL:
Command:
python3 detect.py --url http://demo.ine.local
The detection script identified the target server deployment to be vulnerable to Spring4Shell.
Step 9: Exploit the Spring4Shell vulnerability.
Now that we have detected the vulnerability, we can exploit it using the following Python script:
Reference: https://github.com/reznok/Spring4Shell-POC/blob/master/exploit.py
Save the above script as exploit.py.
Check the help message for the script:
Command:
python3 exploit.py --help
We will use the — url flag to pass the target URL:
Command:
python3 exploit.py --url http://demo.ine.local
Exploitation was successful, and a JSP webshell was uploaded to the target server.
Step 10: Leverage the uploaded webshell to run OS commands on the target server.
Open the following URL (reported by the exploit.py script):
URL: http://demo.ine.local/shell.jsp?cmd=id
Note: The above URL would run the id command. To run any other command, change the string passed in the cmd parameter.
Notice that the output for the id command is returned.
The target application was running as root, and therefore, the webshell is also running as root (uid = 0)!
We can perform enumeration on the target server and inspect the processes. Change the cmd parameter value and send the following command:
Command:
ps aux
The command was executed successfully!
The output is not well-formed as the newlines are not rendered on the web page. But we can inspect the page source (press CTRL+U) and see the returned output:
Check the current working directory:
Command:
pwd
The current working directory is /usr/local/tomcat/.
Step 11: Retrieve the flag.
Use the following command to locate the flag:
Command:
find / -iname flag*
The flag is present in the file: /root/FLAG.
Retrieve the flag:
Command:
cat /root/FLAG
FLAG: 085a0ee954aa4562916fd8416fd2f3f8
With that, we conclude the exploitation of the target server vulnerable to Spring4Shell.
Technical Details
If you are more curious about vulnerability and how it works, let’s break it down and understand it fully.
How is this vulnerability created?
Spring applications that run on Java 9 and above are susceptible to Spring4Shell. In contrast to the Java 8 (and below) versions, in Java 9, the developers committed a change in the Class object and exposed a method called getModule().
This exposure of a new public method to the Class interface added a new way to dynamically trigger the class loader of the JVM. Prior to Java 9, Spring Framework included proper limitations for triggering the class loader.
One common condition is when a request parameter is bound to a POJO (Plain Old Java Object), and the POJO is not decorated with the @RequestBody annotation. The class variable contains a reference to the POJO object that the HTTP parameters are mapped to. Attackers can specify the class variable in their requests, which enables them to directly access that object. Attackers can also access all child properties of the object through the class variable. And so, by following chains of properties, attackers can access all sorts of other valuable objects on the system.
Why did this issue not happen with old Spring Core installations?
The Spring Core code contains the following logic to prevent accessing child properties of the class variable. This logic is not foolproof:
Snippet:
if (Class.class == beanClass &&
("classLoader".equals(pd.getName()) || "protectionDomain".equals(pd.getName()))) {
continue;
}
The code checks for “class.classLoader” and “class.protectionDomain”, but the logic can be bypassed with the following selector: “class.module.classLoader”
How is the Spring4Shell vulnerability exploited?
The ability to access the class variable and all of its sub-properties opens a big door for attackers to change the behavior of the web application (such as remote code execution).
In Apache Tomcat, an attacker could access an AccessLogValve object from the class variable, by following the class.module.classLoader.resources.context.parent.pipeline.first path. A common way to weaponize this access is to redirect the access log to write a web shell into the webroot by manipulating different properties of the AccessLogValve object, including pattern, suffix, directory, and prefix.
Affected applications
The app runs on Java 9 and above.
The app based on the Spring framework.
The app uses “Spring Parameter Binding” and has been configured to use a non-basic parameter type, such as POJOs (Plain Old Java Object).
References
Conclusion
In this article, we saw how an adversary can leverage an application vulnerable to Spring4Shell to gain code execution on the target server. If the application is running as root, like it was in our lab, the attacker would gain elevated privileges on the server to perform further actions like adding a persistence mechanism or scanning other machines in the local network.
Besides the exploitation, we went down the rabbit hole and learnt about the root cause and the technical details on this vulnerability — how it came into existence and how to identify if an application is affected by Spring4Shell.
References
Try this lab for yourself! Subscribe or sign up for a 7-day, risk-free trial with INE to access this lab and a robust library covering the latest in Cyber Security, Networking, Cloud, and Data Science!