Exploração de estouro de heap no CAPWAP e implante de pós-exploração em firewalls FortiGate
Uma falha de estouro de heap no daemon CAPWAP do FortiOS está sendo explorada na prática, sem autenticação, para instalar o PivotC2, um implante em Node.js que decifra e exfiltra as credenciais guardadas no próprio firewall. Trate todo FortiGate exposto e não corrigido como comprometido: atualize, feche a porta UDP 5246 na borda e gire todas as senhas armazenadas no equipamento.
O firewall deixou de ser apenas o obstáculo e passou a ser o cofre. O PivotC2 lê os arquivos de configuração do FortiGate, decifra os campos ENC e entrega em texto claro as chaves pré-compartilhadas de VPN, as contas de SSL-VPN, as senhas de rede sem fio, as credenciais de vínculo LDAP e as contas administrativas [1]. Quem operou o equipamento precisa assumir que essas senhas circulam fora da rede e girá-las todas, porque corrigir a falha não desfaz o que já foi coletado.
Este relatório perfila a exploração ativa de CVE-2025-25249, um estouro de buffer baseado em heap no daemon cw_acd do FortiOS e do FortiSwitchManager, e o implante que ela entrega, chamado PivotC2. A falha foi divulgada e corrigida pela Fortinet em 13 de janeiro de 2026 [2] [3]. A exploração na prática foi identificada pela unidade de pesquisa da SOCRadar e remonta a pelo menos julho de 2026, seguindo em curso [1].
A exploração não exige autenticação, não exige interação de usuário e alcança o equipamento por um único pacote UDP na porta 5246, usada pelo protocolo CAPWAP para gerenciar pontos de acesso sem fio [1] [2]. O implante entregue em seguida roda sobre o Node.js que já acompanha o FortiOS, ou seja, o operador não precisa gravar binário novo no aparelho.
A campanha não é um teste de laboratório: a lista de alvos recuperada com o atacante soma mais de 30.000 endereços IP de FortiGate, dos quais 178 foram confirmadamente explorados e infectados, com concentração nos Estados Unidos, seguidos de Chile, Colômbia e Reino Unido [1]. Em 9 de setembro de 2026 a CISA incluiu a falha no catálogo de vulnerabilidades exploradas conhecidas, com prazo de correção em 12 de setembro de 2026 e exigência de triagem forense [4].
As recomendações estão organizadas em duas frentes que não se substituem. A seção 10 trata de caça, porque o equipamento já corrigido pode continuar infectado. A seção 11 trata de correção, redução de exposição e rotação de credenciais, nessa ordem, porque a rotação é a única medida que endereça o dano já consumado.
Não houve submissão a sandbox nem análise de amostra por esta equipe. Todo o conteúdo técnico é inteligência de fonte aberta, extraída das referências [1] a [6] e conferida contra o texto original de cada uma. Não trate os indicadores abaixo como prova pericial de um incidente local. Eles servem para orientar caça e resposta, e cada achado precisa ser confirmado no seu próprio ambiente.
| Campo | Valor |
|---|---|
| Identificador | CVE-2025-25249 |
| Classe | Estouro de buffer baseado em heap, CWE-122 e CWE-787 [4] |
| Componente | Daemon cw_acd, serviço CAPWAP Control, UDP 5246 [1] |
| Vetor | Rede, sem autenticação e sem interação de usuário [2] |
| CVSS v3.1 | 9,8 crítica pelo NVD, 8,1 alta pela Fortinet como CNA [2] |
| Divulgação | Fortinet, 13 de janeiro de 2026, aviso FG-IR-25-084 [3] |
| Catálogo CISA | Incluída em 9 de setembro de 2026, prazo em 12 de setembro [4] |
| Exploração ativa | Observada desde pelo menos julho de 2026 [1] |
| Campo | Valor |
|---|---|
| Nome | PivotC2 [1] |
| Classe | Trojan de acesso remoto de pós-exploração |
| Linguagem | JavaScript, executado no Node.js nativo do FortiOS [1] |
| Versão recuperada | 0.2.3 |
| Alvo | Appliances FortiGate rodando FortiOS |
| Canal de C2 | Soquete TLS único de saída, com multiplexação de canais [1] |
| Persistência | Nenhuma em disco além do arquivo temporário, ver seção 4.3 |
| Atribuição | Crime cibernético de língua russa, com fim financeiro [1] |
A fonte primária cita 9,8 no corpo do texto e 7,4 na sua própria seção de perguntas frequentes [1]. Ao conferir diretamente no NVD, a pontuação primária é 9,8 crítica, atribuída pelo NIST, e existe uma pontuação secundária de 8,1 alta, atribuída pela Fortinet na condição de CNA (CVE Numbering Authority) [2]. Este relatório adota a pontuação do NVD e registra a da Fortinet ao lado, para que ninguém precise escolher entre números sem saber de onde vêm.
O CAPWAP (Control and Provisioning of Wireless Access Points) é o protocolo que a Fortinet usa para que um FortiGate gerencie centralmente pontos de acesso sem fio. O daemon cw_acd escuta o tráfego de controle desse protocolo na porta UDP 5246 [1]. O ponto que torna a falha grave não é a sofisticação da corrupção de memória, mas a exposição: esse serviço fica ativo em interfaces que tenham o serviço fabric habilitado, inclusive as voltadas para a internet, e responde antes de qualquer autenticação.
A Fortinet publicou o aviso e as correções em 13 de janeiro de 2026. As versões afetadas e as versões corrigidas são as seguintes [2] [6]:
| Produto | Afetadas | Corrigida em |
|---|---|---|
| FortiOS 7.6 | 7.6.0 a 7.6.3 | 7.6.4 ou superior |
| FortiOS 7.4 | 7.4.0 a 7.4.8 | 7.4.9 ou superior |
| FortiOS 7.2 | 7.2.0 a 7.2.11 | 7.2.12 ou superior |
| FortiOS 7.0 | 7.0.0 a 7.0.17 | 7.0.18 ou superior |
| FortiOS 6.4 | todas as versões | 6.4.17 ou superior [6] |
| FortiSwitchManager 7.2 | 7.2.0 a 7.2.6 | 7.2.7 ou superior |
| FortiSwitchManager 7.0 | 7.0.0 a 7.0.5 | 7.0.6 ou superior |
| FortiSASE | afetado, conforme catálogo CISA [4] | migrar para versão corrigida [6] |
O binário de exploração recuperado só traz perfis de deslocamento de memória para builds FortiOS 7.4.0 a 7.4.8, em 13 modelos de FortiGate e 2 de FortiAP [1]. Não conclua que um FortiGate 7.2 ou 6.4 exposto está a salvo. A falha atinge todas as versões da tabela, o perfil de alvo é um arquivo de dados trivial de ampliar, e a ausência de perfil apenas significa que aquela combinação ainda não foi vista sendo atacada por esta ferramenta.
O ataque começa por um binário chamado fortirun.bin, um ELF Linux x86-64 auto-extraível de dois estágios [1]. Ao rodar, ele descomprime da própria seção .rodata um bloco em ZStandard que desempacota 18 artefatos, entre eles um interpretador CPython completo e um segundo binário interno, também chamado fortirun.bin. Esse binário interno carrega dois módulos Python compilados, fortipwn.py e fortirun.py. Scripts em Bash e Python envolvem tudo isso num laço de tentativas repetidas, recebendo como argumentos o IP do FortiGate alvo, a porta CAPWAP, o IP e a porta do ouvinte do atacante, tempos limite e a carga final codificada em Base64 [1].
O módulo fortipwn.py executa a exploração propriamente dita, em quatro passos encadeados [1]:
hw_rev e sw_ver, por exemplo FGT60F-v7.4-build2731, consultados numa tabela interna de compatibilidade. Como a mesma resposta vaza ponteiros de memória vivos, o exploit calcula em tempo de execução as bases image_base e data_rw_base, ou seja, a aleatorização de endereços (ASLR) deixa de proteger.free_list_mp2, uma lista duplamente encadeada de blocos de tamanho fixo. O exploit envia em laço mensagens CAPWAP Add Station com 56 bytes do caractere A, forçando alocações de 72 bytes que preenchem as lacunas da piscina até que o buffer controlado pelo atacante fique imediatamente antes do nó alvo.me_type e me_sz um tamanho menor do que o realmente escrito. O daemon copia o excedente, e 16 bytes passam do fim do buffer de 56 bytes, sobrescrevendo os ponteiros fd e bk do nó vizinho.br x16 para desviar a execução até execvp.A chamada sequestrada de execvp abre um shell reverso em Node.js, que já existe no plano de gerência do FortiOS, e por isso nada precisa ser instalado no aparelho [1]. O módulo fortirun.py então injeta a carga Base64 diretamente no REPL interativo do Node (node -i), acrescenta um marcador de conclusão formado por __FORTIPWN_DONE__ mais 16 caracteres hexadecimais aleatórios, e lê a saída até encontrar esse marcador.
A carga injetada é um estágio intermediário de uma linha só, que se comporta assim [1]:
hxxps[://]146[.]103[.]99[.]177:8443/0c5b76709523;pivot;/tmp/.i.js;O caminho do endereço que serve o estágio não é arbitrário: são os 12 primeiros caracteres hexadecimais do hash SHA-256 do próprio código cliente do PivotC2 [1]. Isso significa que uma mudança no cliente muda o caminho servido, e um caminho fixo de bloqueio envelhece rápido. A regra de detecção por URI da seção 10.4 serve para caça retroativa, não para bloqueio prospectivo.
O PivotC2 adota a arquitetura clássica de shell reverso: o cliente é quem sempre inicia a conexão de saída para o servidor de comando e controle, contornando qualquer regra de entrada do firewall [1]. Toda a comunicação viaja por um único soquete TLS, sobre o qual um protocolo binário leve multiplexa canais nomeados, numa estrutura que lembra o modelo de canais do SSH.
Cada quadro começa com um inteiro de 4 bytes sem sinal em ordem big-endian, indicando o tamanho total da carga, seguido de 1 byte de tipo de mensagem e da carga em si. Todos os tipos, exceto CHANNEL_DATA, carregam um objeto JSON em UTF-8. O CHANNEL_DATA antepõe 4 bytes de identificador de canal a dados binários crus [1].
| Hex | Nome | Sentido | Campos principais |
|---|---|---|---|
| 0x01 | HELLO | Cliente para C2 | hostname, platform, arch, node_version, uptime, user, interfaces |
| 0x02 | HELLO_ACK | C2 para cliente | session_id |
| 0x03 | HEARTBEAT | Bidirecional | ts |
| 0x04 | COMMAND | C2 para cliente | cmd_id, type, args |
| 0x05 | COMMAND_RESULT | Cliente para C2 | cmd_id, data, error, done |
| 0x06 | CHANNEL_OPEN | Bidirecional | channel_id, type, host, port, path, cmd |
| 0x07 | CHANNEL_OPEN_ACK | Bidirecional | channel_id, success, error |
| 0x08 | CHANNEL_DATA | Bidirecional | binário: 4 bytes de cid mais dados crus |
| 0x09 | CHANNEL_CLOSE | Bidirecional | channel_id |
| 0x0A | CHANNEL_EOF | Bidirecional | channel_id |
| 0x0B | LOG | Cliente para C2 | level, msg |
| 0x0D | TASK_RESULT | Cliente para C2 | task_id, status, data, error |
O cliente é escrito para não morrer. Um manipulador global de uncaughtException engole erros inesperados, e a queda da conexão TLS aciona um laço de reconexão com recuo exponencial e variação aleatória [1]. Por padrão o cliente envia um HEARTBEAT a cada 30 segundos, ajustável pelo comando sleep. Do outro lado, o servidor varre as sessões a cada 15 segundos e encerra as que ficam 90 segundos sem sinal.
Um único destino TLS de saída, batendo em intervalo regular a partir do endereço de gerência do firewall, é um padrão que o próprio NetFlow enxerga sem inspeção de conteúdo. A variação aleatória do intervalo atrapalha a detecção por periodicidade exata, mas o par formado por origem fixa e destino fixo continua visível. A seção 10.2 detalha essa via.
Operações curtas rodam de forma síncrona e devolvem um resultado em Base64. Operações longas ou interativas abrem um canal dedicado. Os comandos recuperados são estes [1]:
| Comando | Efeito |
|---|---|
| exec | Executa um comando de sistema. |
| ls, cat, stat | Lista diretório, lê arquivo e obtém metadados. |
| rm, mv, mkdir | Apaga, move ou renomeia e cria diretório. |
| ifconfig, netstat | Lê interfaces de rede e conexões ativas. |
| ps, uname | Lista processos e devolve telemetria do sistema em JSON. |
| portscan | Varre portas por host ou faixa CIDR e mapeia o que está aberto. |
| dns | Resolve nomes de domínio a partir do equipamento. |
| listen, stop_listen | Abre e fecha ouvinte de encaminhamento reverso. |
| harvest | Coleta em lote os arquivos de configuração, ver seção 07. |
| task_start | Registra e executa tarefa em segundo plano. |
| sleep | Ajusta o intervalo do sinal de vida. |
| kill | Apaga os artefatos em disco e encerra o implante. |
Sobre a mesma conexão TLS trafegam canais independentes e bidirecionais, cada um com identificador de 32 bits [1]:
| Tipo | Aberto por | Comportamento |
|---|---|---|
| shell | C2 para cliente | Shell interativo via /bin/sh ou o primeiro disponível entre bash, ash, dash e busybox. |
| exec | C2 para cliente | Executa comando e transmite a saída continuamente. |
| upload | C2 para cliente | Transmite dados que o cliente grava direto em disco. |
| download | C2 para cliente | Transmite de volta o conteúdo de um arquivo do cliente. |
| direct | C2 para cliente | Manda o cliente conectar em host e porta internos, sustentando os proxies SOCKS5 e HTTP. |
| forward | Cliente para C2 | Encaminhamento reverso: conexões que chegam ao ouvinte do cliente saem no C2. |
O nome da ferramenta descreve a intenção. Quando o operador sobe um proxy SOCKS5 no servidor de C2, cada conexão recebida vira um canal direct e o cliente executa net.connect na rede interna da vítima [1]. Ferramentas comuns de linha de comando passam a enxergar a rede protegida como se estivessem dentro dela, sem sobrecarga adicional de tunelamento e sem qualquer regra de entrada nova no firewall.
O console do operador oferece, além dos comandos do cliente, controle de serviços de rede [1]:
| Comando | Efeito |
|---|---|
| sessions | Lista as sessões ativas de vítimas. |
| interact | Entra numa sessão e habilita o comando creds. |
| socks5, http | Sobe proxy local roteado pela sessão escolhida. |
| fwd_local, fwd_remote | Encaminhamento de portas local e reverso. |
| services, stop | Lista e encerra proxies e encaminhamentos ativos. |
| stager | Gera o estágio de uma linha já configurado para um alvo. |
Esta é a capacidade que define a campanha. Combinando o comando harvest no cliente com o comando creds no console, o operador despeja num diretório de coleta os arquivos que guardam a configuração e o segredo do aparelho [1]. Os arquivos coletados são estes:
| Caminho | Conteúdo |
|---|---|
| /data/config/sys_global.conf.gz | Configuração global do sistema |
| /data/config/global_system_interface.gz | Configuração das interfaces de rede |
| /data/config/sys_vd_root+root.conf.gz | Configuração do VDOM, com os campos ENC cifrados |
| /data/etc/fsv_sync.dat | Segredo específico do aparelho, chave AES-128-GCM |
Comentários no código apontam para um módulo fortidecrypt.js, não recuperado, que identifica e decifra os campos ENC por dois caminhos distintos [1]:
Yf267vE@, que serve de gatilho para a detecção automática. Esse caminho decifra sem nenhum acesso ao segredo do aparelho, e a técnica já era pública antes desta campanha [5].fsv_sync.dat.A decifragem bem-sucedida entrega em texto claro as chaves pré-compartilhadas de VPN IPsec, as credenciais de usuários de SSL-VPN, as senhas de redes sem fio, as credenciais de vínculo LDAP e as contas administrativas [1]. Nenhuma dessas senhas vive apenas no firewall: elas valem no diretório, no concentrador de VPN e nos serviços internos. Não trate o incidente como restrito ao equipamento. Enquanto essas senhas não forem giradas, o atacante mantém acesso legítimo mesmo depois de o implante ser removido e a falha corrigida.
O servidor de C2 aceita uma opção de modo automático. Ligada, cada nova conexão de vítima dispara sozinha um encadeamento de cinco etapas, sem nenhuma intervenção humana [1].
HELLO registra a telemetria da vítima.harvest e creds recolhem a configuração global, a do VDOM e o arquivo fsv_sync.dat.forticonfig.js extrai as redes internas do arquivo de interfaces.As faixas internas fixas usadas na varredura automática são estas [1]:
10.0.0.0/24 e 10.0.1.0/24;172.16.0.0/24;192.168.0.0/24 e 192.168.1.0/24.Sem o modo automático, um comprometimento só rende alguma coisa quando um operador dedica tempo àquela vítima, e o volume de alvos deixa de importar. Com ele, o proveito é imediato e independe da atenção humana, ou seja, ser um alvo pequeno e sem valor aparente deixa de ser proteção. As credenciais de qualquer FortiGate infectado são coletadas e decifradas no momento em que o aparelho fala pela primeira vez com o servidor.
A análise dos arquivos do atacante revelou uma lista de mais de 30.000 endereços IP de FortiGate como alvos, dos quais 178 foram confirmados como explorados e infectados com PivotC2 [1]. Cada sessão de vítima registrava metadados da infecção, incluindo identificador de sessão, nome do equipamento, arquitetura, versão do Node.js, endereço e porta da vítima e tempo desde a infecção. A distribuição geográfica mostra maior concentração nos Estados Unidos, seguidos de Chile, Colômbia e Reino Unido.
Em dois alvos nos Estados Unidos o comprometimento passou do firewall. A fonte descreve o ciclo completo: exploração da falha, implante do PivotC2, abertura de túneis internos, descoberta de hosts, extração de credenciais de navegador, movimentação lateral e exfiltração de dados [1]. As saídas das ferramentas recuperadas mostram uso intenso de assistentes de inteligência artificial em várias etapas da intrusão, inclusive na geração automática dos relatórios de saída de comando. O próprio implante traz comentários e instruções de uso detalhados, o que sustenta a avaliação de que a inteligência artificial participou do desenvolvimento.
As ferramentas adicionais recuperadas dessas duas intrusões são estas [1]:
| Ferramenta | Uso observado |
|---|---|
| ldapdomaindump | Enumeração de Active Directory por LDAP: contas de computador, grupos, políticas de grupo, relações de confiança e usuários. |
| obfs4proxy, lyrebird | Proxy SOCKS5 local na porta 9050, roteando o tráfego operacional por pontes Tor. |
| russh | Binário SSH em Rust, usado para montar relés de SSH reverso entre alvos internos. |
| SoftPerfect Network Scanner | Descoberta de sub-redes e perfilamento de hosts. |
| Alteração de registro | fDenyTSConnections = 0 e DisableRestrictedAdmin = 0, liberando RDP com autenticação por repasse de hash. |
| Coleta em navegador | Extração de credenciais salvas no Chrome e no Edge, com personificação de token para obter as chaves mestras DPAPI. |
| run.ps1 | Baixa carga do servidor de C2, decifra por XOR de um byte com chave 0xAB, decodifica o Base64 e injeta o resultado no processo svchost.exe. |
| Exfiltração para S3 | Empacotamento e envio de caixas de correio do Exchange, em arquivos .pst, para buckets Wasabi controlados pelo atacante. |
A fonte primária avalia com alta confiança tratar-se de operação de crime cibernético de língua russa, com motivação financeira, apoiada em comentários em russo nas ferramentas recuperadas, na tática de exfiltração e na busca ativa por infraestrutura de armazenamento e de backup [1]. Os mesmos operadores demonstram interesse em outras falhas conhecidas, entre elas CVE-2024-47575 no FortiManager, CVE-2026-35273 no Oracle PeopleSoft e CVE-2024-26304 no ArubaOS. Este relatório não nomeia grupo nem afirma autoria, e a resposta recomendada não muda em função dela.
A caça vai do mais barato e abrangente para o mais caro e específico. As três primeiras vias não exigem tocar no equipamento suspeito, o que importa quando o equipamento suspeito é o próprio firewall de borda.
As regras Suricata, Sigma e YARA das seções 10.3 a 10.5 foram escritas por esta equipe a partir dos indicadores e do comportamento descritos na fonte primária, e não de execução de amostra. Nenhuma foi validada contra tráfego real ou contra o cliente PivotC2. Trate cada uma como ponto de partida a ajustar e medir no seu ambiente antes de ativar alerta.
Antes de caçar infecção, inventarie exposição. Levante quais interfaces externas têm o serviço fabric habilitado e se há tráfego chegando às portas de controle CAPWAP.
# em cada interface externa, confira se "fabric" aparece na lista
show system interface | grep -f allowaccess
# escuta por trafego CAPWAP de controle chegando na borda
diagnose sniffer packet any 'udp port 5246' 4 20
O implante mantém uma conexão TLS de saída persistente a partir do próprio firewall. Procure no NetFlow ou nos registros de sessão qualquer conexão originada no endereço de gerência do FortiGate para as portas 8443 ou 9443 de destinos externos.
index=netflow src_ip IN (lista_de_firewalls)
| search dest_port IN (8443, 9443)
| stats count, sum(bytes) AS total BY src_ip, dest_ip, dest_port
| sort - total
CommonSecurityLog
| where DestinationIP in ("146.103.99.177", "46.151.29.58")
or (SourceIP in (FirewallMgmtIPs) and DestinationPort in (8443, 9443))
| summarize Sessoes=count(), Bytes=sum(SentBytes) by SourceIP, DestinationIP
| order by Sessoes desc
Duas regras cobrem lados diferentes do problema: a primeira vê a tentativa de exploração, a segunda vê o download do estágio.
# 1. Descoberta CAPWAP vinda de fora da rede, precursora da exploracao
alert udp $EXTERNAL_NET any -> $HOME_NET 5246 (
msg:"CIBERLAB CAPWAP CONTROL EXTERNO POSSIVEL CVE-2025-25249";
classtype:attempted-admin; priority:1;
sid:9000101; rev:2;
)
# 2. Download do estagio PivotC2 pelo caminho derivado do hash do cliente
alert http $HOME_NET any -> $EXTERNAL_NET any (
msg:"CIBERLAB PIVOTC2 DOWNLOAD DE ESTAGIO";
http.uri; content:"/0c5b76709523"; startswith;
classtype:trojan-activity; priority:1;
sid:9000102; rev:2;
)
O caminho /0c5b76709523 é derivado do hash do cliente PivotC2 e muda a cada nova compilação [1]. Não use essa assinatura como controle preventivo único, porque ela deixa de casar assim que o operador recompilar o implante. Ela serve para caça retroativa em registros já coletados, onde o valor antigo continua valendo.
A regra abaixo expressa, de forma portável para o backend de SIEM da instituição, a chegada de tráfego CAPWAP de controle a partir de fora da rede, que é o precursor observável da exploração antes de qualquer implante.
title: Trafego CAPWAP de controle vindo da internet para FortiGate
id: 4e9d2f70-6a1c-4b83-9e52-1d8c7a06b4f9
status: experimental
description: >
O daemon cw_acd escuta CAPWAP Control em UDP 5246 e e explorado por
CVE-2025-25249 sem autenticacao. Trafego para essa porta a partir de
origem externa, na interface de borda, e o precursor da exploracao e nao
deveria existir num plano de gerencia corretamente fechado.
references:
- https://socradar.io/blog/cve-2025-25249-pivotc2-fortigate-rat/
- https://fortiguard.fortinet.com/psirt/FG-IR-25-084
author: CiberLab, Ciencia Embarcada
date: 2026/09/09
tags:
- attack.initial-access
- attack.t1190
logsource:
category: firewall
detection:
capwap_externo:
dst_port: 5246
protocol: udp
direction: inbound
origem_externa:
src_ip|cidr:
- '0.0.0.0/0'
origem_interna:
src_ip|cidr:
- '10.0.0.0/8'
- '172.16.0.0/12'
- '192.168.0.0/16'
condition: capwap_externo and origem_externa and not origem_interna
falsepositives:
- Controlador CAPWAP legitimo gerenciando APs por WAN, se existir: aliste
o endereco do controlador em origem_interna
level: high
Aplicável a captura de rede decifrada, a amostras recuperadas do próprio appliance ou ao conteúdo de /tmp/.i.js, e não a uma varredura de disco de estação Windows, pelo motivo da seção 12.3. A regra combina os marcadores de protocolo e as cadeias operacionais que a fonte documenta no cliente.
rule PivotC2_Node_Client
{
meta:
description = "Cliente PivotC2 em JavaScript, implante de CVE-2025-25249"
author = "CiberLab, Ciencia Embarcada"
date = "2026-09-09"
reference = "https://socradar.io/blog/cve-2025-25249-pivotc2-fortigate-rat/"
confidence = "derivada de OSINT, sem validacao contra amostra"
tlp = "TLP:CLEAR"
strings:
// Marcador de conclusao injetado pelo exploit no REPL do Node [1]
$done = "__FORTIPWN_DONE__" ascii
// Artefato do estagio em disco [1]
$drop = "/tmp/.i.js" ascii
// Nomes de tipo de mensagem do protocolo proprio [1]
$p1 = "HELLO_ACK" ascii
$p2 = "CHANNEL_OPEN_ACK" ascii
$p3 = "TASK_RESULT" ascii
// Comandos e canais caracteristicos [1]
$c1 = "harvest" ascii
$c2 = "stop_listen" ascii
$c3 = "fsv_sync.dat" ascii
// Chave XOR do estagio intermediario [1]
$xor = "pivot" ascii
condition:
// O marcador do exploit sozinho ja e forte; senao, exige um conjunto
// de indicadores de protocolo e operacao para evitar falso positivo
$done
or ($drop and 2 of ($p*))
or (3 of ($p*, $c*) and $xor)
}
Havendo suspeita, inspecione o FortiGate pela linha de comando do FortiOS [1]:
# sessoes ativas para os enderecos de C2 conhecidos
diagnose sys session filter daddr 146.103.99.177
diagnose sys session list
diagnose sys session filter daddr 46.151.29.58
diagnose sys session list
# artefato do implante em disco
fnsysctl ls -la /tmp/.i.js
fnsysctl ls -la /tmp/
# execucao suspeita de Node.js
diagnose sys process list | grep node
O Node.js acompanha legitimamente o FortiOS e sustenta parte do plano de gerência. Não classifique um processo como malicioso apenas por ele ser Node.js, e não use a ausência de processo estranho como prova de que o equipamento está limpo. O que distingue é o argumento de execução, o arquivo carregado e o destino da conexão de saída, não o nome do binário.
fabric das interfaces externas ou aplique uma política local-in descartando UDP de entrada nas portas 5246 a 5249 [1] [3].Trate o firewall como ponto de pivô, não como destino final. Procure na rede interna as marcas descritas na seção 09: alterações de registro que reabilitam RDP, relés de SSH reverso, acesso a credenciais salvas em navegador e transferências de saída para armazenamento em nuvem. As faixas da seção 08 indicam onde a varredura automática bateu primeiro.
| Controle | Aplicação |
|---|---|
| Plano de gerência fechado | Nenhum serviço de gerência ou de fabric respondendo em interface voltada para a internet, inclusive os que usam UDP e não aparecem numa varredura TCP comum. |
| Saída filtrada na borda | O firewall não precisa iniciar conexões arbitrárias para a internet. Restringir a saída do próprio equipamento quebra o canal de C2 mesmo com o implante instalado. |
| Segredos fora do aparelho | Autenticação de administrador e de VPN apoiada em fatores externos, para que a leitura da configuração não baste para reutilizar o acesso. |
| Correção priorizada por exploração | Falhas de borda com exploração confirmada entram em janela emergencial, e não no ciclo trimestral. Esta entrou no catálogo da CISA com prazo de três dias [4]. |
| Telemetria do equipamento | Exportação contínua de sessões e registros do FortiGate para fora dele, porque um aparelho comprometido não é testemunha confiável de si mesmo. |
As técnicas abaixo foram conferidas uma a uma em attack.mitre.org, e os nomes reproduzem o oficial de cada página. A primeira tabela cobre do desenvolvimento de capacidade à evasão de defesas:
| Técnica | Nome | Relação com o caso |
|---|---|---|
| T1587.004 | Develop Capabilities: Exploits | Construção do exploit dedicado a CVE-2025-25249. |
| T1190 | Exploit Public-Facing Application | Exploração do FortiGate exposto na borda. |
| T1059.007 | Command and Scripting Interpreter: JavaScript | Execução do PivotC2 sobre o Node.js do FortiOS. |
| T1059.004 | Command and Scripting Interpreter: Unix Shell | Canais de shell em sh, bash, ash, dash ou busybox. |
| T1059.001 | Command and Scripting Interpreter: PowerShell | Execução de run.ps1 na rede interna. |
| T1036.009 | Masquerading: Break Process Trees | Implante segue vivo em segundo plano após o Node pai encerrar. |
| T1055.002 | Process Injection: Portable Executable Injection | Injeção em svchost.exe pelo run.ps1. |
| T1027 | Obfuscated Files or Information | Base64 e XOR com chave pivot no estágio. |
| T1070.004 | Indicator Removal: File Deletion | Comando kill apaga os artefatos em disco. |
A segunda tabela cobre descoberta, movimentação lateral e coleta:
| Técnica | Nome | Relação com o caso |
|---|---|---|
| T1046 | Network Service Discovery | Varredura de portas por CIDR, manual ou no modo automático. |
| T1087.002 | Account Discovery: Domain Account | Uso de ldapdomaindump contra o Active Directory. |
| T1082 | System Information Discovery | Comandos uname, stat e ps no equipamento. |
| T1016 | System Network Configuration Discovery | Comandos ifconfig, netstat e dns no equipamento. |
| T1083 | File and Directory Discovery | Comandos ls e cat, mais a coleta em lote. |
| T1021.001 | Remote Services: Remote Desktop Protocol | Registro alterado para reabilitar RDP com modo restrito. |
| T1021.004 | Remote Services: SSH | Relés de SSH reverso montados com russh. |
| T1555.003 | Credentials from Password Stores: Credentials from Web Browsers | Coleta de senhas salvas no Chrome e no Edge. |
| T1552.001 | Unsecured Credentials: Credentials In Files | Leitura e decifragem dos campos ENC da configuração. |
| T1114.001 | Email Collection: Local Email Collection | Coleta de arquivos .pst do Exchange. |
A terceira tabela cobre comando e controle e exfiltração:
| Técnica | Nome | Relação com o caso |
|---|---|---|
| T1071.001 | Application Layer Protocol: Web Protocols | Canais sobre HTTPS e download do estágio por requisição web. |
| T1573.002 | Encrypted Channel: Asymmetric Cryptography | Soquete TLS único, com fixação de certificado. |
| T1090.001 | Proxy: Internal Proxy | Proxies SOCKS5 e HTTP embutidos no implante. |
| T1090.002 | Proxy: External Proxy | SOCKS5 local na porta 9050 sobre pontes Tor. |
| T1090.003 | Proxy: Multi-hop Proxy | Encaminhamento de portas local e reverso até o C2. |
| T1105 | Ingress Tool Transfer | Canais de upload e download de arquivos e estágios. |
| T1567.002 | Exfiltration Over Web Service: Exfiltration to Cloud Storage | Envio das caixas de correio para buckets Wasabi. |
A fonte primária lista a coleta de credenciais de navegador sob T1003.001 [1]. Ao conferir em attack.mitre.org, esse identificador corresponde a OS Credential Dumping: LSASS Memory, que descreve outra coisa. A técnica que a própria fonte descreve em texto, credenciais em navegador, é T1555.003 [7], e é essa que este relatório adota. Todos os demais 25 códigos foram conferidos e conferem com o nome oficial.
Todos os indicadores abaixo vêm da fonte primária [1], porque não houve análise local. As URLs e endereços aparecem desarmados de propósito, e não devem ser transformados em link clicável.
| Tipo | Indicador | Severidade | Contexto e ação |
|---|---|---|---|
| IPv4 | 146[.]103[.]99[.]177 | Crítica | Nó do PivotC2, portas 8443 e 9443 [1]. Bloquear e alertar |
| IPv4 | 46[.]151[.]29[.]58 | Crítica | Nó do PivotC2, porta 8443 [1]. Bloquear e alertar |
| URL | hxxps[://]146[.]103[.]99[.]177:8443/0c5b76709523 | Alta | Endereço que serve o estágio [1]. Caça retroativa |
| IPv4 e porta | 45[.]138[.]16[.]182:9130 | Média | Ponte Tor obfs4proxy [1]. Monitorar |
| IPv4 e porta | 89[.]217[.]174[.]207:9001 | Média | Ponte Tor obfs4proxy [1]. Monitorar |
| Porta | UDP 5246 | Alta | Serviço explorado, CAPWAP Control [1]. Bloquear na borda |
| Tipo | Indicador | Severidade | Contexto e ação |
|---|---|---|---|
| Arquivo | /tmp/.i.js | Crítica | Implante PivotC2 gravado pelo estágio [1]. Tratar como infecção |
| Cadeia | __FORTIPWN_DONE__ | Alta | Marcador de conclusão do exploit [1]. Caça retroativa |
| Cadeia | pivot | Contexto | Chave XOR do estágio [1]. Apoio à triagem |
| Cadeia | Yf267vE@ | Contexto | Rastro dos campos AES-256-CBC [1] [5]. Apoio à triagem |
| Registro | fDenyTSConnections = 0 | Alta | Reabilitação de RDP em host interno [1]. Caça retroativa |
| Registro | DisableRestrictedAdmin = 0 | Alta | Repasse de hash por RDP [1]. Caça retroativa |
| Artefato | SHA-256 | Ação |
|---|---|---|
| fortirun.bin | 2d338ffc8cc80293575c6800c059e33eb41e967907c20ba7687b2231c50837db | Caça retroativa |
| payload.js | cc7f0660d56405cbdff157033d3e35305f063e62efaff6501d11e6a34e7bd151 | Caça retroativa |
| payload2.js | eb4d8aab4e687839c5478a7a3819b0a7a857555ed50fc159c026e99764a0c8a0 | Caça retroativa |
| payload_new.js | fe7da807a2b37a2bbd8c27830a9acc0d86ad8128f38489c493873c7e410c0408 | Caça retroativa |
| run.ps1 | c25a27b506fbae62010caf2abff699df5c94d29f056fa7ccfb5f3170d917c8cb | Caça retroativa |
| payload.b64 | d4911736986cf8affb29106fb8e8b74e00e52d5f762dce9025f2cfe431cf2140 | Caça retroativa |
| Origem | SHA-256 | Forma |
|---|---|---|
| 46.151.29.58:8443 | d99fa14f5e7dfe17e437f167f3f9550ebeda496960710dde81d41748bd7749e4 | Decodificado |
| 46.151.29.58:8443 | 005e6014fb8fd47249691756f5af3b3d53bfae82df88a71277e53e13fe94cb9f | Codificado |
| 146.103.99.177:8443 | 550f99193f9e90d93b70af1ab050a2d44f1830259ea165568dafc518e761c589 | Decodificado |
| 146.103.99.177:8443 | 08fa6abac9c132deff4f120a7fcfe5bf17c797b87dbbc3f261d5cf0c077c0a2e | Codificado |
| 146.103.99.177:9443 | a9bea5f89984d47dd60216b0a0b064e8c7e8057e0c10509faa4a2d8d641eb73b | Decodificado |
| 146.103.99.177:8443 | 1bf2c5976f2abbe147ae7be140ed69af2c25092f563786400aecd0231229be19 | Codificado |
Os quatro primeiros artefatos da tabela 16 rodam no appliance, não em Windows, e os hashes do cliente PivotC2 correspondem a arquivos de texto JavaScript servidos por HTTP, não a executáveis gravados em estação de trabalho. Não espere casamento em varredura de disco corporativa, e não conclua que a rede está limpa quando o EDR não devolve nada. Use esses valores em análise de captura de rede, em amostras recuperadas do próprio appliance e em consultas a plataformas de amostras. As exceções são run.ps1 e payload.b64, que de fato tocam hosts Windows.
fortirun.bin nem o cliente PivotC2. Todo o conteúdo técnico vem das referências, e nenhuma afirmação aqui equivale a observação própria.fortidecrypt.js, que faz a decifragem das credenciais, não foi recuperado pela fonte primária. Sua existência e comportamento são inferidos de comentários no código, e o detalhe do esquema AES-256-CBC vem de pesquisa independente anterior [5], não desta campanha.Yf267vE@ usado para reconhecer os campos cifrados. Sustenta a seção 7.1.
https://blog.n0p.me/2026/08/2026-08-21-fortitool-fortios-decryption/
PivotC2 e CVE-2025-25249, relatório técnico de análise de artefato. Versão 2.0, emitida em 9 de setembro de 2026.
Lucas Rayan Guerra, CiberLab, uma iniciativa do Ciência Embarcada.
Classificado TLP:CLEAR: distribuição livre, sem restrição de compartilhamento.