← Back to Feed CACHED · 2026-10-24 05:28:02 · CACHE_KEY CVE-2025-64446
CVE-2025-64446 · CWE-23 · Disclosed 2025-11-14

Fortinet FortiWeb management API pre-auth path traversal to admin account creation

ASSESSED — NOISGATE
Vendor
—
—
—
Reassessed
—
—
—
Verdict: —
Do you agree?
01 · The Real Story

Your firewall's front door is a screen door — attackers are walking in and minting admin accounts without credentials

CVE-2025-64446 is a relative path traversal (CWE-23) in Fortinet FortiWeb, the company's dedicated Web Application Firewall appliance. The flaw lives in the management-plane GUI API: an attacker sends a crafted POST to /api/v2.0/cmdb/system/admin%3f/../../../../../cgi-bin/fwbcgi, escaping the REST API sandbox and landing directly on the fwbcgi binary that processes admin-plane commands. Because fwbcgi trusts the HTTP_CGIINFO header's Base64-encoded JSON (containing username, profile name, VDOM, and login name) without validating the request came through the authenticated session handler, an unauthenticated remote attacker can impersonate the built-in admin and create a brand-new administrator account with prof_admin privileges, 0.0.0.0/0 trusted-host scope, and an attacker-chosen password. This works against FortiWeb 7.0.0–7.0.11, 7.2.0–7.2.11, 7.4.0–7.4.9, 7.6.0–7.6.4, and 8.0.0–8.0.1. Fixed versions are 7.0.12+, 7.2.12+, 7.4.10+, 7.6.5+, and 8.0.2+.

Fortinet scored this CVSS 9.8 CRITICAL — and for once, the vendor severity is entirely correct and arguably understates operational risk. The CVSS vector AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H accurately reflects that this is zero-click, zero-auth, network-reachable. But CVSS doesn't capture that the target is a perimeter security appliance that is internet-facing by design, that exploitation was confirmed in the wild over a month before formal disclosure, that a Metasploit module ships turnkey, that an initial-access broker ('k0t') has already harvested 70,000+ credentials from FortiWeb and related appliances and is selling access to Qilin and Inc ransomware groups, or that 8,163+ unique IPs were scanning for this bug by January 2026. The vendor label matches; real-world urgency exceeds it.

"Unauthenticated admin takeover on internet-facing WAFs with active exploitation and ransomware broker sales"
02 · The Attack Path

5 steps from start to impact.

STEP 01

Enumerate internet-facing FortiWeb management planes

The attacker uses FOFA, Shodan, Censys, or ZoomEye to identify FortiWeb management interfaces exposed to the internet. FortiWeb management typically listens on ports 443, 8443, 8080, 9443, or 10443. Censys observes approximately 20,000 FortiWeb instances online; after honeypot filtering, roughly 300–2,700 are directly reachable depending on the scanning platform. The attacker needs nothing beyond a search query.
Conditions required:
  • FortiWeb management interface is reachable from the internet
Where this breaks in practice:
  • Best-practice deployments restrict management to OOB/management VLANs, reducing the attack surface — but thousands remain exposed
Detection/coverage: Shodan/Censys/FOFA passive enumeration is invisible to the target. GreyNoise tags FortiWeb probing IPs; CrowdSec and GreyNoise community blocklists cover known scanner infrastructure.
STEP 02

Send path-traversal POST to escape the API sandbox

The attacker sends POST /api/v2.0/cmdb/system/admin%3f/../../../../../cgi-bin/fwbcgi to the FortiWeb management interface. The %3f (URL-encoded ?) tricks the API router into treating the rest of the path as a query string, while the underlying file-resolution logic follows the ../ traversal literally, landing on the /cgi-bin/fwbcgi binary outside the intended API namespace. No authentication token, cookie, or session is required. The Metasploit module admin/http/fortinet_fortiweb_create_admin automates this step.
Conditions required:
  • Target runs an affected FortiWeb version (7.0.x ≤ 7.0.11, 7.2.x ≤ 7.2.11, 7.4.x ≤ 7.4.9, 7.6.x ≤ 7.6.4, 8.0.x ≤ 8.0.1)
Where this breaks in practice:
  • Patched versions (8.0.2+, 7.6.5+, etc.) return HTTP 403, stopping the chain dead
Detection/coverage: WAF/IDS rules keyed on %3f/../ or cgi-bin/fwbcgi in the URI path. Tenable Web App Scanning plugin 115040. Qualys QID pending. FortiWeb access logs show the traversal path in the request URI.
STEP 03

Forge cgi_auth() identity via HTTP_CGIINFO header

With access to fwbcgi, the attacker supplies a Base64-encoded JSON blob in the HTTP_CGIINFO header. This JSON contains fields like username, profname, vdom, and loginname, effectively impersonating the built-in admin user. The cgi_auth() function inside fwbcgi parses and trusts this header without verifying it came through the authenticated session manager, granting full admin-level API access to the attacker.
Conditions required:
  • Access to fwbcgi via the path traversal in step 2
Where this breaks in practice:
  • None — this is an inherent design flaw in how fwbcgi validates caller identity
Detection/coverage: Deep packet inspection on the HTTP_CGIINFO header containing Base64-encoded admin credentials. watchTowr released YARA/Sigma detection artefact generators on GitHub.
STEP 04

Create rogue administrator account

The attacker sends a JSON payload to the admin-creation endpoint with prof_admin profile, 0.0.0.0/0 trusted-host access, and an attacker-controlled password. The new admin account is persistent across reboots and provides full GUI and CLI access to the FortiWeb appliance. Multiple threat actors have been observed creating accounts with randomized usernames for stealth.
Conditions required:
  • Successful cgi_auth() bypass from step 3
Where this breaks in practice:
  • None once step 3 succeeds — the API accepts the creation request without further challenge
Detection/coverage: Monitor FortiWeb admin account list for unexpected entries. SIEM alert on system admin creation events in FortiWeb logs. Config diff monitoring via FortiManager.
STEP 05

Weaponize full admin access for lateral movement or data interception

With a legitimate admin account, the attacker can: disable WAF policies to expose backend applications; exfiltrate TLS private keys and certificates for traffic decryption; harvest credentials from LDAP/RADIUS integration configs; pivot into internal networks through the FortiWeb's network interfaces; deploy persistent backdoors via CLI scripts; or sell the access to ransomware operators. The k0t access broker campaign has been observed doing exactly this — harvesting 70,000+ credentials from FortiWeb and similar appliances and selling them to Qilin and Inc ransomware groups.
Conditions required:
  • Rogue admin account from step 4
Where this breaks in practice:
  • Network segmentation behind the WAF may limit lateral movement scope — but the WAF itself is a high-value pivot point
Detection/coverage: Anomalous admin logins from unexpected source IPs. FortiAnalyzer/FortiSIEM correlation rules for new admin activity. Network traffic anomalies from WAF management interfaces to internal hosts.
03 · Compensating Control

1
CRITICAL 9.8→LOW 3.1
SEVERITY REDUCED
Restrict FortiWeb management interface to out-of-band or management-only VLANs immediately — The exploit targets the management-plane API, not the data-plane WAF proxy. If the management interface is unreachable from the internet, the unauthenticated attack path is completely severed. Deploy ACLs or firewall rules to limit management access to trusted admin IPs/jumpboxes only. Per the noisgate mitigation SLA for CRITICAL, deploy within 3 days — but given active exploitation and KEV status, implement within hours.
2
CRITICAL 9.8→IGNORE 0.0
SEVERITY REDUCED
Apply vendor patch (upgrade to 7.0.12+, 7.2.12+, 7.4.10+, 7.6.5+, or 8.0.2+) — The definitive fix. Patched versions reject the traversal with HTTP 403. Per the noisgate remediation SLA for CRITICAL, patch within 90 days — but given KEV listing with a 7-day CISA deadline and active ransomware-affiliated exploitation, patch within days, not weeks. Schedule emergency maintenance windows.
3
CRITICAL 9.8→HIGH 7.5
SEVERITY REDUCED
Audit FortiWeb admin accounts and rotate all credentials — Because exploitation has been occurring since October 2025, any internet-exposed FortiWeb may already have rogue admin accounts. Immediately enumerate all admin accounts (get system admin), remove any unrecognized entries, rotate passwords for all legitimate admins, and rotate any LDAP/RADIUS service account credentials configured on the appliance. Check for modified WAF policies or certificate exports.
4
CRITICAL 9.8→CRITICAL 9.0
Deploy IDS/WAF signatures for the traversal pattern — Create or enable signatures matching %3f/../ or %3F/../ followed by cgi-bin/fwbcgi in the URI path. GreyNoise and CrowdSec community blocklists cover known scanner IPs. This provides detection-in-depth but does NOT prevent exploitation if management is exposed — treat as a detection layer, not a blocking control.
5
CRITICAL 9.8→CRITICAL 9.5
Enable FortiWeb config-change alerting via FortiManager or syslog — Configure real-time alerts for admin account creation, policy modification, and certificate export events. Forward FortiWeb logs to your SIEM with correlation rules for anomalous admin activity. This catches post-exploitation indicators but does not prevent initial compromise.
What doesn't work
  • Data-plane WAF rules on the FortiWeb itself — the exploit targets the management plane, not traffic flowing through the WAF proxy. A WAF rule on the device cannot protect against attacks on its own management API unless explicitly configured as a reverse proxy for its own management (which is not a supported or recommended configuration).
  • FortiWeb trusted-host restrictions on existing admin accounts — the exploit *creates new* admin accounts with 0.0.0.0/0 trusted-host scope, bypassing any restrictions on pre-existing accounts.
  • MFA/FortiToken on existing admin accounts — the path traversal bypasses the authentication layer entirely; MFA is never invoked because the attacker never goes through the login flow.
  • SSL VPN or ZTNA in front of other services — these do not protect the FortiWeb management plane unless the management interface itself is placed behind them, which is architecturally unusual.
04 · Intelligence Metadata

The supporting signals.

In-the-Wild ExploitationConfirmed and widespread. First observed October 6, 2025 by Defused via honeypot captures — over five weeks before formal CVE assignment. GreyNoise documented 8 scanning IPs within 72 hours of public PoC, growing to 8,163 unique source IPs across 1,071 ASNs in 101 countries by January 7, 2026. Initial-access broker k0t actively exploits this CVE alongside CVE-2026-0257 to harvest credentials sold to Qilin and Inc ransomware groups.
CISA KEV StatusListed. Added November 14, 2025. Due date: November 21, 2025 (7-day remediation window — the shortest CISA issues). CISA KEV entry
EPSS Score0.91965 (≈92nd percentile) — indicating near-certainty of exploitation activity, consistent with observed in-the-wild status
Proof-of-Concept AvailabilityWeaponized and public. watchTowr Labs published full PoC on November 13, 2025. Metasploit module admin/http/fortinet_fortiweb_create_admin (PR #20717 by sfewer-r7) ships turnkey exploitation. GitHub repos: verylazytech/CVE-2025-64446, fevar54/CVE-2025-64446-PoC. Warning: ChocoPoC malware distributed via trojanized PoC repos for this CVE — vet sources carefully.
CVSS VectorCVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H (9.8) — Network-reachable, zero complexity, no privileges, no user interaction. All three CIA impacts are High. Scope is Unchanged but that's academic since the target is itself a perimeter trust boundary.
Affected VersionsFortiWeb 7.0.0–7.0.11, 7.2.0–7.2.11, 7.4.0–7.4.9, 7.6.0–7.6.4, 8.0.0–8.0.1
Fixed VersionsFortiWeb 7.0.12+, 7.2.12+, 7.4.10+, 7.6.5+, 8.0.2+ — patched versions reject traversal with HTTP 403
Internet ExposureCensys: ~20,098 FortiWeb instances online. Shodan: ~300–700 after honeypot filtering. FOFA: ~2,700. GreyNoise confirmed scanning across ports 443, 8443, 8080, 9443, 10443.
Vendor AdvisoryFortinet PSIRT FG-IR-25-910, published November 14, 2025. Canadian Cyber Centre issued AL25-017.
DiscoveryInitially spotted by Defused (honeypot operator) via X post on October 6, 2025. Independently confirmed and PoC'd by watchTowr Labs on November 13, 2025. Rapid7 verified and contributed Metasploit module (sfewer-r7).

Sources.

  1. CISA KEV Catalog Entry
  2. Tenable — FortiWeb Zero-Day Path Traversal Analysis
  3. GreyNoise — FortiWeb CVE-2025-64446 Exploitation Telemetry
  4. Arctic Wolf — FortiWeb Path Traversal Admin Account Creation
  5. Rapid7 Metasploit Module PR #20717
  6. Safeguard — k0t Access Broker Campaign (70K Credentials)
  7. Canadian Cyber Centre Advisory AL25-017
  8. CISA FortiWeb Advisory
05 · The Call

Final Verdict
= UNCHANGED to CRITICAL (9.8/10)

Why this verdict

  • Zero friction in the attack chain: The exploit is unauthenticated, requires no user interaction, has trivial complexity (a single HTTP POST), and targets a management interface that on thousands of deployments is directly internet-facing. Every prerequisite is met by default on an exposed FortiWeb.
  • Role multiplier — canonical network edge appliance: FortiWeb is a Web Application Firewall deployed at the network perimeter *by design*. This is not a workstation or internal-only service. 100% of FortiWeb installations occupy the 'network edge appliance' high-value role. Compromise yields: TLS private key exfiltration (fleet-scale traffic decryption), WAF policy disablement (exposing all protected backend applications), LDAP/RADIUS credential harvesting, and direct network pivot into internal infrastructure. Blast radius is tenant-to-fleet scale depending on what sits behind the WAF.
  • Confirmed ransomware supply chain: The k0t initial-access broker campaign has weaponized this CVE at scale, harvesting 70,000+ credentials and selling access to Qilin and Inc ransomware affiliates. This isn't theoretical — the exploit-to-ransomware pipeline is documented and operational.
  • Exploitation maturity is maximal: Metasploit module ships turnkey, multiple public PoCs circulate, 8,163+ unique IPs scanned for this bug across 101 countries, and exploitation predates disclosure by over five weeks (true zero-day exploitation).
  • EPSS 0.92 and KEV-listed with 7-day remediation deadline — both the probabilistic model and CISA's operational judgment agree this is top-tier urgency.

Why not higher?

The CVSS 9.8 is already near-ceiling. The only theoretical path to 10.0 would require Scope: Changed (S:C), but while compromising a WAF has devastating downstream effects, the CVSS definition of scope change requires a formally different security authority — the FortiWeb appliance itself is the authorization scope. The 9.8 with unchanged scope is technically correct; operational impact arguably exceeds it but CVSS has no mechanism to express that.

Why not lower?

Every downgrade lever is absent. There are zero authentication requirements, zero complexity barriers, zero user interaction dependencies. The target is internet-facing by design — this is not a case where 'requires internal network access' provides friction. The product is canonically a high-value network edge component (100% of installs are perimeter security appliances), the floor is CRITICAL. Active exploitation by ransomware-affiliated access brokers with a Metasploit module and 8,000+ scanning IPs eliminates any theoretical argument for latent or unlikely exploitation. Downgrading below CRITICAL would require evidence that FortiWeb is never deployed at the perimeter, which contradicts its entire product purpose.

06 · Verification

Crowdsourced verification payload.

Run from any auditor workstation with curl and bash against the target FortiWeb management IP/hostname. No authentication required. Usage: bash check_cve_2025_64446.sh <fortiweb-host> [port] (default port 443). The script first attempts version detection, then falls back to a non-destructive traversal canary (GET, not POST — does not create accounts). Exit codes: 0=PATCHED, 1=VULNERABLE, 2=UNKNOWN.

noisgate-verify.sh
BASHREAD-ONLYSAFE
#!/usr/bin/env bash
# CVE-2025-64446 FortiWeb Vulnerability Check
# Usage: bash check_cve_2025_64446.sh <host> [port]
# Exit: 0=PATCHED, 1=VULNERABLE, 2=UNKNOWN
set -uo pipefail

HOST="${1:?Usage: $0 <fortiweb-host> [port]}"
PORT="${2:-443}"
BASE="https://${HOST}:${PORT}"

echo "[*] CVE-2025-64446 check against ${BASE}"

# Step 1: Try to detect FortiWeb version from login page
VERSION=""
LOGIN_RESP=$(curl -sk --max-time 10 "${BASE}/" 2>/dev/null || true)
if echo "$LOGIN_RESP" | grep -qi 'FortiWeb'; then
    VERSION=$(echo "$LOGIN_RESP" | grep -oiP '(?:FortiWeb|FWB)[^0-9]*\K[0-9]+\.[0-9]+\.[0-9]+' | head -1)
fi

# Step 2: Try status API (some configs leak version)
if [ -z "$VERSION" ]; then
    STATUS_RESP=$(curl -sk --max-time 10 "${BASE}/api/v2.0/system/status" 2>/dev/null || true)
    VERSION=$(echo "$STATUS_RESP" | grep -oP '"version"\s*:\s*"\K[0-9]+\.[0-9]+\.[0-9]+' | head -1)
fi

# Step 3: Non-destructive traversal canary (GET only — will NOT create accounts)
CANARY_CODE=$(curl -sk -o /dev/null -w "%{http_code}" --max-time 10 \
    -X GET "${BASE}/api/v2.0/cmdb/system/admin%3f/../../../../../cgi-bin/fwbcgi" \
    2>/dev/null || echo "000")

if [ -z "$VERSION" ] && [ "$CANARY_CODE" = "000" ]; then
    echo "[?] UNKNOWN - Cannot reach ${BASE} or identify as FortiWeb."
    exit 2
fi

echo "[*] Detected version: ${VERSION:-<undetermined>}"
echo "[*] Traversal canary HTTP status: ${CANARY_CODE}"

# Evaluate version if found
if [ -n "$VERSION" ]; then
    MAJOR=$(echo "$VERSION" | cut -d. -f1)
    MINOR=$(echo "$VERSION" | cut -d. -f2)
    PATCH=$(echo "$VERSION" | cut -d. -f3)
    VULN=0
    case "${MAJOR}.${MINOR}" in
        7.0) [ "${PATCH:-0}" -le 11 ] 2>/dev/null && VULN=1 ;;
        7.2) [ "${PATCH:-0}" -le 11 ] 2>/dev/null && VULN=1 ;;
        7.4) [ "${PATCH:-0}" -le 9 ]  2>/dev/null && VULN=1 ;;
        7.6) [ "${PATCH:-0}" -le 4 ]  2>/dev/null && VULN=1 ;;
        8.0) [ "${PATCH:-0}" -le 1 ]  2>/dev/null && VULN=1 ;;
    esac
    if [ "$VULN" -eq 1 ]; then
        echo "[!] VULNERABLE - FortiWeb ${VERSION} is in the affected range."
        echo "[!] Upgrade to 7.0.12+ / 7.2.12+ / 7.4.10+ / 7.6.5+ / 8.0.2+"
        exit 1
    else
        echo "[+] PATCHED - FortiWeb ${VERSION} is outside the affected range."
        exit 0
    fi
fi

# Fallback: interpret canary response
if [ "$CANARY_CODE" = "403" ]; then
    echo "[+] PATCHED - Traversal canary returned 403 Forbidden (patched behavior)."
    exit 0
elif [ "$CANARY_CODE" = "200" ] || [ "$CANARY_CODE" = "302" ]; then
    echo "[!] VULNERABLE - Traversal canary returned ${CANARY_CODE} (unpatched behavior)."
    exit 1
else
    echo "[?] UNKNOWN - Canary returned HTTP ${CANARY_CODE}. Manual verification required."
    exit 2
fi