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:

  • Username: natas11
  • Password: U82q5TCMMQ9xuFoI3dYX61s7OZD9JKoK

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:

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:

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:

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 $latex (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:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
<?

$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>

<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>";
}

?>

ObservationsI 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 $latex A$ be the key and let $latex B$ be the defaults. Let $latex C$ be the encrypted defaults. We know that $latex 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: $latex 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”):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
// 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:

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):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
// 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:

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

We now get the password to the next level!

Conclusion

Capture The Flag security games are great! You need to think like another computer or person in order to find the bug. Most of the time, this is rewarded by learning something new. I had never heard about the Burp suite before writing this blog post. I had some background knowledge of the XOR encryption, but this was also described on Wikipedia. If you have any questions or comments or if you know an awesome CTF challenge, feel free to post them below! And if you liked this article, feel free to share it :-).

Besides posts on security, Data Blogger also provides many tutorials on software development. If you are interested in web scraping, you should definitely check out this step-by-step guide about Python Scrapy.