# My Approach to Natas Level 11 (a Web Security Game)

Recently I came across the concept of CTF (Capture The Flag) which are security competitions and I really enjoy these kinds of the competitions. One of my favorites is OverTheWire. They provide different kinds of games and one of these is Natas, in which you need to attack a webserver. The concept is simple: the creator of the game designs a normal functioning webserver and intentionally puts in a bug. We need to find a password in order to get to the next level which can be found by exploiting the bug. That’s why it is called Capture The Flag. So lets get started!

## Starting the Level

You can access level 11 of the Natas game by navigating to this URL: http://natas11.natas.labs.overthewire.org/ and by using the following credentials:

## Tools

If you are not interested in the tools I used for modifying web requests, you can skip this section.

I highly recommend the Burp suite for intercepting and modifying web requests. Besides that, you need to forward your requests to the suite using a proxy. If you use Chrome, you can use the FoxyProxy plugin for that. Make sure to setup a Proxy listener in Burp:

Burp Proxy Listener.

The Proxy Listener can be found under the Proxy tab and then by navigating towards Options. By default, port 8080 is used.

Now you need to forward the requests from your browser to the Burp suite. This is done by creating a proxy sending requests to the Proxy which is created in Burp (127.0.0.1:8080). This is my FoxyProxy configuration:

FoxyProxy settings.

Nice! Now the Burp suite and my browser are connected. When I request a website, I get the details in the Burp suite and I can modify all data before sending the actual request. After changing data, I can press the “Forward” button to send the actual modified request. Make sure to disable your proxy after using it. I will use the Burp suite in this blog post for modifying the cookie information.

## My Approach

### Exploring Phase

We will first take a look at the different components and try to find any vulnerability in the code. Lets take a look at the screen:

Game screen for Natas Level 11.

Hmm. Nothing special. Except the message that XOR encryption is used. This Wikipedia article gives some clues about the encryption. The most important property is $(A \bigoplus B) \bigoplus B = A$ which states that when you encrypt some data twice, you will get back to the original. This is definitely something we could abuse later on. We can now check out the source code by clicking on the “View sourcecode” link:

<?

$defaultdata = array( "showpassword"=>"no", "bgcolor"=>"#ffffff"); function xor_encrypt($in) {
$key = '<censored>';$text = $in;$outText = '';

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

return $outText; } function loadData($def) {
global $_COOKIE;$mydata = $def; if(array_key_exists("data",$_COOKIE)) {
$tempdata = json_decode(xor_encrypt(base64_decode($_COOKIE["data"])), true);
if(is_array($tempdata) && array_key_exists("showpassword",$tempdata) && array_key_exists("bgcolor", $tempdata)) { if (preg_match('/^#(?:[a-f\d]{6})$/i', $tempdata['bgcolor'])) {$mydata['showpassword'] = $tempdata['showpassword'];$mydata['bgcolor'] = $tempdata['bgcolor']; } } } return$mydata;
}

function saveData($d) { setcookie("data", base64_encode(xor_encrypt(json_encode($d))));
}

$data = loadData($defaultdata);

if(array_key_exists("bgcolor",$_REQUEST)) { if (preg_match('/^#(?:[a-f\d]{6})$/i', $_REQUEST['bgcolor'])) {$data['bgcolor'] = $_REQUEST['bgcolor']; } } saveData($data);

?>

<h1>natas11</h1>
<div id="content">
<body style="background: <?=$data['bgcolor']?>;"> Cookies are protected with XOR encryption<br/><br/> <? if($data["showpassword"] == "yes") {
print "The password for natas12 is <censored><br>";
}

?>

### Observations

I did the following observations:

• The password is shown when “showpassword” is set to “yes”. So we should do that :-).
• The bgcolor variable is checked for validity (it should start with # followed by 6 digits).
• First, data is loaded by the loadData method. It either uses a default ([“showpassword” => “no”, “bgcolor” => “#ffffff”]) or it uses decrypted data from the cookie. The latter option can be modified by us, so this would be a potential attack.
• When the default is used, we will get a cookie with the encrypted version of the default.
• For modifying the cookie data, we need to know the key that was used. Hmmm…

### Potential attack

Now we can think of a potential attack:

• Step 1: Get the encrypted version of the defaults.
• Step 2: Let $A$ be the key and let $B$ be the defaults. Let $C$ be the encrypted defaults. We know that $C = A \bigoplus B$. In this problem, we have access to the encrypted defaults and to the defaults. Is it possible to obtain the key from this? Yes! Since: $A = (A \bigoplus B) \bigoplus B = C \bigoplus B$. In other words, when applying XOR encryption on the encrypted defaults and the defaults, we get back the key by this property of the XOR encryption.
• Step 3: We can forge our desired data ([“showpassword” => “yes”, “bgcolor” => “#ffffff”]) into the cookie by using the XOR encryption with the found key.
• Step 4: Now we should get the password!

Lets start!

## The Attack

### Step 1: Get the encrypted version of the defaults

This subproblem is not that hard. We can use the developer tools (keyboard shortcut F12) in Chrome to inspect the cookie data:

There we are. The encrypted version of the defaults equals ClVLIh4ASCsCBE8lAxMacFMZV2hdVVotEhhUJQNVAmhSEV4sFxFeaAw.

### Step 2: Decrypt the key

I wrote a little PHP script to obtain the key (and ran this script on a local PHP shell using “php -a”):

// Just the same XOR encrypt code as found in the script but using $key as an argument so we can modify that function xor_encrypt($in, $key) {$text = $in;$outText = '';

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

return $outText; } // Get the encrypted default, make sure to peel of the base64 encrypted layer$enc_defaults = base64_decode("ClVLIh4ASCsCBE8lAxMacFMZV2hdVVotEhhUJQNVAmhSEV4sFxFeaAw");
// The defaults as found in the script
$defaults = json_encode(array("showpassword"=>"no", "bgcolor"=>"#ffffff")); // Obtain the key by abusing the properties of the XOR encryption$key = xor_encrypt($enc_defaults,$defaults);

// Display the result
echo $key; This resulted into the following: PHP shell. Great! There we have our key :-). The key equals qw8J. One property of the XOR encryption is that the key often is repeated. qw8J is a repeating pattern in the result we found. ### Step 3: Encrypt the modified data Now we can easily encrypt a modified version of the data (again by using the PHP interactive shell): // Now by using the key we just found we can create a modified version of the defaults function xor_encrypt($in, $key) {$text = $in;$outText = '';

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

return $outText; }$key = "qw8J";
echo base64_encode(xor_encrypt(json_encode(array("showpassword"=>"yes", "bgcolor"=>"#ffffff")), \$key));

This resulted into the following encrypted version of the modified data: ClVLIh4ASCsCBE8lAxMacFMOXTlTWxooFhRXJh4FGnBTVF4sFxFeLFMK.

### Step 4: Obtain the password

Now we can use the Burp suite to modify the HTTP request by changing the cookie data:

Modifying request data using Burp.

First, I changed the cookie data and I then pressed the forward button.

We now get the password to the next level!