# Kit de détection pour CVE-2026-35616 Kit de détection pour CVE-2026-35616, un contournement d'API pré-authentification dans FortiClient EMS. Comprend un scanner Python et un script Nmap NSE pour identifier les versions vulnérables et fournir des recommandations de remédiation.
Un contournement d'authentification critique dans Fortinet FortiClient EMS 7.4.5 et 7.4.6 permet à un attaquant distant totalement non authentifié de contourner l'authentification API en usurpant un seul en-tête HTTP (X-SSL-CLIENT-VERIFY). La faille existe parce que le middleware Django fait confiance aux métadonnées de certificat client provenant d'en-têtes contrôlés par l'utilisateur, et pas uniquement au proxy inverse de confiance. Cela donne aux attaquants un accès API administratif complet - et à partir de là, une exécution de code arbitraire sur les points de terminaison gérés à travers l'entreprise.
Exploité activement depuis le 31 mars 2026. Ajouté au catalogue KEV de la CISA le 6 avril 2026.
| Champ | Détail |
|---|---|
| ID CVE | CVE-2026-35616 |
| Fournisseur | Fortinet |
| Produit | FortiClient Enterprise Management Server (EMS) |
| Versions affectées | 7.4.5, 7.4.6 |
| Non affecté | Branche 7.2.x, 7.4.4 et antérieures |
| CVSS v3.1 | 9.1 (Critique) |
| CWE | CWE-284 - Contrôle d'accès inapproprié |
| Vecteur d'attaque | Réseau |
| Authentification | Aucune requise |
| Interaction utilisateur | Aucune |
| Maturité de l'exploit | Exploité dans la nature |
| CISA KEV | Ajouté le 6 avril 2026 (échéance : 9 avril 2026) |
| Correctif | Correctif d'urgence disponible ; correctif complet dans 7.4.7 |
| Crédité à | Simo Kohonen (Defused Cyber), Nguyen Duc Anh |
FortiClient Enterprise Management Server (EMS) est la plateforme centralisée de gestion des points de terminaison de Fortinet. Elle sert de couche de commande et de contrôle pour déployer, configurer et surveiller les agents FortiClient dans une organisation. Considérez-la comme le cerveau qui gouverne chaque point de terminaison dans un environnement géré par Fortinet :
Lorsqu'un attaquant obtient un accès administratif à EMS, il détient essentiellement les clés de chaque point de terminaison géré dans l'organisation.
FortiClient EMS utilise une pile d'applications web assez standard en arrière-plan :
+----------------+ +----------------+ +----------------+
| Navigateur / | HTTPS | Apache | WSGI | Django |
| Client API | -------> | (mod_ssl) | -------> | Backend |
+----------------+ +----------------+ +----------------+
Lorsque le TLS mutuel (mTLS) est configuré, le mod_ssl d'Apache gère la vérification du certificat client. Après avoir validé le certificat, Apache transmet le résultat de la vérification à Django via des variables d'environnement WSGI de confiance :
SSL_CLIENT_VERIFY - Le statut de vérification (SUCCESS, NONE, FAILED)SSL_CLIENT_S_DN - Le nom distinctif du sujet du certificatSSL_CLIENT_SERIAL - Le numéro de série du certificatC'est le modèle standard et sécurisé. Le problème réside dans la façon dont le middleware Django lit ces données.
Dans FortiClient EMS 7.4.5 et 7.4.6, le middleware d'authentification Django a été modifié pour également accepter ces mêmes informations à partir des en-têtes de requête HTTP :
X-SSL-CLIENT-VERIFYX-SSL-CLIENT-S-DNX-SSL-CLIENT-SERIALCela a probablement été ajouté pour prendre en charge les déploiements de proxy inverse où Apache n'est pas le point de terminaison TLS. Cependant, le middleware ne fait pas la distinction entre ces deux sources. Il vérifie d'abord les variables WSGI, mais si elles sont absentes (pas de mTLS configuré, ou connexion directe), il retombe sur les en-têtes HTTP - que n'importe quel client peut définir.
Voici la répartition conceptuelle :
CHEMIN SÉCURISÉ (prévu) :
Apache mod_ssl valide le certificat --> définit les variables d'env WSGI --> Django lit les variables d'env [OK]
CHEMIN NON SÉCURISÉ (la vulnérabilité) :
L'attaquant définit directement les en-têtes HTTP --> Django lit les en-têtes --> Leur fait confiance [ÉCHEC]
Le middleware fait effectivement confiance au client pour auto-attester son propre statut de vérification de certificat. C'est comme si un videur demandait à quelqu'un « Hé, est-ce que l'autre videur a déjà vérifié ta pièce d'identité ? » et le laissait entrer quand il répond « oui ».
Étape 1 : L'attaquant envoie une requête POST à un point de terminaison API EMS
avec ces en-têtes :
X-SSL-CLIENT-VERIFY: SUCCESS
X-SSL-CLIENT-S-DN: CN=admin
X-SSL-CLIENT-SERIAL: 0000000000000001
Étape 2 : Le middleware Django vérifie les variables d'env WSGI → absentes
Retombe sur les en-têtes HTTP → trouve X-SSL-CLIENT-VERIFY: SUCCESS
Étape 3 : Le middleware traite la requête comme authentifiée avec l'identité admin
Étape 4 : L'attaquant a un accès API administratif complet
Étape 5 : Depuis l'API admin, l'attaquant peut :
- Pousser des politiques malveillantes vers tous les points de terminaison gérés
- Extraire les identifiants et certificats stockés
- Déployer des charges utiles via la distribution logicielle
- Modifier les configurations ZTNA
- Pivoter vers le réseau plus large
L'attaque entière nécessite une seule requête HTTP. Pas de force brute, pas de bourrage d'identifiants, pas d'ingénierie sociale. Juste un en-tête falsifié.
La gravité ici va au-delà du serveur lui-même. FortiClient EMS est un multiplicateur de force - le compromettre donne à un attaquant un levier sur chaque point de terminaison géré :
Impact immédiat :
Impact en aval (via les points de terminaison gérés) :
Risque pour l'entreprise :
| Version | Statut |
|---|---|
| FortiClient EMS 7.4.6 | Vulnérable |
| FortiClient EMS 7.4.5 | Vulnérable |
| FortiClient EMS 7.4.4 et antérieures | Non affecté |
| FortiClient EMS 7.2.x | Non affecté |
| Date | Événement |
|---|---|
| ~Fin mars 2026 | Vulnérabilité découverte et signalée par Simo Kohonen et Nguyen Duc Anh |
| 31 mars 2026 | Premières tentatives d'exploitation enregistrées contre des honeypots (Defused Cyber) |
| 4 avril 2026 | Fortinet publie des correctifs d'urgence pour 7.4.5 et 7.4.6 |
| 6 avril 2026 | La CISA ajoute CVE-2026-35616 au catalogue KEV (échéance : 9 avril 2026) |
| 13 avril 2026 | Publication de cette boîte à outils de détection |
Le script Python teste plusieurs points de terminaison API en utilisant une technique de réponse différentielle.
Comment ça fonctionne :
HTTP 401 Unauthorized)X-SSL-CLIENT-VERIFY: SUCCESS injecté401 à autre chose (généralement 500 ou 200), le contournement d'authentification est confirméAucune charge utile d'exploitation n'est jamais envoyée. Le test est sûr pour la production.
Utilisation :
# Installer les dépendances (seule la bibliothèque standard est nécessaire pour ce script)
pip install -r requirements.txt
# Cible unique
python CVE-2026-35616_FortiClientEMS_detector.py -t 192.168.1.100
# Port personnalisé
python CVE-2026-35616_FortiClientEMS_detector.py -t ems.corp.local -p 8443
# Analyse en masse depuis un fichier
python CVE-2026-35616_FortiClientEMS_detector.py -f targets.txt
# Sortie JSON enregistrée dans un fichier
python CVE-2026-35616_FortiClientEMS_detector.py -t 192.168.1.100 --json -o results.json
# Avec vérification du certificat SSL activée
python CVE-2026-35616_FortiClientEMS_detector.py -t 192.168.1.100 --verify-ssl
# Délai d'attente augmenté pour les réseaux lents
python CVE-2026-35616_FortiClientEMS_detector.py -t 192.168.1.100 --timeout 20
Options :
| Option | Description | Défaut |
|---|---|---|
-t, --target | IP ou nom d'hôte cible | - |
-f, --file | Fichier avec les cibles, une par ligne (les lignes commençant par # sont ignorées) | - |
-p, --port | Port cible | 443 |
--timeout | Délai d'attente de connexion en secondes | 10 |
--verify-ssl | Activer la vérification du certificat SSL | Désactivé |
--json | Sortir les résultats au format JSON | Désactivé |
-o, --output | Enregistrer les résultats dans un fichier | - |
Exemple de sortie :
╔══════════════════════════════════════════════════════════════╗
║ CVE-2026-35616 - Détecteur de contournement d'auth FortiClient EMS ║
║ Contournement d'accès API pré-authentification → Élévation de privilèges║
║ CVSS : 9.1 (Critique) | CISA KEV : Exploitation active ║
╚══════════════════════════════════════════════════════════════╝
[*] Analyse de 192.168.1.100:443...
Cible : 192.168.1.100:443
============================================================
[*] FortiClient EMS détecté (Version : Inconnue)
Résultats des tests de vulnérabilité :
[VULNÉRABLE] /api/v1/auth/signin Référence : 401 → Usurpé : 500
[VULNÉRABLE] /api/v1/system/status Référence : 401 → Usurpé : 500
[NON VULN] /api/v1/endpoints Référence : 401 → Usurpé : 401
[!] LA CIBLE EST PROBABLEMENT VULNÉRABLE À CVE-2026-35616
Contournement API pré-authentification confirmé. Appliquez le correctif immédiatement !
Remédiation : Mettez à niveau vers FortiClient EMS 7.4.7 ou appliquez le correctif d'urgence
# Installer le script NSE
sudo cp CVE-2026-35616_FortiClientEMS.nse /usr/share/nmap/scripts/
sudo nmap --script-updatedb
# Analyse de base
nmap -p 443 --script CVE-2026-35616_FortiClientEMS <cible>
# Analyser un sous-réseau
nmap -p 443 --script CVE-2026-35616_FortiClientEMS 10.0.0.0/24
# Analyser plusieurs cibles depuis un fichier
nmap -p 443 --script CVE-2026-35616_FortiClientEMS -iL targets.txt
# Avec détection de version de service
nmap -sV -p 443 --script CVE-2026-35616_FortiClientEMS <cible>
Exemple de sortie Nmap :
PORT STATE SERVICE
443/tcp open https
| CVE-2026-35616_FortiClientEMS:
| VULNÉRABLE :
| Contournement d'API pré-authentification FortiClient EMS
| État : VULNÉRABLE
| ID : CVE:CVE-2026-35616
| Facteur de risque : Critique (CVSS : 9.1)
| Date de divulgation : 2026-04-04
| Informations supplémentaires :
| Points de terminaison affectés : 2
| Remédiation : Appliquez le correctif d'urgence pour FortiClient EMS 7.4.5/7.4.6 ou mettez à niveau vers 7.4.7
| Échéance CISA KEV : 9 avril 2026
| Références :
| https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2026-35616
|_ https://www.cisa.gov/known-exploited-vulnerabilities-catalog
Si vous souhaitez confirmer manuellement avec curl :
# Étape 1 : Référence - devrait renvoyer 401
curl -sk -X POST https://<CIBLE>:443/api/v1/auth/signin \
-H "Content-Type: application/json" \
-d '{}' \
-o /dev/null -w "%{http_code}\n"
# Étape 2 : Usurpé - si renvoie autre chose que 401, probablement vulnérable
curl -sk -X POST https://<CIBLE>: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"
Si la première renvoie 401 et la seconde renvoie 500 ou 200, l'instance est vulnérable.
Surveillez ces signes dans votre environnement :
X-SSL-CLIENT-VERIFY provenant de sources non-proxySources de journaux à examiner :
Actions immédiates (faites-les maintenant) :
À court terme (cette semaine) :
À long terme :
X-SSL-CLIENT-VERIFY, X-SSL-CLIENT-S-DN et X-SSL-CLIENT-SERIAL des requêtes entrantes à la périphérie du réseauKerem Oruç - Ingénieur en cybersécurité