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:

  1. Step 1 determines the Key value of the original function. Remember the formula that ChatGPT provided: key = plaintext ⊕ ciphertext
  2. Step 2 then takes that key, and uses it with an edited $defaultdata array - called $editeddata to set the showpassword value to yes.
<?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.