
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: