All posts

CVE-2026-35616: FortiClient EMS Auth Bypass

A textbook trusted-proxy header spoofing vulnerability in Fortinet's endpoint management control plane — pre-authentication API access leading to privilege escalation and command execution, added to CISA KEV within days of disclosure.


CVECVE-2026-35616
CVSS9.1 Critical
CWECWE-284 Improper Access Control
AffectedFortiClient EMS 7.4.5 – 7.4.6
StatusCISA KEV — patch by 2026-04-09

Overview

Fortinet published an out-of-band advisory for CVE-2026-35616 in early April 2026, disclosing a pre-authentication API access bypass in FortiClient EMS — the centralised management plane for Fortinet's endpoint security product. With a CVSS score of 9.1, the flaw allows an unauthenticated attacker to circumvent all API authentication and authorisation controls, ultimately executing commands on the server.

CISA added this CVE to its Known Exploited Vulnerabilities (KEV) catalog on 6 April 2026, mandating remediation by Federal Civilian Executive Branch agencies within 72 hours — a timeline that signals confirmed, in-the-wild exploitation with real operational risk.

What is FortiClient EMS?

FortiClient EMS is the control plane for all FortiClient-connected endpoints. It manages endpoint policy enforcement, remote access configuration, telemetry collection, and ongoing administration of every managed device in a Fortinet-secured environment. A compromise here is not a single-host compromise — it is a compromise of the entire endpoint management infrastructure.

Root Cause: Trusted-Proxy Header Spoofing

The vulnerability stems from a mismatch in trust assumptions between the Apache reverse proxy layer and the Django application backend. FortiClient EMS uses mutual TLS client certificate authentication routed through Apache. Apache validates the certificate and then communicates the result to Django via HTTP headers — specifically X-SSL-CLIENT-VERIFY and X-SSL-CLIENT-CERT.

The critical flaw: Apache was never configured to strip these headers from inbound external requests. An attacker could therefore inject arbitrary values for X-SSL-CLIENT-VERIFY and X-SSL-CLIENT-CERT directly in their HTTP request, and Django would accept them as authentic signals from the proxy layer.

A request like the following, sent directly to the exposed API, would bypass all client certificate enforcement:

POST /api/v1/some/protected/endpoint HTTP/1.1
Host: forticlient-ems.target.corp
X-SSL-CLIENT-VERIFY: SUCCESS
X-SSL-CLIENT-CERT: [any plausible certificate DN string]
Content-Type: application/json

{"action": "execute", "command": "..."}

The second compounding weakness: certificate chain validation in the Django application performed no cryptographic verification. Knowledge of the Fortinet root CA's Distinguished Name (DN) strings was sufficient to forge a passing certificate chain — achievable with standard openssl commands.

Why This Pattern is Common

Reverse-proxy header spoofing is a well-documented vulnerability class, yet it continues to appear in enterprise products for a predictable reason: developers test the application in integrated environments where the proxy correctly strips headers, and the two components are never security-tested in isolation. The assumption that "the proxy handles it" is rarely documented or enforced at the application layer.

Impact

A successful exploit gives an unauthenticated remote attacker:

First exploitation attempts were observed on 31 March 2026. The gap between initial exploitation and CISA's KEV listing (6 April) was under a week.

Affected Versions

The full code-level fix ships in 7.4.7. Fortinet also released a hotfix for existing deployments.

Remediation

  1. Upgrade to FortiClient EMS 7.4.7 as soon as it is available in your maintenance window — this is the definitive fix.
  2. Apply Fortinet's hotfix immediately if you cannot upgrade: the hotfix adds RequestHeader unset directives to Apache configuration, stripping X-SSL-CLIENT-VERIFY and X-SSL-CLIENT-CERT from all externally-originating requests before they reach Django.
  3. Restrict network access to the EMS management API to trusted internal network ranges only — it should never be directly internet-facing.
  4. Review API access logs for requests containing X-SSL-CLIENT-VERIFY: SUCCESS from unexpected source IPs.
  5. Audit all endpoint policies for unexpected changes or new entries pushed after 31 March 2026.

Detection Guidance

Look for the following in Apache access logs on the EMS server:

Takeaways

Two design principles would have prevented this vulnerability entirely: never trust client-supplied headers that convey security decisions, and always validate at the application layer regardless of what the proxy tier claims. Proxy-to-backend trust must be enforced bidirectionally — strip untrusted headers at ingress, and verify authenticity cryptographically at the application, not just in the proxy.

For defenders, this case reinforces the importance of treating network security product management planes with the same — arguably greater — scrutiny as the endpoints they manage. A compromised EMS is a compromised fleet.

References