
Kit de detecção para CVE-2026-35616, uma bypass de API pré-autenticação no FortiClient EMS. Inclui scanner em Python e script Nmap NSE para identificar versões vulneráveis e fornecer orientações de remediação.
Um bypass crítico de autenticação no Fortinet FortiClient EMS 7.4.5 e 7.4.6 permite que um atacante remoto completamente não autenticado contorne a autenticação da API falsificando um único cabeçalho HTTP (X-SSL-CLIENT-VERIFY). A falha existe porque o middleware Django confia em metadados de certificado de cliente provenientes de cabeçalhos controlados pelo usuário, e não apenas do proxy reverso confiável. Isso dá aos atacantes acesso administrativo completo à API - e, a partir daí, execução arbitrária de código em endpoints gerenciados em toda a empresa.
Explorado ativamente desde 31 de março de 2026. Adicionado ao CISA KEV em 6 de abril de 2026.
| Campo | Detalhe |
|---|---|
| ID CVE | CVE-2026-35616 |
| Fornecedor | Fortinet |
| Produto | FortiClient Enterprise Management Server (EMS) |
| Versões Afetadas | 7.4.5, 7.4.6 |
| Não Afetadas | Ramo 7.2.x, 7.4.4 e anteriores |
| CVSS v3.1 | 9.1 (Crítico) |
| CWE | CWE-284 - Controle de Acesso Impropriado |
| Vetor de Ataque | Rede |
| Autenticação | Nenhuma necessária |
| Interação do Usuário | Nenhuma |
| Maturidade da Exploração | Explorado ativamente |
| CISA KEV | Adicionado em 6 de abril de 2026 (prazo: 9 de abril de 2026) |
| Correção | Hotfix disponível; correção completa no 7.4.7 |
| Créditos | Simo Kohonen (Defused Cyber), Nguyen Duc Anh |
O FortiClient Enterprise Management Server (EMS) é a plataforma centralizada de gerenciamento de endpoints da Fortinet. Ele serve como a camada de comando e controle para implantar, configurar e monitorar agentes FortiClient em uma organização. Pense nele como o cérebro que governa cada endpoint em um ambiente gerenciado pela Fortinet:
Quando um atacante obtém acesso administrativo ao EMS, ele essencialmente possui as chaves de todos os endpoints gerenciados na organização.
O FortiClient EMS usa uma pilha de aplicação web bastante padrão nos bastidores:
+----------------+ +----------------+ +----------------+
| Browser / | HTTPS | Apache | WSGI | Django |
| API Client | -------> | (mod_ssl) | -------> | Backend |
+----------------+ +----------------+ +----------------+
Quando o TLS mútuo (mTLS) está configurado, o mod_ssl do Apache lida com a verificação do certificado do cliente. Após validar o certificado, o Apache passa o resultado da verificação para o Django através de variáveis de ambiente WSGI confiáveis:
SSL_CLIENT_VERIFY - O status da verificação (SUCCESS, NONE, FAILED)SSL_CLIENT_S_DN - O Distinguished Name do assunto do certificadoSSL_CLIENT_SERIAL - O número de série do certificadoEste é o padrão seguro e correto. O problema está em como o middleware Django lê esses dados.
No FortiClient EMS 7.4.5 e 7.4.6, o middleware de autenticação Django foi modificado para também aceitar essas mesmas informações de cabeçalhos de requisição HTTP:
X-SSL-CLIENT-VERIFYX-SSL-CLIENT-S-DNX-SSL-CLIENT-SERIALIsso provavelmente foi adicionado para suportar implantações com proxy reverso onde o Apache não é o ponto de terminação TLS. No entanto, o middleware não distingue entre essas duas fontes. Ele verifica as variáveis WSGI primeiro, mas se elas estiverem ausentes (sem mTLS configurado, ou uma conexão direta), ele recorre aos cabeçalhos HTTP - que qualquer cliente pode definir.
Aqui está a análise conceitual:
CAMINHO SEGURO (pretendido):
Apache mod_ssl valida cert --> define variáveis de ambiente WSGI --> Django lê variáveis de ambiente [OK]
CAMINHO INSEGURO (a vulnerabilidade):
Atacante define cabeçalhos HTTP diretamente --> Django lê cabeçalhos --> Confia neles [FALHA]
O middleware efetivamente confia que o cliente ateste seu próprio status de verificação de certificado. Isso é como um segurança perguntar a alguém "Ei, o outro segurança já verificou seu documento?" e deixá-lo entrar quando ele diz "sim".
Passo 1: Atacante envia uma requisição POST para um endpoint da API do EMS
com estes cabeçalhos:
X-SSL-CLIENT-VERIFY: SUCCESS
X-SSL-CLIENT-S-DN: CN=admin
X-SSL-CLIENT-SERIAL: 0000000000000001
Passo 2: Middleware Django verifica variáveis de ambiente WSGI → não presentes
Recorre aos cabeçalhos HTTP → encontra X-SSL-CLIENT-VERIFY: SUCCESS
Passo 3: Middleware trata a requisição como autenticada com identidade de admin
Passo 4: Atacante tem acesso administrativo completo à API
Passo 5: A partir da API administrativa, o atacante pode:
- Enviar políticas maliciosas para todos os endpoints gerenciados
- Extrair credenciais e certificados armazenados
- Implantar payloads via distribuição de software
- Modificar configurações ZTNA
- Pivotar para a rede mais ampla
O ataque inteiro requer uma única requisição HTTP. Sem força bruta, sem credential stuffing, sem engenharia social. Apenas um cabeçalho forjado.
A gravidade aqui vai além do próprio servidor. O FortiClient EMS é um multiplicador de força - comprometê-lo dá ao atacante vantagem sobre cada endpoint gerenciado:
Impacto Imediato:
Impacto a Jusante (via endpoints gerenciados):
Risco Empresarial:
| Versão | Status |
|---|---|
| FortiClient EMS 7.4.6 | Vulnerável |
| FortiClient EMS 7.4.5 | Vulnerável |
| FortiClient EMS 7.4.4 e anteriores | Não afetado |
| FortiClient EMS 7.2.x | Não afetado |
| Data | Evento |
|---|---|
| ~Final de março de 2026 | Vulnerabilidade descoberta e reportada por Simo Kohonen e Nguyen Duc Anh |
| 31 de março de 2026 | Primeiras tentativas de exploração registradas contra honeypots (Defused Cyber) |
| 4 de abril de 2026 | Fortinet lança hotfixes de emergência para 7.4.5 e 7.4.6 |
| 6 de abril de 2026 | CISA adiciona CVE-2026-35616 ao catálogo KEV (prazo: 9 de abril de 2026) |
| 13 de abril de 2026 | Este kit de detecção publicado |
O script Python testa múltiplos endpoints da API usando uma técnica de resposta diferencial.
Como funciona:
HTTP 401 Unauthorized)X-SSL-CLIENT-VERIFY: SUCCESS injetado401 para qualquer outra coisa (tipicamente 500 ou 200), o bypass de autenticação é confirmadoNenhum payload de exploração é enviado. O teste é seguro para produção.
Uso:
# Instalar dependências (apenas stdlib necessária para este script)
pip install -r requirements.txt
# Alvo único
python CVE-2026-35616_FortiClientEMS_detector.py -t 192.168.1.100
# Porta personalizada
python CVE-2026-35616_FortiClientEMS_detector.py -t ems.corp.local -p 8443
# Varredura em massa a partir de arquivo
python CVE-2026-35616_FortiClientEMS_detector.py -f targets.txt
# Saída JSON salva em arquivo
python CVE-2026-35616_FortiClientEMS_detector.py -t 192.168.1.100 --json -o results.json
# Com verificação de certificado SSL habilitada
python CVE-2026-35616_FortiClientEMS_detector.py -t 192.168.1.100 --verify-ssl
# Timeout aumentado para redes lentas
python CVE-2026-35616_FortiClientEMS_detector.py -t 192.168.1.100 --timeout 20
Opções:
| Flag | Descrição | Padrão |
|---|---|---|
-t, --target | IP ou hostname do alvo | - |
-f, --file | Arquivo com alvos, um por linha (linhas começando com # são ignoradas) | - |
-p, --port | Porta do alvo | 443 |
--timeout | Timeout de conexão em segundos | 10 |
--verify-ssl | Habilita verificação de certificado SSL | Desabilitado |
--json | Saída de resultados em formato JSON | Desligado |
-o, --output | Salvar resultados em um arquivo | - |
Exemplo de saída:
╔══════════════════════════════════════════════════════════════╗
║ CVE-2026-35616 - FortiClient EMS Auth Bypass Detector ║
║ Pre-Authentication API Access Bypass → Privilege Escalation║
║ CVSS: 9.1 (Critical) | CISA KEV: Active Exploitation ║
╚══════════════════════════════════════════════════════════════╝
[*] Scanning 192.168.1.100:443...
Target: 192.168.1.100:443
============================================================
[*] FortiClient EMS detected (Version: Unknown)
Vulnerability Test Results:
[VULNERABLE] /api/v1/auth/signin Baseline: 401 → Spoofed: 500
[VULNERABLE] /api/v1/system/status Baseline: 401 → Spoofed: 500
[NOT VULN] /api/v1/endpoints Baseline: 401 → Spoofed: 401
[!] TARGET IS LIKELY VULNERABLE TO CVE-2026-35616
Pre-authentication API bypass confirmed. Apply hotfix immediately!
Remediation: Upgrade to FortiClient EMS 7.4.7 or apply the hotfix
# Instalar o script NSE
sudo cp CVE-2026-35616_FortiClientEMS.nse /usr/share/nmap/scripts/
sudo nmap --script-updatedb
# Varredura básica
nmap -p 443 --script CVE-2026-35616_FortiClientEMS <target>
# Varrer uma sub-rede
nmap -p 443 --script CVE-2026-35616_FortiClientEMS 10.0.0.0/24
# Varrer múltiplos alvos a partir de um arquivo
nmap -p 443 --script CVE-2026-35616_FortiClientEMS -iL targets.txt
# Com detecção de versão de serviço
nmap -sV -p 443 --script CVE-2026-35616_FortiClientEMS <target>
Exemplo de saída Nmap:
PORT STATE SERVICE
443/tcp open https
| CVE-2026-35616_FortiClientEMS:
| VULNERABLE:
| FortiClient EMS Pre-Authentication API Bypass
| State: VULNERABLE
| IDs: CVE:CVE-2026-35616
| Risk factor: Critical (CVSS: 9.1)
| Disclosure date: 2026-04-04
| Extra information:
| Affected endpoints: 2
| Remediation: Apply hotfix for FortiClient EMS 7.4.5/7.4.6 or upgrade to 7.4.7
| CISA KEV deadline: April 9, 2026
| References:
| https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2026-35616
|_ https://www.cisa.gov/known-exploited-vulnerabilities-catalog
Se você quiser confirmar manualmente com curl:
# Passo 1: Linha de base - deve retornar 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: Falsificado - se retornar qualquer coisa diferente de 401, provavelmente vulnerável
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 o primeiro retornar 401 e o segundo retornar 500 ou 200, a instância está vulnerável.
Fique atento a estes sinais no seu ambiente:
X-SSL-CLIENT-VERIFY de fontes que não sejam proxyFontes de log para revisar:
Ações imediatas (faça agora):
Curto prazo (esta semana):
Longo prazo:
X-SSL-CLIENT-VERIFY, X-SSL-CLIENT-S-DN e X-SSL-CLIENT-SERIAL de requisições recebidas na borda da redeKerem Oruç - Engenheiro de Cibersegurança