Challenge:
Cookies are protected with XOR encryption

Solution:
I checked into this but it seems pretty hard to do. Lets try it and if we get stuck we google for some help.

First lets have a look at the source code again

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

So lets see what we found:

  • The variable defaultdata is an array with the values: Showpassword -> No and bgcolor -> ffffff
  • There is an xor function to encrypt
  • There is a function to load data which will check if the colorcode is valid.
  • When the variaba data has the value of yes. We will get the key to the next level
  • But to modify this data we need to have the key, which is censored.

So lets read more about XOR. “a string of text can be encrypted by applying the bitwise XOR operator to every character using a given key. To decrypt the output, merely reapplying the XOR function with the key will remove the cipher. ” So if we can run the same value through the XOR encryption we get the decrypted value. (A ⊕ B) ⊕ C = A ⊕ (B ⊕ C). So lets say C is the key, A is the defaults and B is the encrypted defaults.
1. The defaults can be found in the code and are: $defaultdata = array( “showpassword”=>”no”, “bgcolor”=>”#ffffff”)
2. The encrypted defaults can be found in the cookie and are: ClVLIh4ASCsCBE8lAxMacFMZV2hdVVotEhhUJQNVAmhSEV4sFxFeaAw%3D
3. The key we don’t know

Step 2 can be found in the developer console under storage. This is where we can find our cookies.

So lets try to make a PHP script with my little php knowledge to complete this. It was hard but with some help it worked.

// same XOR encrypt function from the webpage but deleted the $key variable since we dont have it.
// added to the function so we can pass the value when we get it
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;
}

// The defaults unencrypted, but these need to be json encoded
$defaults = json_encode(array("showpassword"=>"no", "bgcolor"=>"#ffffff"));

// The defaults encrypted
$encrypted_defaults = base64_decode("ClVLIh4ASCsCBE8lAxMacFMZV2hdVVotEhhUJQNVAmhSEV4sFxFeaAw");

$key = xor_encrypt($encrypted_defaults, $defaults);
echo $key;

The output is: qw8Jqw8Jqw8Jqw8Jqw8Jqw8Jqw8Jqw8Jqw8Jqw8Jq. Which is save to say that “qw8J” is repeated a lot, So this is probably the key. Lets make the next piece of code so it encrypts a new value for us. This value needs to be the default value but then with yes. So: (array(“showpassword”=>”Yes”, “bgcolor”=>”#ffffff”)). This value needs to be Json encoded, xor encrypted and base64 encoded.

//Exactly the function as on the webpage, just changed the cencored part to the value of the key.
function xor_encrypt($in) {
    $key = 'qw8J';  
    $text = $in;
    $outText = '';

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

    return $outText;
}
//Using the method to encrypt like it does in the saveData function. With our own data
$cookie = base64_encode(xor_encrypt(json_encode(array("showpassword"=>"yes", "bgcolor"=>"#ffffff"))));
echo $cookie;

So this echo’s the cookie “ClVLIh4ASCsCBE8lAxMacFMOXTlTWxooFhRXJh4FGnBTVF4sFxFeLFMK” which we can try out now. Which gives us access to Natas12 😀

Leave a Reply

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