Skip to content

BishopFox/CVE-2026-35616-check

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

1 Commit
 
 
 
 
 
 

Repository files navigation

CVE-2026-35616 Vulnerability Assessment Tool

Safely detect whether a FortiClient EMS server is vulnerable to CVE-2026-35616 without causing any disruption. See the full write-up on the Bishop Fox blog.

Description

CVE-2026-35616 is a pre-authentication API bypass in FortiClient EMS 7.4.5 and 7.4.6 that allows remote, unauthenticated attackers to bypass certificate-based authentication through HTTP header spoofing. The Django application trusts user-controllable HTTP headers (X-SSL-CLIENT-VERIFY, X-SSL-CLIENT-CERT) as equivalent to Apache mod_ssl WSGI environment variables, and the Apache configuration never strips them. Combined with certificate chain validation that performs only Distinguished Name string matching (no cryptographic signature verification), an attacker can forge certificates and gain authenticated API access. Fortinet has confirmed exploitation in the wild.

This tool performs non-destructive vulnerability testing by:

  1. Sending a baseline POST to /api/v1/fabric_device_auth/fortigate/init with no spoofed headers
  2. Sending the same POST with X-SSL-CLIENT-VERIFY: SUCCESS but no certificate data
  3. Comparing the two responses to determine if the header reached Django

Sending the verify header with no certificate PEM data triggers the detection path but cannot authenticate because no certificate chain is provided. The server remains stable and can continue handling connections.

  • Vulnerable servers will return different responses: the baseline returns HTTP 401 ("Certificate not found in request header") while the spoofed request returns HTTP 500 (server error), because contains_certificate() passes the gate but validate_cert_chain() crashes on missing PEM data.
  • Patched servers will return identical HTTP 401 responses for both requests, because the hotfix adds Apache RequestHeader unset directives that strip the spoofed header before it reaches Django.
  • Non-EMS servers will fail to reach the endpoint, in which case the tool reports an INCONCLUSIVE result.

Installation

git clone https://github.com/BishopFox/CVE-2026-35616-check
cd CVE-2026-35616-check

No external dependencies. The scanner uses only Python standard library modules.

Usage

Test a FortiClient EMS server at <TARGET>:<PORT>. The default port is 443/TCP.

python3 CVE-2026-35616-check.py <TARGET> [PORT]

Example: Vulnerable Server

$ python3 CVE-2026-35616-check.py 192.168.1.1
======================================================================
FortiClient EMS CVE-2026-35616 Vulnerability Scanner
Non-Destructive Detection
======================================================================

[*] Target: 192.168.1.1:443
[*] Testing for CVE-2026-35616 (non-destructive)

[1] Sending baseline POST (no spoof headers)... HTTP 401
[2] Sending POST with X-SSL-CLIENT-VERIFY: SUCCESS... HTTP 500

[*] Analyzing responses...
[+] Baseline: 401Certificate not found in request header.
[+] Spoofed:  500Server encountered an error, please try again later.
[!] Spoofed header changed server behavior
[!] X-SSL-CLIENT-VERIFY is reaching Django (hotfix not applied)

======================================================================
RESULT: VULNERABLE to CVE-2026-35616
Affected versions: FortiClient EMS 7.4.5 - 7.4.6
Recommendation: Apply Fortinet hotfix or upgrade to 7.4.7+
======================================================================

Example: Patched Server

$ python3 CVE-2026-35616-check.py 192.168.1.1
======================================================================
FortiClient EMS CVE-2026-35616 Vulnerability Scanner
Non-Destructive Detection
======================================================================

[*] Target: 192.168.1.1:443
[*] Testing for CVE-2026-35616 (non-destructive)

[1] Sending baseline POST (no spoof headers)... HTTP 401
[2] Sending POST with X-SSL-CLIENT-VERIFY: SUCCESS... HTTP 401

[*] Analyzing responses...
[+] Baseline: 401Certificate not found in request header.
[+] Spoofed:  401Certificate not found in request header.
[-] Responses identical (header stripped by Apache)

======================================================================
RESULT: NOT VULNERABLE (hotfix applied)
Apache is stripping X-SSL-CLIENT-VERIFY before it reaches Django
======================================================================

Preconditions

The tool can only detect the vulnerability if the following conditions are met:

  • The target is running FortiClient EMS 7.4.5 or 7.4.6
  • The EMS web interface is accessible
  • The /api/v1/fabric_device_auth/fortigate/init endpoint exists and uses cert_chain_approved authentication

If any condition isn't met, the tool will report an INCONCLUSIVE result.

License

This code is distributed under an MIT license.

Legal Disclaimer

Usage of this tool for attacking targets without prior mutual consent is illegal. It is the end user's responsibility to obey all applicable local, state, and federal laws. Developers assume no liability and are not responsible for any misuse or damage caused by this program.

See Also

About

No description, website, or topics provided.

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Languages