Welcome to Part 3 of the Natas write up where I cover Natas 11-15 the difficulty on these challenges definitely step it up to the previous ones, so let’s check it out.

Natas 11

So we are presented with a screen that let’s us change the colour of the background, cool.

So just from what the screen says that “Cookies are protected with XOR encryption” we can assume that we need to steal the admin cookie somehow. Let’s have a look at the source code

<?

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



?>

So it seems the way this page is running is that it sets a cookie for the user with two key:value pairs namely ‘showpassword’ and ‘bgcolor’. It then either sets the default values of that if the cookie doesn’t exist or is malformed, or it loads the one that the user has. These cookies are encrypted through this statement

base64_encode(xor_encrypt(json_encode($d)

So base64’d, XOR’d and JSON encoded, let’s have a look at the xor_encrypt function:

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

So it goes through each character of the data and encrypts it with a repeating key, over and over. So to successfully set the showpassword value to 1 we need to encrypt the value correctly with the correct key.

The way I approached this initially was to use python but I had trouble getting the encryption bit to work, so I headed to an online php executer to run the code as close to the actual environment http://www.writephponline.com/.

So if you don’t know, XOR is an exclusive OR function which compares two bits and returns 1 if they are different otherwise it is 0. So in this situation this happening. We need to find the key

plaintext ⊕ key = ciphertext
ciphertext ⊕ key = plaintext

Luckily this property of XOR also exists

plaintext ⊕ ciphertext = key

So we need the ciphertext (our cookie value, making sure that it is URL decoded so replacing the %30 with an =) and the plaintext. The plaintext will be the default value of the cookie that was given to us in the source code.

<?php
$defaultdata = array( "showpassword"=>"no", "bgcolor"=>"#ffffff");
$cookievalue = "ClVLIh4ASCsCBE8lAxMacFMZV2hdVVotEhhUJQNVAmhSEV4sFxFeaAw=";

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

echo xor_encrypt(base64_decode($cookievalue));
?>

This outputs us “qw8Jqw8Jqw8Jqw8Jqw8Jqw8Jqw8Jqw8Jqw8Jqw8Jq” which is the key just repeated, so the XOR key is “qw8J”. Cool so now we use that key to encrypt our own payload with the showpassword value set as ‘yes’.

<?php
$payload = array( "showpassword"=>"yes", "bgcolor"=>"#ffffff");
$cookievalue = "ClVLIh4ASCsCBE8lAxMacFMZV2hdVVotEhhUJQNVAmhSEV4sFxFeaAw=";

function xor_encrypt($in) {
    $key = "qw8J";
    $text = $in;
    $outText = '';

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

    return $outText;
}

echo base64_encode(xor_encrypt(json_encode($payload)));
?>

Making sure to base64 encode the output as well we get a cookie value of ” ClVLIh4ASCsCBE8lAxMacFMOXTlTWxooFhRXJh4FGnBTVF4sFxFeLFMK”. Setting this as our cookie in the browser and refreshing the page:

There we go we have natas 12 password:

EDXp0pS26wLKHZy1rDBPUZk0RKfLGIR3

One Reply to “Natas Writeup Part 3”

Leave a Reply

Your email address will not be published. Required fields are marked *