OverTheWire Natas 20-24

Level 20

User: natas20

Pass: eofm3Wsshxc5bwtVnEuGIlr7ivb9KABF

Back to having source code, let’s take a look and find the important stuff.

   if($_SESSION and array_key_exists(“admin”, $_SESSION) and $_SESSION[“admin”] == 1) {

   print “You are an admin. The credentials for the next level are:<br>”;

   print “<pre>Username: natas21\n”;

   print “Password: <censored></pre>”;

   }

So first we can see that there is a conditional statement checking for three things.

  1. Does the global variable $_SESSION exist?
  2. Is the key “admin” set in the array $_SESSION?
  3. Does $_SESSION[“admin’] equal 1?

Trying to meet these conditions we can look in the code for setting the “admin” key. However, in the code this key is not set anywhere; let’s look deeper.

As long as the $sid variable meets the conditional statement below by only consisting of the variables shown than we see that we save a file.

   if(strspn($sid, “1234567890qwertyuiopasdfghjklzxcvbnmQWERTYUIOPASDFGHJKLZXCVBNM-“) != strlen($sid)) {

   debug(“Invalid SID”);  

       return “”;

   }

$filename = session_save_path() . “/” . “mysess_” . $sid;

Therefore, the $filename variable will be “currentDirectory/mysess_/$sid”. However, in the myread function this file will be checked to see if it exists. When it realizes it does not the function is terminated. Luckily, in the mywrite function we can create this file.

   $filename = session_save_path() . “/” . “mysess_” . $sid;

   $data = “”;

   debug(“Saving in “. $filename);

   ksort($_SESSION);

   foreach($_SESSION as $key => $value) {

       debug(“$key => $value”);

       $data .= “$key $value\n”;

   }

   file_put_contents($filename, $data);

   chmod($filename, 0600);

In the above foreach loop we can see how the data is saved to the $_SESSION array. We simply provide a key followed by a space followed by a value. The next line will contain another key and then value. This follows the ksort() method of sorting arrays which it indeed mentions in the code.

Now we are back to our initial problem. Setting the “admin” key value in the $_SESSION array. Looking back at the myread function we can see how the key and values are read from the array.

   $_SESSION = array();

   foreach(explode(“\n”, $data) as $line) {

       debug(“Read [$line]”);

   $parts = explode(” “, $line, 2);

   if($parts[0] != “”) $_SESSION[$parts[0]] = $parts[1];

   }

   return session_encode();

Explode is giving us a wonderful vulnerability. This operation splits a string into substrings based on a delimiter which they have chosen as “\n” otherwise known as a new line. This means that when myread looks at our input if we place a new line into our input it will read each line individually enabling us to provide a value for the name key and also provide a new key and name to write as the input for the name key will satisfy the other conditional statements.

Let’s go back to the 3 conditions to receive the password

1) Does the global variable $_SESSION exist?

Yes!

2) Is the key “admin” set in the array $_SESSION?

We can set the key admin by exploiting the explode method used. As usual we will want to encode our input using url encoding.

Plaintext “admin\nadmin 1” => “admin%0Aadmin%201”

Do not try this in a url encoder the encoding for a new line is ‘%0A’

3) Does $_SESSION[“admin’] equal 1?

Yes! With our new input the key now equals 1

Using curl we will first send the post request with a custom PHPSESSID which will create the admin authentication on that session ID. We will then send another curl request with this session id and obtain the password for the next level.

Below we can see our curl request and in the response we see value=”xyz” where xyz should be a new line followed by “admin 1”  which is exactly what we want. I chose to set the PHPSESSID to “testing”. Therefore, to obtain the password we will send a curl request with –cookie “PHPSESSID=testing”.

Level 21:

User: natas21

Pass: IFekPyrQXftziDEsUr3x21sYuahypdgJ

Here we are once again signed in as a regular user. The objective is once again to meet the 3 requirements listed below to print out the credentials for the next user.

  1. Does the global variable $_SESSION exist?
  2. Is the key “admin” set in the array $_SESSION?
  3. Does $_SESSION[“admin’] equal 1?

Looking at the source code all we are given is that session_start() and print_credentials() are called. Not much to see so let’s move on to the other page which is linked on the original challenge page.

Looking at the source code on the colocated web page we can quickly find our way to set the admin key. First we see the following:

// if update was submitted, store it

if(array_key_exists(“submit”, $_REQUEST)) {

   foreach($_REQUEST as $key => $val) {

   $_SESSION[$key] = $val;

   }

}

Therefore we see that if the key “submit” exists in the array $_REQUEST it will then execute a for loop going through each value in the array $_REQUEST and assigning the key and value to the array $_SESSION.

When looking at the network as we hit the “Update” button we can see the following:

Since we know the code mentioned previously does not filter for specific keys and values we can simply add admin as a key with a value of 1. Let’s try this with curl:

Using curl again with the same PHPSESSID we used to send the POST request we can get the password for natas22.

Level 22:

User: natas22

Pass: chG9fbe1Tq2eWVMgjYYD1MsfIvN461kJ

Well this page has absolutely nothing on it so this should be fun. Let’s look at the source code. First, we see that a session is started. If the array from the $_GET variable contains a key with the name “revelio” the admin credentials will be printed. Let’s try using curl and sending a get request with the string “revelio”.

<?

   if(array_key_exists(“revelio”, $_GET)) {

   print “You are an admin. The credentials for the next level are:<br>”;

   print “<pre>Username: natas23\n”;

   print “Password: <censored></pre>”;

   }

?>

Level 23:

User: natas23

Pass: D0vlad33nQF0Hz2EP255TP5wSW9ZsRSE

<?php

   if(array_key_exists(“passwd”,$_REQUEST)){

       if(strstr($_REQUEST[“passwd”],”iloveyou”) && ($_REQUEST[“passwd”] > 10 )){

           echo “<br>The credentials for the next level are:<br>”;

           echo “<pre>Username: natas24 Password: <censored></pre>”;

       }

       else{

           echo “<br>Wrong!<br>”;

       }

   }

   // morla / 10111

?>  

Here we have two conditions in order to receive the password.

  1. Does the passwd key contain the string “iloveyou”?

This one is easy to solve, simply be sure to include “iloveyou” in the password input

  1. Is this string > 10?

This one is also easy if you recognize that we are comparing a string to an int. Therefore we need the string we input to have a greater int value than 10. You can run various trials through the intval() function at this site: https://www.functions-online.com/intval.html or save the php code and execute it. What you will find is that no matter the string your result will be 0 unless, the string beings with a number. This means we can simply input “123iloveyou” and we will receive the password.

Level 24:

User: natas24

Pass: OsRmXFguozKpTZZ5X14zNO43379LZveg

This level is similar to the last however, the condition has changed.

  1. Does a key of “passwd” exist in the array $_REQUEST?

Once we fill in the form this becomes true.

  1. When comparing the value for the key passwd to the censored string does it return 0?

While reading the info on strcmp() at http://php.net/manual/en/function.strcmp.php the top comment suggests that if we compare a string with another type we will receive unexpected results.

How can we get one of the strcmp() parameters to be a non-string value? Well taking a look at our GET request what we have is “password=whatever”. What we can do is change the password variable! If we change our request to “password[]=123” we will receive the password for the next level.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

This site uses Akismet to reduce spam. Learn how your comment data is processed.

Create a website or blog at WordPress.com

Up ↑

%d bloggers like this: