
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):