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

14 - Hunting de DNS, HTTP e TLS

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

Hunting de DNS, HTTP e TLS

Nota 14 do capítulo 08 (Técnicas de Hunting por TTPs), descendo ao nível do protocolo onde o adversário precisa falar para ser ouvido.
Estrutura a caça por protocolo: DNS com DGA, NXDOMAIN e túnel; HTTP com user agent, paths e POST volumétrico; TLS com JA3/JA4, certificados e SNI.
Aprofunda os campos citados nas notas 12 e 13; alimenta as conversões de detecção do capítulo 18 e a análise de infraestrutura do capítulo 03.

1. Contexto e Posicionamento na Biblioteca

A caça por protocolo ocupa o meio da Pirâmide de Dor do capítulo 04: mais custosa para o adversário que trocar um IP de feed, mais barata para você que reconstruir TTP completa. Um domínio gerado por algoritmo queima em dias, mas a assinatura estatística que o denuncia, comprimento, entropia e cadência, sobrevive a infinitas trocas de infraestrutura. O mesmo vale para o fingerprint de TLS, que identifica a biblioteca cliente usada pelo malware e só muda quando o adversário troca de ferramenta ou passa a imitar navegadores de propósito. Esta nota organiza as três caçadas protocolares de maior retorno e entrega as consultas prontas para cada uma.

As fontes são as da nota 12: logs Zeek dns, http e ssl, eve.json do Suricata e, onde existir, logs de proxy e de resolver interno. A regra de trabalho é calibrar limiares por segmento com baseline de 30 dias, porque entropia aceitável, comprimento de URI e distribuição de user agent variam demais entre ambientes para aceitar números absolutos. Cada seção fecha com a leitura dos resultados e os falsos positivos conhecidos, e a seção 5 costura os três protocolos no mesmo caso, porque o adversário raramente usa um protocolo por vez.

2. Caça em DNS

Três famílias de hipótese concentram o valor do DNS em caça. A primeira é DGA (Domain Generation Algorithms), malware que gera dezenas ou centenas de domínios por dia e tenta resolvê-los até achar o C2 vivo. A segunda é NXDOMAIN em massa, que é o rastro barato da DGA, porque a maioria das tentativas falha e o resolver registra o erro. A terceira é túnel DNS, encapsulamento de dados em consultas e respostas, tipicamente TXT e NULL, que exfiltra ou recebe comandos por um canal quase sempre liberado sem inspeção.

O detector de DGA mais simples e eficaz calcula a entropia de Shannon e o comprimento do rótulo de subdomínio. O script abaixo consome a coluna query do dns.log e imprime apenas nomes com subdomínio de 20 caracteres ou mais e entropia a partir de 3,5, limiar que separa palavras humanas de strings aleatórias na prática.

# entropia_dns.py: ranqueia qnames por entropia de Shannon do subdominio
import sys, math
from collections import Counter

def entropia(s):
    c = Counter(s)
    n = len(s)
    return -sum((v / n) * math.log2(v / n) for v in c.values())

for linha in sys.stdin:
    qname = linha.strip().lower()
    rotulos = qname.split(".")
    if len(rotulos) < 3:
        continue
    sub = "".join(rotulos[:-2])
    if len(sub) >= 20 and entropia(sub) >= 3.5:
        print(f"{entropia(sub):.2f} {len(sub):3d} {qname}")
cat dns.log | zeek-cut query | python3 entropia_dns.py | sort -rn | head -25

A segunda caça conta NXDOMAIN por host e é a consulta mais barata de toda a rotina de rede. A leitura separa dois padrões: muitos domínios distintos falhando sugere DGA ativa, enquanto muitos subdomínios do mesmo domínio falhando sugere lista de subdomínios de canal de C2 ou de túnel, e os dois merecem caminhos de investigação diferentes.

cat dns.log | zeek-cut id.orig_h qtype_name rcode_name query |
  awk '$3 == "NXDOMAIN" { print $1, $4 }' | sort | uniq -c | sort -rn | head -15

A terceira caça mira o túnel por dois lados: tipo de registro incomum em volume e rótulo de subdomínio longo demais para navegação humana. O filtro abaixo isola consultas TXT com primeiro rótulo acima de 40 caracteres, padrão das ferramentas clássicas de túnel.

cat dns.log | zeek-cut id.orig_h query qtype_name |
  awk '$3 == "TXT" { n = split($2, rot, "."); if (length(rot[1]) > 40) print $1, $2 }' |
  sort | uniq -c | sort -rn | head -20

Os falsos positivos conhecidos são finitos e entram no baseline: SPF e DMARC produzem TXT grandes, mas em domínios fixos e conhecidos, com rótulo estável; telemetria de SaaS usa TXT para configuração, com volume constante. Túnel real mostra rótulo que muda a cada consulta, volume crescente e respostas com muitas strings. A versão em SIEM da mesma caça segue abaixo, ajustando os nomes de tabela ao esquema ingerido do ambiente.

// Consultas TXT e NULL por host nas ultimas 24h; ajustar tabela ao esquema ingerido
ZeekDNS
| where TimeGenerated > ago(24h)
| where QueryType in ("TXT", "NULL")
| summarize Consultas = count(), Subdominios = dcount(QueryName) by ClientIP
| where Consultas > 300 or Subdominios > 100

3. Caça em HTTP

O HTTP sobrevive como superfície de caça mesmo em mundo de TLS, porque o proxy corporativo vê o header, o Suricata vê SNI e user agent no handshake, e boa parte do C2 de commodity ainda fala HTTP puro. Três caçadas concentram o retorno: user agent anômalo, path incomum e POST volumétrico. A tabela abaixo resume os sinais de user agent e os falsos positivos que acompanham cada um, base da triagem antes de qualquer consulta.

Sinal no user_agent Leitura típica Falso positivo comum
Vazio ou reduzido a um espaço Ferramenta caseira ou curl sem header Health check de appliance documentado
python-requests, Go-http-client, curl, wget Script ou malware em execução Automação de TI inventariada e aprovada
String antiga de IE6 ou XP em host moderno Kit de phishing ou ferramenta que imita navegador Compatibilidade legada documentada
UA que não casa com o software do host Impressão digital de ferramenta nova Atualização recente de aplicativo corporativo

A primeira consulta ranqueia user agent por frequência; valores raros e genéricos são candidatos diretos. A segunda isola URIs longas, típicas de beacon com dados codificados na query e de exploração com payload em parâmetro.

cat http.log | zeek-cut user_agent | sort | uniq -c | sort -rn | head -30
cat http.log | zeek-cut method uri | awk '$1 == "POST" && length($2) > 250 { print $2 }' | head -20

A terceira caça olha o volume de corpo enviado em POST, filtro de exfiltração e de interação com webshell, que costuma receber corpos grandes em comandos codificados. A leitura cruza cada candidato com o baseline por aplicação: POST de megabytes para API de backup é rotina, POST de megabytes para PHP que nunca recebeu corpo é caso.

cat http.log | zeek-cut method host uri request_body_len |
  awk '$1 == "POST" { print $4, $2, $3 }' | sort -rn | head -15

Paths incomuns complementam o quadro: frequência de URIs únicas por host, proporção de extensões de script nunca vistas no segmento e presença de padrões de probe de scanner como caminhos de CMS em servidores que não rodam CMS. Cada sinal é fraco sozinho; dois ou três sinais no mesmo host no mesmo dia sustentam abertura de caso.

4. Caça em TLS

O TLS virou o protocolo dominante, e por isso os metadados do handshake são a superfície de caça mais valiosa da rede. O JA3 resume versão, lista de cifras, extensões, curvas elípticas e formatos de ponto em um hash MD5 estável por biblioteca cliente; o JA4, mais recente, estrutura a impressão digital em formato legível que inclui presença de SNI e ALPN, e chega por Suricata 7 e plugins. A primeira caça ranqueia ja3 por frequência; a segunda conta quantos hosts distintos usam cada ja3, e o quadrante de interesse é o ja3 raro usado por um único host, que indica ferramenta nova em um ativo específico.

cat ssl.log | zeek-cut ja3 | sort | uniq -c | sort -rn | head -15
cat ssl.log | zeek-cut id.orig_h ja3 | sort -u | awk '{ print $2 }' | sort | uniq -c | sort -n | head -15

A segunda família de caça olha os certificados. O validation_status do ssl.log marca autoassinados e cadeias não verificáveis; o par subject e issuer revela emissores sem reputação e CNs aleatórios; e a validade excessivamente longa é marca registrada de certificado de C2, que ninguém pretende renovar. O filtro abaixo separa os status de erro mantendo apenas o primeiro campo, que não contém espaços, truque simples para evitar desalinhamento no awk.

cat ssl.log | zeek-cut validation_status server_name subject issuer |
  awk '$1 == "self" || $1 == "unable" { print $2, $3, $4 }' |
  sort | uniq -c | sort -rn | head -20

A terceira família compara SNI e certificado. Quando o server_name anunciado no handshake não aparece no subject nem na SAN, o destino está servindo identidade que não bate, padrão de infraestrutura alugada com certificado genérico e de C2 que empresta SNI de serviço legítimo. A comparação abaixo remove o prefixo CN= do subject e lista os pares divergentes, lembrando que certificados multi-domínio exigem leitura da SAN completa para veredicto.

cat ssl.log | zeek-cut server_name subject |
  awk '{ cn = $2; sub(/^CN=/, "", cn); if (cn != "" && $1 != cn) print $1, $2 }' |
  sort | uniq -c | sort -rn | head -20

Cifras legadas fecham o quadro: suites TLS 1.0 sobrevivendo em handshake novo, conjuntos de cifra que não pertencem a nenhum navegador moderno e curvas incomuns denunciam clientes escritos à mão. O adversário sofisticado imita o JA3 do Chrome, e aí o desempate vem do comportamento: cadência, tamanho de resposta e ausência de navegação prévia distinguem ferramenta de navegador mesmo com fingerprint clonado.

5. Correlacionando DNS, HTTP e TLS no Mesmo Caso

O adversário encadeia protocolos, e a caça madura encadeia consultas. O quadro abaixo amarra a etapa do adversário, o protocolo que a denuncia, o campo observável e a técnica ATT&CK correspondente, servindo de índice para o catálogo de hunts do ambiente.

Etapa do adversário Protocolo Campo que denuncia ATT&CK
Geração de domínio aleatório DNS Entropia e comprimento do qname T1568.002
Tentativas de resolução falhas DNS NXDOMAIN em massa por host T1568.002
Túnel de dados ou comando DNS TXT e NULL com rótulos longos T1071.004
C2 em HTTP com cliente não padrão HTTP user_agent e cadência T1071.001
Upload de dados HTTP request_body_len anômalo T1041
C2 em TLS com fingerprint novo TLS ja3 ou ja4 fora do baseline T1071.001
Infraestrutura própria TLS Certificado autoassinado, SNI divergente T1583

O caso costurado da biblioteca mostra a cadeia em uma linha do tempo. A estação 10.20.7.31 consulta 47 domínios NXDOMAIN de 12 a 15 caracteres em nove minutos, todos com entropia acima de 3,8; um deles resolve; minutos depois surge handshake TLS para esse domínio com ja3 ausente do baseline e certificado autoassinado com CN de 16 caracteres aleatórios; em seguida, conexões a cada 300 segundos com respostas 200 e corpos pequenos. O veredicto é malware com DGA e fallback para C2 único, e as ações seguem o roteiro: bloquear o padrão de domínio no resolver com expressão regular, isolar o host, extrair o ja3 para watchlist e converter a cadeia em duas detecções permanentes no capítulo 18, uma de volume de NXDOMAIN por host e outra de ja3 novo por segmento.

6. Erros Comuns e Pontos de Atenção

  • Usar entropia sozinha como detector de DGA; efeito: CDN e serviços legítimos de alta aleatoriedade viram ruído; correção: combinar comprimento, volume por domínio, idade do domínio e reputação antes de decidir.
  • Descartar NXDOMAIN como lixo de log; efeito: perda do sinal mais barato de DGA e de túnel; correção: manter baseline de rcode por host com limiar por segmento.
  • Tratar user agent como identidade; efeito: atribuição falsa, porque o header se falsifica em uma linha; correção: cruzar sempre com ja3 e cadência, que custam mais para mudar.
  • Comparar SNI apenas com o CN; efeito: falso positivo em certificados multi-domínio legítimos; correção: ler a SAN completa e o histórico do certificado antes de escalonar.
  • Aplicar limiares absolutos entre ambientes; efeito: consulta calibrada em um cliente falha no outro; correção: calibrar por segmento com janela de 30 dias e registrar os limiares no catálogo.
  • Ignorar que a maioria do tráfego é TLS; efeito: caça de HTTP cobre só a ponta visível e o adversário passa pela outra; correção: priorizar metadados de ssl e, onde existir, proxy que loga SNI e user agent.
  • Deixar limiares sem versionamento; efeito: regressão silenciosa após ajustes e perda do histórico de calibração; correção: catálogo de hunts com data, dono, limiar e resultado da última execução.

7. Integração com o Restante da Biblioteca

As notas 12 e 13 entregam sensor e escala; esta nota entrega a camada de campo por protocolo, e os três juntos formam o bloco de rede do capítulo 08. Os domínios e hashes descobertos aqui alimentam o ciclo de vida de IOC do capítulo 03, e a leitura de entropia e de infraestrutura nova conversa com a análise de domínios e com o Certificate Transparency da seção 06 do mesmo capítulo. A justificativa teórica dos fingerprints protocolares está na Pirâmide de Dor do capítulo 04, e a conversão das caças em detecções permanentes é o tema do capítulo 18, com as salvaguardas de rede no TH.12 e a qualidade de coleta no DAT.2 do capítulo 15.

Um ganho operacional fecha a nota: mantenha por protocolo uma folha de referência com as cinco consultas que respondem à maioria das caçadas, entropia e NXDOMAIN no DNS, user agent e POST no HTTP, ja3 e certificado no TLS, e revise os limiares a cada trimestre com o baseline corrente. A vantagem composta vem da repetição: a mesma consulta rodada em vários ambientes gera distribuições comparáveis, e essas distribuições transformam a calibração subjetiva em tabela de referência da biblioteca, reduzindo o custo de caçar em qualquer ambiente novo.