Natas Level 11 – XOR “Encryption”

In this post we’re going to take a look at Level 11 of the Natas wargame, hosted by Over The Wire.

What’s Going On?

Upon logging in, we see a message that states that cookies are encrypted with XOR encryption.  Additionally, there is a text input, submit button, and a link to the PHP source code of the page.  Looking at the prompt on the page, it sounds like if we input a valid RGB color code, the background of the page will change.  We can test this with a different code, such as #000000 and see that it works.  Now, let’s go a head at look at the PHP source code by following the link.

Looking through the code, we see quite a bit of PHP and some HTML.  Additionally, in the HTML section, we see a snippet of PHP which will display the password to the next level if the “showpassword” key of an array called “data” is set to “yes”.  Thus, this will be our final target, to set the showpassword key of the data array to yes.  So, let’s track back through the PHP code to see where this array comes from.

The last line of the PHP code section is saveData($data); so let’s look at the saveData function, which is defined a few lines above.  The saveData function seems to set a cookie called “data” with the value which is the result of calling json_encode(), xor_encrypt(), and base64_encode() in order on the argument passed to saveData.  Between these two sections of code, we also see that $data is set to the return value of loadData($defaultData);  At the top of the code section, we can see that $defaultData is an array with two keys set, “showpassword”=>”no” and “bgcolor”=>”#ffffff”.  Thus, if we can craft a fake array with “showpassword”=>”yes”, encrypt it in the same way as was done in the saveData function, and put that value into our cookie, we should be able to get the password for the next level!  However, let’s take a closer look at those encoding functions.

A couple of the functions are basic two way functions, json_encode() and base64_encode() both have opposite direction functions within the normal PHP API.  However, xor_encrypt() deserves a little more attention.  XOR encryption is a fast bit based encryption scheme which requires a SECRET KEY.  Plain text is XOR’d with the key, and a cipher text is output.  It also has a reverse operation which is the exact same operation, cipher text XOR’d with the key gives the plain text.  This is an attempt to make it so we cannot forge a cookie value, since we cannot encode with the same key by which the cookie will be decoded with, since we don’t know the key.  However, by XOR’s nature, it is vulnerable to a known plain text attack.  This is because the plain text XOR’d with the cipher text results in the key.  So, let’s see how we can take advantage of XOR’s weakness to recover the key, and thus forge our own cookie!

Exploit

The first thing we need to do, to be able to determine the key, is determine the plain and cipher text which were used and produced during the run.  We know the plain text was the result of running json_encode(array(“showpassword”=>”no”, “bgcolor”=”#ffffff”)), and that the result, the cipher text, was run through base64_encode and saved to a cookie.  So, let’s look up our cookie called data set by the natas11 site and find it’s value.  We can then put that value through base64_decode() to get what was the cipher text of the original XOR’d data.  Once we have recovered these two, we can go a head and use one as the key and one as the plaintext, and run them through the xor_encrypt function to get the original key that was used.  Let’s look at a re-arranged PHP file based off the code of this level, which will recover the key:

<?

$cryptData = base64_decode(“ClVLIh4ASCsCBE8lAxMacFMZV2hdVVotEhhUJQNVAmhSEV4sFxFeaAw%3D”); //default cookie value

function xor_encrypt($in) {
$key = json_encode(array( “showpassword”=>”no”, “bgcolor”=>”#ffffff”));
$text = $in;
$outText = ”;

// Iterate through each character
for($i=0;$i<strlen($text);$i++) {
$outText .= $text[$i] ^ $key[$i % strlen($key)];
}

return $outText;
}

print xor_encrypt($cryptData);

?>

The above code does just what was mentioned.  It takes the base64_decode() results of the data cookie’s value, and passes it as plain text to the xor_encrypt() function.  The xor_encrypt() function uses the json_encode() results on the default array value.  After xor_encrypt is run, the results are printed to the screen as shown:

[somebox]$ php recoverKey.php
qw8Jqw8Jqw8Jqw8Jqw8Jqw8Jqw8Jqw8Jqw8Jqw8JqL

We can see it’s a repeated 4 character key.  Since XOR encryption uses modulus to wrap around the key, we can shorten it to just the original 4 characters, qw8J, or any number of full repetitions.  Notice the random “L” at the end, let’s replace it with what should be there, a “w”.

Next, we need a program which will create a fake, crafted array with the showpassword key set to yes, and fully encode it with json, XOR, and base64, and output it for use as our cookie value.  Let’s rip off more code from this level and create a PHP program to do that, such as the following:

[somebox]$ cat forgeCookie.php
<?

$data = array( “showpassword”=>”yes”, “bgcolor”=>”#ffffff”);

function xor_encrypt($in) {
$key = “qw8Jqw8Jqw8Jqw8Jqw8Jqw8Jqw8Jqw8Jqw8Jqw8Jqw”;
$text = $in;
$outText = ”;

// Iterate through each character
for($i=0;$i<strlen($text);$i++) {
$outText .= $text[$i] ^ $key[$i % strlen($key)];
}

return $outText;
}

print base64_encode(xor_encrypt(json_encode($data)));

?>

When we go a head and run the above program, we get our desired faked cookie value with showpassword set to yes:

[somebox]$ php forgeCookie.php
ClVLIh4ASCsCBE8lAxMacFMOXTlTWxooFhRXJh4FGnBTVF4sFxFeLFMK

Now if we load up the webpage in our browser, such as Chrome, and use something like the Edit This Cookie add-on to change the cookie value, we see the fruits of our labor.  The password for the next level is displayed on the screen!

So What?

In this level, a key based encryption algorithm was used as a verification of valid cookie data, before using the cookie data.  While a good idea in theory, the way it was executed was flawed since the encryption used has a very simple known plain text attack, and in this instance, we were able to find both the plain and cipher text.  Other key based encryption schemes would be better in this situation, such as AES.

Posted in Natas, Over The Wire, Wargames | 2 Comments

Natas Level 10 – Input Sanitization

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

What’s Going On?

Upon logging in, we should see that this level seems very similar to the previous.  In fact, it’s presented the same except it tells us that it performs user sanitization (“we now filter on certain characters”).  Checking the HTML and PHP source code we see very little differences except for one check in the PHP code.  This check is a regex expression checking for any instance of ; | or &.  These characters are used on the linux shell to separate commands, and thus, this is an attempt to make sure our page only submits on command to passthru().  So, how can we make use of our position of supplying data to passthru and to grep, to get the password for the next level?

Exploit

While we can’t easily supply multiple commands, maybe we can make use of the grep command.  Looking at how the key is combined with grep, let’s try and figure out a way to read the password file.  With grep, we could supply empty quotes to list the contents of the directory file, and if we try it, it works.  Submit “” and see the contents of the file!  Next, we need to specify a different file.  Well, luckily, with grep we can specify multiple files to search through!  Thus, let’s try “” /etc/natas_webpass/natas11.  Low and behold we get the contents of the password file followed by the contents of the dictionary.txt file!

So What?

So again, even with “sanitization,” one must be aware of what to sanitize.  This level did a fine job preventing users from submitting multiple commands to the shell, however the desired command itself also has areas which made it a vector for leaked information, a vector of attack.

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

Natas Level 9 – Shell Execution

In this post we’re going to be looking at level 9 of the Natas wargame provided by Over The Wire.

What’s Going On?

Upon logging in we’re presented with another text entry and submit button, a long with a link to the source of the php page.  Viewing the HTML source quickly shows no hints or ideas, so let’s click on the view source code link.  Once we are viewing the PHP source code, we can see what this page does.  It takes a user input and passes it as part of a command to the PHP function passthru().  Passthru() takes a string representing a shell command, and executes it, returning the output back towards us.  In this instance, passthru() gets fed a string starting with the grep command.  This is all good in the normal execution, we can even grep through the dictionary.txt file by submitting the web form with values in it.  However, what can we do with this to break out?

Exploit

The first thing to notice is that the user supplied input is not sanitized.  Next, it’s placed into the middle of a command, making it slightly more involved than passthru(userInput), but not by much.  Since the string passed to passthru is sent directly to the shell, we can break up shell commands with the semi-color delimiter.  To test this, let’s make a crafted string.  This string will finish the grep command, perform a command we desire, then do something with the appended “dictionary.txt.  To test this, let’s try to make our command print the current directory.  Let’s make use of the following string for that:

“skldfjklsjfklsjf” dictionary.txt; pwd; ls -la

Putting the above string into the search box and clicking submit will net us a page with the current directory (/var/www/natas/natas9), and an ls -la print out of dictionary.txt.  Now lets switch up the pwd command with something more valuable.  If we remember back a couple levels, we had to read a password from a file at /etc/natas_webpass/natas8.  Well, let’s see if there is a similar file for the next level.  Let’s get the directory listing from /etc/natas_webpass:

“skldfjklsjfklsjf” dictionary.txt; ls -la /etc/natas_webpass/; ls -la

Upon searching, we get back the listing of the natas_webpass directory.  Low and behold, there is a natas10 file which is group readable for natas9!  So, let’s try to read that file:

“lksdfklsdfdklsf” dictionary.txt; more /etc/natas_webpass/natas10; ls -la

Once executed, we should now see the password for level10.

So What?

One should be VERY careful when using functions such as passthru(), exec(), system(), etc.  Even if they are designed to take a string (“a command”), sometimes multiple commands can be put together in a way which is both logically legal and against the initial intentions of the original command.  These functions are very dangerous as the commands are passed to the shell, and if they are user supplied, that means users can alter and possibly control what is passed to the shell.

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

Natas Level 8 – Encoding Instead of Hashing

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

What’s Going On?

Upon logging in we’re presented with another input field, submit button and source code link.  Quickly viewing the source of our current page, we see no comments, so let’s move on to the source code link.  Here we see the php source code of our current page.  This code takes user input, performs base64_encode, string reverse, and binary to hex conversion, in that order.  Then the result is compared to a constant variable, and if they match the password for the next level is revealed.  So, how do we figure out what to input so that they will match?

Lucky for us, all the functions used are 2-way functions.  This means that they all have a reverse operation.  So, let’s take the encryptedSecret variable and do the reverse operations on it.  We can do this easily by creating a small php file.  Lets look at a file that will do just this:

<?

$encodedSecret = “3d3d516343746d4d6d6c315669563362”;
$binString = pack(“H*”, $encodedSecret);
$revString = strrev($binString);
$decodedString = base64_decode($revString);

print “$decodedString”;

?>

Reverse functions in opposite order.  The only thing of real note is the pack function.  PHP’s  hex2bin function has been outdated since PHP5 and replaced with pack.  Running this script (I choose from the command line), results in the output of the decoded secret.  Copying this secret and pasting it into the text field on the level8 website and submitting it results in an “Access Granted” message, and the password to the next level.

So What?

This is an interesting level.  From a programming perspective, one might say the functions are easy to program in reverse, so this isn’t safe.  After all, seeing the source code makes it easy to crack, and thus we know saying most people won’t see it is security through obscurity and that isn’t safe.  So what is a better choice?  Well, it depends what you’re trying to do, but in this level a better choice would have been a better choice in hash functions.  Hash functions are 1-way functions, functions without a reverse operation function.  This means to “reverse” or discern the original value, one must guess through all possible originals until the same encrypted (hashed) value is found.  Some popular hash functions are MD5, SHA-1, SHA-256, SHA-512 and, just this month, NIST announced that Keccak was selected as the algorithm to become SHA-3!

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

Natas Level 7 – User Input and Unsafe Includes

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

What’s Going On?

Upon logging in, we are presented with a page with two links.  Let’s view the page’s source first.  Upon doing this, we get a comment hint that the password for the next level is located in the file at /etc/natas_webpass/natas8.  We also see that the two links are links to the current page with a value assigned to the “page” variable.  The value is passed via the URL and GET style arguments, making it easy to edit.  If we go back and click on either link we can see some text on each page.

This site navigation option of taking a page name as a variable has many positive sides from a web-programmer’s point of view.  However, let’s look at how it is implemented in this page.  The simplest thing to conclude would be a simple include($_GET[‘page’]); call.  This would, in the example of home and about, simply get files called home or about.  Let’s check this idea by requesting those URLs ourselves and checking they exist and match what we saw earlier on those pages.  We should find http://natas7.natas.labs.overthewire.org/home and http://natas7.natas.labs.overthewire.org/about both exist, and have our expected values.  Thus, let’s make the assumption we figured out how the include works.  How can we use this to get the password to the next level?

Exploit

Since the include file is specified via the page variable, let’s think about what we can supply as the page variable to get the password to the next level.  As we saw in the comment hint, the password is stored in the file /etc/natas_webpass/natas8.  So, let’s try supplying that as the value of the page variable!  Requesting the page, http://natas7.natas.labs.overthewire.org/index.php?page=/etc/natas_webpass/natas8, we get a response with the password for level 8.

So What?

So what!?  So don’t blindly let users access files or provide absolute and full file locations!  Use some input sanitation! Start from the current directory (string concat “./”.$sanitizedUserInput).  Append file types!  There are various options at making this safer, but having un-sanitized user provided data act as absolute file paths on the server, is not a good idea.

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