Natas11-->Natas12
We're continuing our series of the Natas challenges. In the previous post, we navigated two challenges of increasing complexity around command injection. This writeup will solely focus on one challenge, around XOR.
Walkthrough
Website: http://natas11.natas.labs.overthewire.org/ Access Credentials: natas11:1KFqoJXi6hRaPluAmk8ESDW4fSysRoIg
As with previous challenges, visit the site, and hit the View Sourcecode link. Within the PHP, there are three functions xor_encrypt()
, loadData()
, and saveData()
. The loadData()
and saveData()
functions both the xor_encrypt()
function inside of it. The former to return an array of $mydata
and the latter function sets a cookie of data
with the base64 encoded value of the xor'd json encoded value.
Prior to the functions, there is an array of $defaultdata
, with default key value pairs of showpassword="no"
, and bgcolor="#ffffff"
. After the functions, a variable of $data
is defined which uses the loadData
function to initially setup the $data
array using the $defaultdata
key value pairs. The code checks to ensure the the value for bgcolor
is an expected value, mainly 6 values of a digit or lowercase letter a-f. If the condition is met, it updates the $data['bgcolor']
value to the value provided in the request. Lastly, the code then uses the saveData
function to set the data
cookie value to the base64, xor encrypted, and json encoded value of the $data
array.
After the first batch of php is the HTML, which shows another small batch of PHP code:
<?
if($data["showpassword"] == "yes") {
print "The password for natas12 is <censored><br>";
}
?>
This if statement is checking to see if the showpassword
key in the $data
array has a value of yes
. If so, it will print the password. The logical conclusion is that we need to edit our cookie value, so that it sets the showpassword
key to a value of yes
.'
Looking closer at the xor_encrypt()
function, it appears as if the value of the $key
variable has been redacted.
Like in the last challenge, lets continue the trend of diversifying our research techniques, and asking ChatGPT in lieu of the google machines. Assuming you know nothing about XOR, you could pose the following question and get a response like the following:
Lets pause to take a look at these functions in action. The natas11 home page should load a default value of #ffffff
in the Background Color text box. Click Set Color and the page will reload. Inspect the request/response in a proxy, and note the Cookie header value of data=MGw7JCQ5OC04PT8jOSpqdmkgJ25nbCorKCEkIzlscm5oKC4qLSgubjY%3D
. We can this value the JSON encoded, then XOR encrypted and base64 encoded value of the $defaultdata
array in the beginning of the code (array( "showpassword"=>"no", "bgcolor"=>"#ffffff")
). So we have the plaintext value - the $defaultdata
array, the ciphertext - the value of the data
cookie, which has also been base64 encoded. We can use those two items to derive the key
used in the XOR function.
Below is the code to help solve the challenge. It's helpful to use a PHP sandbox like onlinephp.io to solve the challenge yourself. Additionally, you can find my solution there as well. This code is technically written in two steps:
- Step 1 determines the Key value of the original function. Remember the formula that ChatGPT provided:
key = plaintext ⊕ ciphertext
- Step 2 then takes that key, and uses it with an edited
$defaultdata
array - called$editeddata
to set theshowpassword
value toyes
.
<?php
$defaultdata = array("showpassword" => "no", "bgcolor" => "#ffffff");
$editedtdata = array("showpassword" => "yes", "bgcolor" => "#ffffff");
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;
}
print "Step 1 - Determine the value of the 'key' first!\n";
print xor_encrypt(base64_decode('MGw7JCQ5OC04PT8jOSpqdmkgJ25nbCorKCEkIzlscm5oKC4qLSgubjY='), json_encode($defaultdata));
print "\nThis is a repeating string... remove the repeating characters to come up with a unique key\n";
print "Take the output from Step 1, and provide it as the key value in the function below\n";
print "new cookie:\n";
print base64_encode(xor_encrypt(json_encode($editedtdata), 'KNHL'));
?>
The code edits the original xor_encrypt
function a tad, allowing for two values to be passed in, not just the plaintext, but also the key value. Take the last line in the code output and provide it as the data
cookie value to retrieve the password. MGw7JCQ5OC04PT8jOSpqdmk3LT9pYmouLC0nICQ8anZpbS4qLSguKmkz
.
The server responds with the password: YWqo0pjpcXzSIl5NMAVxg12QxeC1w9QG
.