Home Comunidade Eventos YouTube Networks Desafios // produtos Academy News CTI | CVE Contato

06 - Hunting por Comando e Controle (Beaconing, DNS Tunneling)

video explicativo
Video explicativoEspaco reservado para o video desta anotação — adicione video: https://youtu.be/... no frontmatter da nota.

Hunting por Comando e Controle (Beaconing, DNS Tunneling)

Nota 06 do capítulo 08 (Técnicas de Hunting por TTPs), abrindo o bloco de caça por tática com a fase de Comando e Controle da MITRE ATT&CK.
Consolida os padrões de C2 mais frequentes, o cálculo de cadência e jitter, consultas KQL de beaconing por estatística de intervalo e a detecção de túnel DNS.
Dialoga com as notas de telemetria do capítulo 02, com o controle TH.12 (Hunting de Rede) do capítulo 15 e com a nota 07 deste capítulo, sobre exfiltração.

1. Contexto e Posicionamento na Biblioteca

Toda intrusão prolongada precisa de um canal de controle, e é esse canal que sustenta o dwell time do adversário: sem C2 estável não há segunda fase, não há movimento lateral e não há exfiltração. Por essa razão, a tática de Command and Control é um dos alvos mais produtivos de hunting, porque o adversário precisa manter uma regularidade de comunicação que tráfego humano genuíno não tem. Esta nota transforma essa regularidade em consultas executáveis, partindo do padrão conceitual de cada família de C2 até a estatística que a delata na telemetria.

O posicionamento na biblioteca é o de primeira nota aplicativa do capítulo 08: aqui as hipóteses estruturadas da nota sobre formulação (TH.6) encontram a telemetria de rede descrita no capítulo 02 e o controle TH.12 do capítulo 15. A nota 07 continua a mesma cadeia quando o canal de C2 vira canal de exfiltração, e a nota 09 reaproveita várias consultas em Windows com contexto de processo. O leitor deve sair desta nota com três habilidades: calcular cadência e jitter, caçar beacons por estatística de intervalo e reconhecer túnel DNS.

2. Padrões de Comando e Controle e suas Assinaturas

O C2 moderno se organiza em poucas famílias de padrão, e cada família deixa uma assinatura distinta na telemetria quando observada em janelas suficientes. O beaconing periódico com jitter é o mais comum: o implante dorme um intervalo base e acorda com uma variação percentual aleatória, o que gera conexões quase regulares que resistem a detecção por intervalo fixo. O C2 sobre HTTPS legítimo abusa de que o tráfego criptografado é aceito por padrão, o domain fronting esconde o domínio real atrás do SNI de uma CDN, o túnel DNS carrega comando dentro de rótulos de subdomínio, o DNS sobre HTTPS tira a visibilidade do resolver corporativo e o P2P distribui o controle entre muitos pares para eliminar ponto único. A tabela abaixo consolida o essencial para hunting.

Padrão Mecanismo típico Sinal dominante na telemetria ATT&CK
Beaconing com jitter Sleep fixo mais variação aleatória (ex.: 60s mais 20%) Intervalos entre conexões com coeficiente de variação baixo T1071.001
C2 over HTTPS POST/GET periódicos para endpoint falso de API Host novo com volume simétrico, user agent inconsistente T1071.001
Domain fronting SNI de CDN grande, Host header com domínio do operador SNI diferente do Host no log de proxy T1090.004
DNS tunneling Dados codificados em rótulos, consultas TXT/NULL Rótulos longos, volume alto para um mesmo domínio T1071.004
DoH / criptografia de resolução Resolução direta a provedores de DoH na porta 443 Conexões para endpoints /dns-query, ausência de log no resolver T1090.001
P2P e mesh Muitos pares, portas altas, conexões bidirecionais Grau de conexões alto e simétrico entre hosts e IPs externos T1095

A leitura de hunting dessa tabela é que nenhum padrão é detectável por evento isolado: todos exigem agregação em janela e comparação com baseline. O erro estrutural mais comum é caçar beacon procurando payload, quando o payload está criptografado e o que sobra para o analista é exatamente a cadência. Por isso as seções seguintes tratam a cadência como objeto primário de caça e os demais sinais como corroboradores.

3. Cadência e Jitter: Definições e Cálculo

Cadência é o intervalo médio entre conexões consecutivas do mesmo host para o mesmo destino; jitter é a variação percentual desses intervalos, aproximada pelo coeficiente de variação, que é o desvio padrão dividido pela média. Um implante configurado com sleep de 60 segundos e jitter de 20% produz intervalos entre 48 e 72 segundos com desvio da ordem de 12 segundos, o que dá coeficiente de variação perto de 0,20. Navegação humana, sync de aplicativo legítimo e keepalive de infraestrutura têm assinaturas diferentes, e é essa diferença que a consulta explora. O cálculo exige intervalos pareados por destino, porque misturar conexões de destinos distintos destrói a estatística.

Coeficiente de variação observado Interpretação provável Ação sugerida
Abaixo de 0,10 Beacon com jitter baixo ou zero; raro em tráfego humano Prioridade alta; atribuir processo de origem
Entre 0,10 e 0,30 Beacon com jitter típico (10% a 30%); sinal forte quando cadência entre 10s e 600s Prioridade alta; enriquecer domínio e IP
Entre 0,30 e 0,60 Zona ambígua: sincronizações, telemetria de aplicativo Filtrar por destino conhecido e revisar manualmente
Acima de 0,60 Tráfego humano ou aleatoriedade forte; estatística sem valor Descartar para beaconing; caçar por outros sinais

Dois detalhes práticos definem a qualidade do cálculo. Primeiro, a contagem mínima: com menos de 15 a 20 intervalos a média e o desvio são instáveis e geram ruído, então a consulta deve exigir volume. Segundo, o pareamento deve ser por tupla host, IP e porta, e não apenas por IP, porque CDNs compartilham IP entre milhares de domínios e produzem falsos positivos em massa quando agregadas sozinhas.

4. Consultas KQL de Beaconing por Estatística de Intervalo

A consulta abaixo parte de eventos de rede de endpoint (DeviceNetworkEvents) e calcula intervalos entre conexões consecutivas pareadas por destino, usando partição explícita para não misturar fluxos. O filtro exclui endereços privados e exige contagem mínima de 20 intervalos com coeficiente de variação abaixo de 0,30, que é a faixa prática onde beacons emergem com pouco ruído em redes corporativas. Ajustar os limites de cadência entre 5 e 3600 segundos cobre implantes rápidos e beacons lentos de pós-exploração.

// Beacons candidados: intervalos regulares por host e destino externo
let Janela = 24h;
DeviceNetworkEvents
| where Timestamp > ago(Janela)
| where ActionType == "ConnectionSuccess"
| where RemotePort in (80, 443, 8080)
| where not(ipv4_is_match(RemoteIP, "10.0.0.0/8")
    or ipv4_is_match(RemoteIP, "172.16.0.0/12")
    or ipv4_is_match(RemoteIP, "192.168.0.0/16"))
| project Timestamp, DeviceName, RemoteIP, RemotePort
| partition hint.strategy=shuffle by RemoteIP
    (
        order by Timestamp asc
        | serialize
        | extend IntervaloS = (Timestamp - prev(Timestamp)) / 1s
        | where isnotnull(IntervaloS) and IntervaloS between (5 .. 3600)
    )
| summarize Contagem = count(), Media = round(avg(IntervaloS), 1),
            Desvio = round(stdev(IntervaloS), 1),
            Minimo = round(min(IntervaloS), 1), Maximo = round(max(IntervaloS), 1)
            by DeviceName, RemoteIP, RemotePort
| extend CV = round(Desvio / Media, 3)
| where Contagem >= 20 and CV < 0.30
| order by CV asc

A segunda consulta trabalha no plano do proxy, com logs CEF na tabela CommonSecurityLog, e usa estatística por janela fixa de 30 segundos: um beacon que dorme 30 segundos aparece como um número quase constante de conexões por janela, enquanto tráfego humano concentrado em rajadas não se mantém constante ao longo de centenas de janelas. Essa forma é útil quando o endpoint não tem EDR e o proxy é a única visibilidade de saída, e combina bem com a técnica de stack counting do controle TH.8.

// Estatística por janela de 30s no proxy: constância de conexões por destino
CommonSecurityLog
| where TimeGenerated > ago(1d)
| where ApplicationProtocol in~ ("HTTP", "HTTPS") and isnotempty(RequestURL)
| extend Host = tostring(parse_url(RequestURL)["Host"])
| summarize Conexoes = count() by Host, DestinationIP, Janela30s = bin(TimeGenerated, 30s)
| summarize MediaPorJanela = round(avg(Conexoes), 2), MaxPorJanela = max(Conexoes),
            JanelasAtivas = count()
            by Host, DestinationIP
| where MediaPorJanela between (0.8 .. 3.0) and MaxPorJanela <= 6 and JanelasAtivas > 200
| extend Leitura = strcat("cerca de ", MediaPorJanela, " conexoes por janela de 30s em ", JanelasAtivas, " janelas")

Para domain fronting, a verificação decisiva é a divergência entre SNI e header Host no log do proxy: quando o proxy registra ambos, toda linha em que o Host difere do destino TLS merece revisão, porque a legítima pilha de aplicativos quase nunca fronta. Para DoH, a hipótese complementar é de contorno: conexões na porta 443 para provedores de DoH conhecidos ou URLs terminando em /dns-query indicam que resoluções estão escapando do resolver corporativo, e o hunting deve então correlacionar hosts que fazem DoH com hosts que produzem consultas de domínio ausentes no log de DNS interno. A consulta abaixo prioriza o uso de DoH fora do navegador, que é a forma mais relevante para hunting, porque navegadores corporativos usam DoH por padrão em muitos ambientes e poluiriam a lista sem essa exclusão.

// Contorno de resolucao: hosts usando DoH fora de navegadores conhecidos
let ProvedoresDoh = dynamic(["1.1.1.1", "8.8.8.8", "9.9.9.9", "149.112.112.112"]);
DeviceNetworkEvents
| where Timestamp > ago(7d)
| where RemotePort == 443
| where RemoteIP in (ProvedoresDoh) or RemoteUrl has "/dns-query"
| where not(InitiatingProcessFileName in~ ("chrome.exe", "msedge.exe", "firefox.exe", "chrome", "msedge", "firefox"))
| summarize Conexoes = count(), Processos = dcount(InitiatingProcessFileName),
            Primeira = min(Timestamp)
            by DeviceName, RemoteIP, InitiatingProcessFileName
| where Conexoes > 20
| order by Conexoes desc

5. Detecção de Túnel DNS

O túnel DNS converte o resolver corporativo em canal de dados: o implante codifica comando em rótulos de subdomínio, o servidor autoritativo do operador responde com dados em TXT ou NULL, e o volume atravessa o firewall como tráfego de resolução aparentemente normal. Os sinais confiáveis são três, e funcionam melhor combinados: rótulos de primeiro nível anormalmente longos, concentração de consultas em tipo TXT ou NULL para um mesmo domínio e alto número de rótulos únicos que nunca se repetem, porque dados codificados em base32 ou base16 mudam a cada consulta. Domínios legítimos usados por CDNs e telemetria produzem rótulos longos ocasionais, mas não volume concentrado e não rotatividade total de rótulos.

// Túnel DNS candidado: rótulos longos, dominância TXT e rotatividade de subdomínios
DnsEvents
| where TimeGenerated > ago(6h)
| extend Dominio = tolower(Name), Rotulo = tostring(split(Name, ".")[0])
| summarize Consultas = count(), TamMedio = round(avg(strlen(Rotulo)), 1),
            TamMax = max(strlen(Rotulo)),
            TXT = countif(QueryType == "TXT"),
            RotulosUnicos = dcount(Rotulo)
            by ClientIP, Dominio
| where TamMedio > 30 or (TXT > 50 and TXT > 0.5 * Consultas) or RotulosUnicos > 200
| extend Leitura = strcat("mediana de rotulo ", TamMedio, " chars; ", TXT, " TXT de ", Consultas, " consultas; ", RotulosUnicos, " rotulos unicos")
| order by Consultas desc

A interpretação exige dois contrapesos documentados no baseline. Provedores que usam DNS para balanceamento e telemetria de segurança geram rótulos únicos em volume, então a exceção deve ser registrada por domínio e não por host; e o hunting ganha força quando cruza o tamanho do rótulo com a origem, porque túnel real vem de poucos hosts internos consultando um domínio externo único, enquanto telemetria vem de todos os hosts consultando domínios conhecidos. Quando o resolver interno não tem log completo, o controle DAT.2 do capítulo 15 é o pré-requisito que precisa ser cobrado antes de qualquer caça confiável de túnel.

6. Exemplo de Caça Completa

O caso a seguir amarra a sequência inteira em um roteiro executável. A hipótese estruturada é: se um host mantém beacon HTTPS para infraestrutura nova do operador, então existe um conjunto de conexões de saída com cadência estável para um IP sem histórico na rede, originado por processo que não é navegador. A caça prossegue em quatro passos, com fontes e critérios de saída explícitos em cada um.

  1. Executar a primeira consulta da seção 4 em janela de 24 horas e listar os cinco melhores candidatos por coeficiente de variação, descartando destinos já documentados no baseline de exceções do proxy; o objetivo aqui é reduzir milhares de fluxos a uma lista curta verificável.
  2. Enriquecer cada candidato com passive DNS, WHOIS e idade de domínio: IP novo, domínio registrado há menos de 30 dias ou certificado emitido na véspera elevam a prioridade; IP de CDN grande com centenas de domínios legítimos reduz, mas não zera, porque fronting vive exatamente aí.
  3. Atribuir processo de origem ao candidato sobrevivente, usando a consulta abaixo; processo não navegador repetindo conexões periódicas para o mesmo destino externo é o critério de confirmação técnica, e o comando de linha do processo alimenta a resposta e a regra de detecção.
  4. Expandir a janela para 30 dias e replicar a consulta com o processo e o destino como âncoras, determinando início da comunicação, hosts adicionais afetados e volume total; produzir a regra de analytics e abrir o caso de resposta com o material anexado.
// Atribuicao de processo ao beacon confirmado no host suspeito
DeviceNetworkEvents
| where Timestamp > ago(24h)
| where DeviceName =~ "WKS-FIN-0231" and RemoteIP == "203.0.113.66"
| summarize Conexoes = count(), Primeira = min(Timestamp), Ultima = max(Timestamp)
            by InitiatingProcessFileName, InitiatingProcessCommandLine, AccountName
| order by Conexoes desc

O veredicto do caso se apoia em três evidências concorrentes, e não em uma só: cadência estável com coeficiente de variação baixo, processo não navegador como origem e infraestrutura jovem no destino. Quando as três coincidem, a probabilidade de falso positivo é residual e a resposta pode prosseguir para isolamento do host e bloqueio do destino; quando falta uma delas, o caso volta para a fila de enriquecimento com prazo definido, porque hunting sem critério de encerramento vira acúmulo de dossiês sem decisão.

7. Erros Comuns e Pontos de Atenção

  • Agregar apenas por IP de destino: CDNs e provedores de nuvem colocam milhares de domínios legítimos no mesmo IP, e a estatística pareada só pelo IP produz listas gigantes de falsos positivos; parear sempre por host, IP e porta, e exigir atribuição de processo antes de escalar.
  • Aplicar limiar de coeficiente de variação rígido demais: beacons com jitter alto, canais que usam buffers aleatórios e falhas de rede empurram o CV acima de 0,30; tratar a zona ambígua com enriquecimento manual, e não com exclusão automática, evita perder a caça por um parâmetro.
  • Ignorar beacons lentos: implantes de persistência de longo prazo dormem por horas, e janelas de caça de 24 horas não acumulam intervalos suficientes; rodar a mesma consulta em janelas de 7 e 30 dias com contagem mínima reduzida é cobertura complementar, não redundante.
  • Confundir túnel DNS com telemetria de segurança: alguns produtos legítimos usam TXT e rótulos longos, e a distinção prática está na concentração por host interno e na rotatividade total de rótulos; registrar as exceções no baseline, senão a consulta morre de ruído em semanas.
  • Caçar sem log de resolver completo: parcialidade de amostragem e ausência de tipo de consulta escondem exatamente o sinal procurado; antes de culpar a consulta, validar a fonte com o controle DAT.5 do capítulo 15.

8. Integração com o Restante da Biblioteca

Esta nota consome diretamente a telemetria de rede inventariada no capítulo 02 e opera dentro do processo de hunting do capítulo 07, aplicando a formulação de hipóteses do controle TH.6 e a estatística de stack counting do TH.8. A nota 07 deste capítulo estende o mesmo canal para exfiltração, e a distinção entre volume de C2 e volume de exfiltração é tratada lá; a nota 09 traz a mesma consultas de beaconing ancoradas em processo no Windows, e a nota 11 repete o exercício em cloud, onde o beaconing aparece entre instâncias e endpoints de comando. O mapeamento de cobertura dos controles MAP.2 e MAP.4 do capítulo 15 deve registrar esta nota como fonte de cobertura das técnicas T1071, T1090 e T1071.004, e o capítulo 18 (Detection Engineering) é o destino natural das consultas que aqui se revelaram estáveis, transformadas em regras de analytics com limiares calibrados pelas métricas do controle MET.2. Feeds e CTI alimentam o enriquecimento do passo 2 do exemplo de caça, fechando o ciclo descrito na nota de integração CTI-TH do capítulo 10.