Friday 3 October 2014

Wargames - Natas 11

<< Previous challenge

Recommended reading:
From the credentials discovered from the previous challenge, head up to http://natas11.natas.labs.overthewire.org and take a look at its content.
This challenge is pretty interesting and fun, some cryptography knowledge is required, specifically XOR cipher. If you take a look at the page, it's a simple form that takes an hexadecimal value and sets it as the background color of the page, no big deal there. We're also told that the cookies are XOR encrypted. We can assume that the background color we choose is saved in said cookies. Let's take a look at the source code:
 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
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
<html>
<head>
<!-- This stuff in the header has nothing to do with the level -->
<link rel="stylesheet" type="text/css" href="http://natas.labs.overthewire.org/css/level.css">
<link rel="stylesheet" href="http://natas.labs.overthewire.org/css/jquery-ui.css" />
<link rel="stylesheet" href="http://natas.labs.overthewire.org/css/wechall.css" />
<script src="http://natas.labs.overthewire.org/js/jquery-1.9.1.js"></script>
<script src="http://natas.labs.overthewire.org/js/jquery-ui.js"></script>
<script src=http://natas.labs.overthewire.org/js/wechall-data.js></script><script src="http://natas.labs.overthewire.org/js/wechall.js"></script>
<script>var wechallinfo = { "level": "natas11", "pass": "<censored>" };</script></head>
<?

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

?>

<form>
Background color: <input name=bgcolor value="<?=$data['bgcolor']?>">
<input type=submit value="Set color">
</form>

<div id="viewsource"><a href="index-source.html">View sourcecode</a></div>
</div>
</body>
</html>
Biggest source we've seen so far, let's break it into smaller parts, looking first into the functions:
xor_encrypt: This is a basic xor encryption, the key for the cipher is censored, otherwise it'd be too easy, if you take a look at the recommended reading, you'll understand how easy it works. The input text is just repeatedly XORed with the key in order to get the encrypted text;
loadData: This function is also pretty simple, although it's the biggest in the code. What it does is try to load the data saved in the cookies and sets it accordingly. If there's no cookie or if the cookie data isn't valid, it uses the default values, which are set in line 13.
saveData: Also pretty simple and obvious, it takes the data and saves it in the cookies, since this is the most simple function, we can easily see how the data is stored:
json_encode -> xor_encrypt -> base64_encode
This sums up all the functions, after their definitions comes some simple logic. Data is loaded from the cookie, or uses the default data, afterwords it checks if there's a request (GET request in this case) with the bgcolor key, if there is and it's a valid color, it sets the data with the new background color. Finally it saves the data to the cookies.
Uff, we're done analyzing this. All fun and games, but how can we exploit this? It all comes down to the xor_encrypt function, it's a basic XOR, even though we don't have the key, we have the decoded data and the encoded data, so we just need to XOR that in order to get the key, how simple right? You can use a PHP Sandbox and simply copy the xor_encrypt function, replace the key with either the encoded or decoded data and call it with the data you didn't use as a key. I'll leave it for you to try this on your own, don't forget that the encoded data is base64 encoded and that decoded data is json encoded before being encrypted. If you've done everything right, you should end with and output similar to this:
qw8Jqw8Jqw8Jqw8Jqw8Jqw8Jqw8Jqw8Jqw8Jqw8Jq
This is the encryption key, don't forget that it gets repeated due to it's small size, so the key is only: qw8J. Having the key to encrypt makes it trivial to do what we want. In the xor_encrypt function we set this key, and again pass the default data in, but this time change the showpassword field to yes, pretty simple. Again, don't forget that the data is json encoded before being encrypted and it's base64 encoded before being saved in the cookie. This is what our modified cookie looks like:
ClVLIh4ASCsCBE8lAxMacFMOXTlTWxooFhRXJh4FGnBTVF4sFxFeLFMK
Now we just need to change the data cookie to reflect our modification. You can do this in various ways, I fine just using curl to do so:
curl --cookie data=ClVLIh4ASCsCBE8lAxMacFMOXTlTWxooFhRXJh4FGnBTVF4sFxFeLFMK http://natas11:U82q5TCMMQ9xuFoI3dYX61s7OZD9JKoK@natas11.natas.labs.overthewire.org/
And this is what we get:
 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
<html>
<head>
<!-- This stuff in the header has nothing to do with the level -->
<link rel="stylesheet" type="text/css" href="http://natas.labs.overthewire.org/css/level.css">
<link rel="stylesheet" href="http://natas.labs.overthewire.org/css/jquery-ui.css" />
<link rel="stylesheet" href="http://natas.labs.overthewire.org/css/wechall.css" />
<script src="http://natas.labs.overthewire.org/js/jquery-1.9.1.js"></script>
<script src="http://natas.labs.overthewire.org/js/jquery-ui.js"></script>
<script src=http://natas.labs.overthewire.org/js/wechall-data.js></script><script src="http://natas.labs.overthewire.org/js/wechall.js"></script>
<script>var wechallinfo = { "level": "natas11", "pass": "U82q5TCMMQ9xuFoI3dYX61s7OZD9JKoK" };</script></head>

<h1>natas11</h1>
<div id="content">
<body style="background: #ffffff;">
Cookies are protected with XOR encryption<br/><br/>

The password for natas12 is EDXp0pS26wLKHZy1rDBPUZk0RKfLGIR3<br>
<form>
Background color: <input name=bgcolor value="#ffffff">
<input type=submit value="Set color">
</form>

<div id="viewsource"><a href="index-source.html">View sourcecode</a></div>
</div>
</body>
</html>
Here we go, line 17, we get the password for natas12.

User natas12
Password EDXp0pS26wLKHZy1rDBPUZk0RKfLGIR3

Interesting challenge indeed, pretty simple after you understand it. He can see how XOR encryption is easy to break, even more in this case where we have both the encoded and decoded text.

Never Settle,

<< Previous challenge

No comments:

Post a Comment