
Toolkit di rilevamento per CVE-2026-35616, un bypass API pre-autenticazione in FortiClient EMS. Include uno scanner Python e uno script Nmap NSE per identificare le versioni vulnerabili e fornire indicazioni di rimedio.
Un bypass critico dell'autenticazione in Fortinet FortiClient EMS 7.4.5 e 7.4.6 consente a un attaccante remoto completamente non autenticato di aggirare l'autenticazione API falsificando un singolo header HTTP (X-SSL-CLIENT-VERIFY). Il difetto esiste perché il middleware Django si fida dei metadati dei certificati client provenienti da header controllati dall'utente, non solo dal proxy inverso affidabile. Questo dà agli attaccanti pieno accesso amministrativo alle API - e da lì, esecuzione arbitraria di codice sugli endpoint gestiti in tutta l'azienda.
Sfruttato attivamente dal 31 marzo 2026. Aggiunto al catalogo KEV CISA il 6 aprile 2026.
| Campo | Dettaglio |
|---|---|
| ID CVE | CVE-2026-35616 |
| Vendor | Fortinet |
| Prodotto | FortiClient Enterprise Management Server (EMS) |
| Versioni interessate | 7.4.5, 7.4.6 |
| Non interessate | ramo 7.2.x, 7.4.4 e precedenti |
| CVSS v3.1 | 9.1 (Critico) |
| CWE | CWE-284 - Controllo degli accessi improprio |
| Vettore di attacco | Rete |
| Autenticazione | Nessuna richiesta |
| Interazione utente | Nessuna |
| Maturità dello sfruttamento | Sfruttato in natura |
| CISA KEV | Aggiunto il 6 aprile 2026 (scadenza: 9 aprile 2026) |
| Patch | Hotfix disponibile; correzione completa in 7.4.7 |
| Crediti | Simo Kohonen (Defused Cyber), Nguyen Duc Anh |
FortiClient Enterprise Management Server (EMS) è la piattaforma centralizzata di gestione degli endpoint di Fortinet. Funge da livello di comando e controllo per distribuire, configurare e monitorare gli agenti FortiClient in un'organizzazione. Pensalo come il cervello che governa ogni endpoint in un ambiente gestito da Fortinet:
Quando un attaccante ottiene accesso amministrativo a EMS, possiede di fatto le chiavi di ogni endpoint gestito nell'organizzazione.
FortiClient EMS utilizza uno stack applicativo web abbastanza standard dietro le quinte:
+----------------+ +----------------+ +----------------+
| Browser / | HTTPS | Apache | WSGI | Django |
| API Client | -------> | (mod_ssl) | -------> | Backend |
+----------------+ +----------------+ +----------------+
Quando è configurato il TLS reciproco (mTLS), il mod_ssl di Apache gestisce la verifica del certificato client. Dopo aver validato il certificato, Apache passa il risultato della verifica a Django tramite variabili d'ambiente WSGI affidabili:
SSL_CLIENT_VERIFY - Lo stato della verifica (SUCCESS, NONE, FAILED)SSL_CLIENT_S_DN - Il Distinguished Name del soggetto dal certificatoSSL_CLIENT_SERIAL - Il numero di serie del certificatoQuesto è il pattern standard e sicuro. Il problema sta in come il middleware Django legge questi dati.
In FortiClient EMS 7.4.5 e 7.4.6, il middleware di autenticazione Django è stato modificato per accettare anche queste stesse informazioni da header delle richieste HTTP:
X-SSL-CLIENT-VERIFYX-SSL-CLIENT-S-DNX-SSL-CLIENT-SERIALQuesto è stato probabilmente aggiunto per supportare distribuzioni con proxy inverso dove Apache non è il punto di terminazione TLS. Tuttavia, il middleware non distingue tra queste due fonti. Controlla prima le variabili WSGI, ma se sono assenti (nessun mTLS configurato, o una connessione diretta), ripiega sugli header HTTP - che qualsiasi client può impostare.
Ecco la suddivisione concettuale:
PERCORSO SICURO (previsto):
Apache mod_ssl valida il cert --> imposta variabili env WSGI --> Django legge le env vars [OK]
PERCORSO NON SICURO (la vulnerabilità):
L'attaccante imposta direttamente gli header HTTP --> Django legge gli header --> Si fida di essi [FAIL]
Il middleware di fatto si fida del client per auto-attestare il proprio stato di verifica del certificato. È come se un buttafuori chiedesse a qualcuno "Ehi, l'altro buttafuori ha già controllato il tuo documento?" e lo facesse entrare quando risponde "sì".
Passo 1: L'attaccante invia una richiesta POST a un endpoint API EMS
con questi header:
X-SSL-CLIENT-VERIFY: SUCCESS
X-SSL-CLIENT-S-DN: CN=admin
X-SSL-CLIENT-SERIAL: 0000000000000001
Passo 2: Il middleware Django controlla le variabili env WSGI → non presenti
Ripiega sugli header HTTP → trova X-SSL-CLIENT-VERIFY: SUCCESS
Passo 3: Il middleware tratta la richiesta come autenticata con identità admin
Passo 4: L'attaccante ha pieno accesso amministrativo alle API
Passo 5: Dall'API admin, l'attaccante può:
- Distribuire policy dannose a tutti gli endpoint gestiti
- Estrarre credenziali e certificati memorizzati
- Distribuire payload tramite la distribuzione software
- Modificare le configurazioni ZTNA
- Muoversi lateralmente nella rete più ampia
L'intero attacco richiede una singola richiesta HTTP. Nessun brute-forcing, nessun credential stuffing, nessuna ingegneria sociale. Solo un header falsificato.
La gravità qui va oltre il server stesso. FortiClient EMS è un moltiplicatore di forza - comprometterlo dà a un attaccante leva su ogni endpoint gestito:
Impatto immediato:
Impatto a valle (tramite gli endpoint gestiti):
Rischio aziendale:
| Versione | Stato |
|---|---|
| FortiClient EMS 7.4.6 | Vulnerabile |
| FortiClient EMS 7.4.5 | Vulnerabile |
| FortiClient EMS 7.4.4 e precedenti | Non interessata |
| FortiClient EMS 7.2.x | Non interessata |
| Data | Evento |
|---|---|
| ~Fine marzo 2026 | Vulnerabilità scoperta e segnalata da Simo Kohonen e Nguyen Duc Anh |
| 31 marzo 2026 | Primi tentativi di sfruttamento registrati contro honeypot (Defused Cyber) |
| 4 aprile 2026 | Fortinet rilascia hotfix di emergenza per 7.4.5 e 7.4.6 |
| 6 aprile 2026 | CISA aggiunge CVE-2026-35616 al catalogo KEV (scadenza: 9 aprile 2026) |
| 13 aprile 2026 | Pubblicazione di questo toolkit di rilevamento |
Lo script Python testa più endpoint API utilizzando una tecnica di risposta differenziale.
Come funziona:
HTTP 401 Unauthorized)X-SSL-CLIENT-VERIFY: SUCCESS iniettato401 a qualsiasi altro (tipicamente 500 o 200), il bypass dell'autenticazione è confermatoNon viene mai inviato alcun payload di sfruttamento. Il test è sicuro per la produzione.
Utilizzo:
# Installare le dipendenze (per questo script serve solo la stdlib)
pip install -r requirements.txt
# Singolo target
python CVE-2026-35616_FortiClientEMS_detector.py -t 192.168.1.100
# Porta personalizzata
python CVE-2026-35616_FortiClientEMS_detector.py -t ems.corp.local -p 8443
# Scansione di massa da file
python CVE-2026-35616_FortiClientEMS_detector.py -f targets.txt
# Output JSON salvato su file
python CVE-2026-35616_FortiClientEMS_detector.py -t 192.168.1.100 --json -o results.json
# Con verifica del certificato SSL abilitata
python CVE-2026-35616_FortiClientEMS_detector.py -t 192.168.1.100 --verify-ssl
# Timeout aumentato per reti lente
python CVE-2026-35616_FortiClientEMS_detector.py -t 192.168.1.100 --timeout 20
Opzioni:
| Flag | Descrizione | Default |
|---|---|---|
-t, --target | IP o hostname del target | - |
-f, --file | File con i target, uno per riga (le righe che iniziano con # vengono saltate) | - |
-p, --port | Porta del target | 443 |
--timeout | Timeout di connessione in secondi | 10 |
--verify-ssl | Abilita la verifica del certificato SSL | Disabilitata |
--json | Output dei risultati in formato JSON | Off |
-o, --output | Salva i risultati su un file | - |
Esempio di output:
╔══════════════════════════════════════════════════════════════╗
║ CVE-2026-35616 - Rilevatore Bypass Auth FortiClient EMS ║
║ Bypass Accesso API Pre-Autenticazione → Escalation Privilegi║
║ CVSS: 9.1 (Critico) | CISA KEV: Sfruttamento attivo ║
╚══════════════════════════════════════════════════════════════╝
[*] Scansione di 192.168.1.100:443...
Target: 192.168.1.100:443
============================================================
[*] FortiClient EMS rilevato (Versione: Sconosciuta)
Risultati del test di vulnerabilità:
[VULNERABILE] /api/v1/auth/signin Base: 401 → Falsificato: 500
[VULNERABILE] /api/v1/system/status Base: 401 → Falsificato: 500
[NON VULN] /api/v1/endpoints Base: 401 → Falsificato: 401
[!] IL TARGET È PROBABILMENTE VULNERABILE A CVE-2026-35616
Bypass API pre-autenticazione confermato. Applicare subito l'hotfix!
Rimedio: Aggiornare a FortiClient EMS 7.4.7 o applicare l'hotfix
# Installare lo script NSE
sudo cp CVE-2026-35616_FortiClientEMS.nse /usr/share/nmap/scripts/
sudo nmap --script-updatedb
# Scansione di base
nmap -p 443 --script CVE-2026-35616_FortiClientEMS <target>
# Scansione di una sottorete
nmap -p 443 --script CVE-2026-35616_FortiClientEMS 10.0.0.0/24
# Scansione di più target da un file
nmap -p 443 --script CVE-2026-35616_FortiClientEMS -iL targets.txt
# Con rilevamento della versione del servizio
nmap -sV -p 443 --script CVE-2026-35616_FortiClientEMS <target>
Esempio di output Nmap:
PORT STATE SERVICE
443/tcp open https
| CVE-2026-35616_FortiClientEMS:
| VULNERABLE:
| Bypass API Pre-Autenticazione FortiClient EMS
| State: VULNERABLE
| IDs: CVE:CVE-2026-35616
| Fattore di rischio: Critico (CVSS: 9.1)
| Data di divulgazione: 2026-04-04
| Informazioni aggiuntive:
| Endpoint interessati: 2
| Rimedio: Applicare l'hotfix per FortiClient EMS 7.4.5/7.4.6 o aggiornare a 7.4.7
| Scadenza CISA KEV: 9 aprile 2026
| Riferimenti:
| https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2026-35616
|_ https://www.cisa.gov/known-exploited-vulnerabilities-catalog
Se vuoi confermare manualmente con curl:
# Passo 1: Base - dovrebbe restituire 401
curl -sk -X POST https://<TARGET>:443/api/v1/auth/signin \
-H "Content-Type: application/json" \
-d '{}' \
-o /dev/null -w "%{http_code}\n"
# Passo 2: Falsificato - se restituisce qualcosa di diverso da 401, probabilmente vulnerabile
curl -sk -X POST https://<TARGET>:443/api/v1/auth/signin \
-H "Content-Type: application/json" \
-H "X-SSL-CLIENT-VERIFY: SUCCESS" \
-H "X-SSL-CLIENT-S-DN: CN=admin" \
-H "X-SSL-CLIENT-SERIAL: 0000000000000001" \
-d '{}' \
-o /dev/null -w "%{http_code}\n"
Se il primo restituisce 401 e il secondo restituisce 500 o 200, l'istanza è vulnerabile.
Cerca questi segnali nel tuo ambiente:
X-SSL-CLIENT-VERIFY da fonti non proxyFonti di log da esaminare:
Azioni immediate (fai queste ora):
A breve termine (questa settimana):
A lungo termine:
X-SSL-CLIENT-VERIFY, X-SSL-CLIENT-S-DN e X-SSL-CLIENT-SERIAL dalle richieste in ingresso al perimetro di reteKerem Oruç - Ingegnere della Cybersecurity