Solution for Natas web security wargame with by XORing the plaintext with the ciphertext...
Currently I am playing some wargames on overthewire.org.
The first 10 levels were very easy and everyone with some technical knowledge and programming experience should be able to solve them. But somehow I got stuck for a few hours on level 11. The task is to modify a XOR encrypted cookie. For some reason I couldn't figure out how to obtain the xor key that was used.
The challenge was to reverse engineer the key by having the plaintext and the ciphertext. Of course I should have realized very quickly that xoring the plaintext with the ciphertext yields us back the key. But why is this so? Consider the following math:
plaintext xor ciphertext == key <=> plaintext xor (plaintext xor key) <=> plaintext xor plaintext xor key <=> 00000... xor key == key
As you can see, the plaintext cancels out. If the plaintext would be a
single byte, say, 1100 1101, then XORing this byte with itself yields:
1100 1101 XOR 1100 1101 -------- 0000 0000
To finally get to solution of the wargame, you can safe the following file as a PHP file and run it:
<?php
function xor_encrypt($text, $key) {
$outText = '';
// Iterate through each character
for($i=0;$i<strlen($text);$i++) {
$outText .= $text[$i] ^ $key[$i % strlen($key)];
}
return $outText;
}
function decodeData($data, $key) {
return json_decode(xor_encrypt(base64_decode($data), $key), true);
}
function encodeData($data, $key) {
return base64_encode(xor_encrypt(json_encode($data), $key));
}
function encodeData2($data, $key) {
return base64_encode(xor_encrypt($data, $key));
}
function xstrings($s1, $s2) {
if (strlen($s1) != strlen($s2)) {
print 'Strings must be equal in length!';
return;
}
$res = '';
for($i = 0; $i < strlen($s1); $i++) {
$res .= $s1[$i] ^ $s2[$i];
}
echo $res."\n";
echo bin2hex($res)."\n";
}
// finding out the key
xstrings(base64_decode("ClVLIh4ASCsCBE8lAxMacFMZV2hdVVotEhhUJQNVAmhSEV4sFxFeaAw="),
json_encode(array( "showpassword"=>"no", "bgcolor"=>"#ffffff")));
// the above function outputs
// qw8Jqw8Jqw8Jqw8Jqw8Jqw8Jqw8Jqw8Jqw8Jqw8Jq
// 7177384a7177384a7177384a7177384a7177384a7177384a7177384a7177384a7177384a7177384a71
// we can easily see that the xor key must be 'qw8J'
$key = 'qw8J';
// generate the new data with the key
echo 'Submit the following as the "data" cookie to gain access: '.encodeData(array("showpassword"=>"yes", "bgcolor"=>"#ffffff"), $key)."\n";
?>
Here a screenshot of the message you get when submitting the generated cookie: