Módulo 10 de 12

Módulo 10: Análisis de red y detección de C2

Módulo 10: Análisis de red y detección de C2

Aviso ético y legal: las técnicas de este módulo (captura de tráfico, análisis de PCAP, fingerprinting TLS, detección de beaconing) se explican exclusivamente para su uso en investigaciones de respuesta a incidentes autorizadas, ejercicios de laboratorio con capturas propias o cedidas legalmente, y entornos de test controlados (home lab, CTF, rangos de entrenamiento). Interceptar o analizar tráfico de redes o sistemas sobre los que no tienes autorización expresa constituye un delito en España (arts. 197 y 197 bis del Código Penal) y en la práctica totalidad de jurisdicciones. Aplica siempre cadena de custodia sobre las capturas y respeta la normativa de protección de datos (RGPD) al tratar tráfico que pueda contener PII.

Qué aprenderás

  • A capturar y analizar tráfico de red con Wireshark usando filtros de display reales, seguir flujos TCP/HTTP y exportar objetos transferidos.
  • A trabajar en línea de comandos con tshark para análisis a escala y extracción de campos en entornos sin GUI.
  • A desplegar Zeek y a interpretar sus logs (conn.log, dns.log, http.log, ssl.log, x509.log, files.log) como fuente de verdad para IR de red.
  • A detectar beaconing de C2 mediante análisis de periodicidad e intervalos, con y sin la ayuda de RITA.
  • A aplicar fingerprinting TLS con JA3/JA3S y JARM para identificar clientes y servidores maliciosos aunque cambien de IP o dominio.
  • A reconocer los perfiles maleables de Cobalt Strike en el tráfico de red.
  • A detectar DNS tunneling por entropía, longitud de subdominios y volumen anómalo de consultas TXT.
  • A identificar patrones de exfiltración de datos por volumen, horario y destino.
  • A escribir y afinar reglas básicas de Suricata/Snort para generar alertas sobre estos indicadores.
  • A aplicar la Pirámide del Dolor de David Bianco para priorizar qué indicadores de red merecen la pena perseguir.

1. El análisis de red en la respuesta a incidentes

En un IR (Incident Response), el tráfico de red es una de las fuentes de evidencia más difíciles de manipular por un atacante a posteriori: si capturaste el PCAP, ahí queda. A diferencia de los logs de endpoint, que un adversario con privilegios puede borrar o alterar, una captura de red obtenida de un TAP, un SPAN port o un sensor Zeek/Suricata desplegado con antelación es una fuente casi inmutable. Por eso el NSM (Network Security Monitoring) es un pilar de FOR572 y de cualquier programa maduro de detección.

El objetivo de este módulo es que sepas responder, con evidencia, a preguntas como: ¿hay un host de la red hablando con infraestructura de C2? ¿durante cuánto tiempo lleva haciéndolo? ¿ha exfiltrado datos? ¿qué herramienta de C2 es (Cobalt Strike, Sliver, Mythic, algo custom)?

2. Wireshark: filtros de display esenciales para IR

Wireshark sigue siendo la herramienta de referencia para el análisis interactivo de un PCAP. La clave para un analista es dominar los filtros de display (distintos de los filtros de captura BPF) que permiten aislar tráfico de interés en segundos.

# Ver solo peticiones HTTP (no todo el tráfico HTTP, solo las requests)
http.request

# Ver el Client Hello de TLS (handshake type 1) — clave para JA3
tls.handshake.type == 1

# Ver el Server Hello de TLS (handshake type 2) — clave para JA3S
tls.handshake.type == 2

# Ver el certificado presentado por el servidor (handshake type 11)
tls.handshake.type == 11

# Todas las consultas y respuestas DNS
dns

# Filtrar por una IP concreta en cualquier sentido
ip.addr == 203.0.113.50

# Solo tráfico ORIGINADO por un host concreto (ojo a la dirección)
ip.src == 10.0.5.23

# Paquetes SYN (inicio de conexión TCP) — útil para ver escaneos o beacons
tcp.flags.syn == 1 and tcp.flags.ack == 0

# Filtrar por longitud de host DNS (posibles subdominios de tunneling)
dns.qry.name and strlen(dns.qry.name) > 50

# Ver solo las respuestas DNS de tipo TXT (habitual en tunneling)
dns.qry.type == 16

# Combinar: Client Hello de TLS hacia un puerto no estándar
tls.handshake.type == 1 and tcp.port != 443

# Ver el SNI (Server Name Indication) de cada Client Hello — dominio real solicitado
tls.handshake.extensions_server_name

# Filtrar por JA3 concreto (requiere el plugin JA3 activado en Wireshark)
tls.handshake.ja3 == "e7d705a3286e19ea42f587b344ee6865"

# Tráfico HTTP con User-Agent sospechoso o vacío
http.user_agent == "" or http.user_agent contains "Mozilla/4.0"

2.1 Seguir flujos: Follow TCP/HTTP Stream

Sobre cualquier paquete, botón derecho > Follow > TCP Stream (o HTTP Stream si el paquete ya fue clasificado como HTTP) reconstruye la conversación completa cliente-servidor en orden, coloreando cada lado. Es la forma más rápida de leer el contenido real de un beacon HTTP de C2: headers, cuerpo de la petición, respuesta del servidor. Para tráfico cifrado (TLS) esto no revela el contenido salvo que dispongas de las claves de sesión (variable de entorno SSLKEYLOGFILE capturada en el endpoint infectado, o certificado privado si hicieras MITM en laboratorio).

Atajo de teclado: Ctrl+Alt+Shift+T para TCP Stream. El menú permite exportar el stream como texto plano, C array, hex dump o los datos en crudo — útil para volcar un payload sospechoso a disco y analizarlo aparte.

2.2 Exportar objetos transferidos

Menú File > Export Objects > HTTP (o SMB, o TFTP) lista todos los ficheros transferidos en ese protocolo dentro de la captura y permite guardarlos a disco individualmente o todos de golpe. Esto es fundamental cuando un beacon HTTP descarga un stager, un payload de segunda fase o exfiltra un ZIP: en lugar de reconstruirlo manualmente del stream, Wireshark ya te lo entrega como fichero. Recuerda tratar cualquier objeto exportado como potencialmente malicioso: aislarlo, no ejecutarlo, calcular su hash (sha256sum) antes de subirlo a VirusTotal.

2.3 Estadísticas de conversaciones

Menú Statistics > Conversations agrupa todo el tráfico por par de endpoints (IPv4, IPv6, TCP, UDP) mostrando paquetes, bytes, duración y — crucialmente para beaconing — puedes activar la columna de Duration y ordenar por número de paquetes para localizar conversaciones anormalmente largas y regulares con pocos bytes por paquete, el patrón típico de un canal de C2 en reposo. Statistics > Endpoints da la vista inversa, por host individual. Ambas ventanas permiten aplicar el filtro de display activo con la casilla «Limit to display filter», lo que te deja cruzar, por ejemplo, solo las conversaciones TLS hacia un ASN concreto.

3. tshark: Wireshark en línea de comandos

tshark comparte motor de disección con Wireshark pero es scriptable, ideal para procesar PCAPs grandes, automatizar extracción de campos o integrarlo en pipelines de threat hunting.

# Aplicar un filtro de display y extraer campos concretos en formato tabular
tshark -r captura.pcap -Y "http.request" -T fields -e frame.time -e ip.src -e ip.dst -e http.host -e http.request.uri

# Extraer todos los Client Hello con su JA3 (requiere tshark reciente con soporte JA3)
tshark -r captura.pcap -Y "tls.handshake.type==1" -T fields -e ip.src -e ip.dst -e tls.handshake.extensions_server_name -e tls.handshake.ja3

# Listar todas las consultas DNS únicas resueltas
tshark -r captura.pcap -Y "dns.flags.response==0" -T fields -e dns.qry.name | sort -u

# Extraer todas las conversaciones TCP con duración y bytes (para detectar beaconing)
tshark -r captura.pcap -q -z conv,tcp

# Volcar solo tráfico hacia un host y puerto concreto a un nuevo pcap (triage)
tshark -r captura.pcap -Y "ip.addr==203.0.113.50 and tcp.port==443" -w sospechoso_c2.pcap

# Estadísticas de protocolo (qué % del tráfico es cada cosa)
tshark -r captura.pcap -q -z io,phs

# Extraer certificados x509 vistos (para pivotar por Issuer/Subject/SHA1 del cert)
tshark -r captura.pcap -Y "tls.handshake.type==11" -T fields -e ip.dst -e x509sat.uTF8String -e x509af.serialNumber

# Contar cuántas veces se repite cada intervalo de tiempo entre paquetes de un mismo flujo (aprox. de beaconing)
tshark -r captura.pcap -Y "ip.addr==203.0.113.50" -T fields -e frame.time_epoch | awk 'NR>1{print $1-prev} {prev=$1}'

La combinación -T fields -e campo1 -e campo2 es la más usada para volcar CSV-like a herramientas posteriores (Python/pandas, RITA, hojas de cálculo). Añade -E header=y -E separator=, para un CSV con cabecera limpio.

4. Zeek: la capa de logs para NSM

Zeek (antes Bro) no es un sniffer interactivo como Wireshark: es un motor de análisis de red que procesa tráfico (en vivo o desde PCAP) y genera logs estructurados por protocolo, pensados para consultarse, indexarse en un SIEM o correlacionarse en bloque. Es la herramienta de referencia en NSM a escala porque convierte terabytes de PCAP en logs manejables en TSV/JSON.

# Procesar un PCAP con Zeek y generar los logs en el directorio actual
zeek -r captura.pcap

# Ídem pero con salida en JSON (más fácil de ingerir en Elastic/Splunk)
zeek -r captura.pcap LogAscii::use_json=T

# Consultar conn.log con zeek-cut (extrae columnas por nombre)
cat conn.log | zeek-cut id.orig_h id.resp_h id.resp_p duration orig_bytes resp_bytes

# Filtrar conexiones largas y con pocos bytes (candidato a beaconing en reposo)
cat conn.log | zeek-cut id.orig_h id.resp_h duration orig_bytes resp_bytes | awk '$3 > 3600 && $4 < 5000'

# Ver dominios consultados por DNS y su tipo de registro
cat dns.log | zeek-cut query qtype_name answers

# Ver todos los SNI de TLS y su JA3/JA3S (si el paquete Zeek JA3 está cargado)
cat ssl.log | zeek-cut id.orig_h server_name ja3 ja3s

# Ver certificados x509 vistos, con su Issuer y validez
cat x509.log | zeek-cut certificate.subject certificate.issuer certificate.not_valid_before certificate.not_valid_after

# Ver ficheros extraídos/transferidos y su tipo MIME
cat files.log | zeek-cut tx_hosts rx_hosts filename mime_type total_bytes

4.1 Qué buscar en cada log de Zeek

Log de Zeek Qué contiene Qué indicio de C2/exfiltración buscar
conn.log Metadatos de cada conexión (IPs, puertos, protocolo, duración, bytes en cada sentido, estado de la conexión — campo conn_state). Conexiones muy repetidas al mismo destino con duración e intervalo casi idénticos (beaconing); conn_state = S0 masivo (intentos fallidos, posible escaneo); relación orig_bytes/resp_bytes muy asimétrica y sostenida en el tiempo (exfiltración lenta); conexiones a puertos altos no habituales.
dns.log Cada consulta DNS: dominio solicitado, tipo de registro, TTL, respuestas. Subdominios muy largos o con alta entropía (aleatorios); volumen alto de consultas tipo TXT, NULL o CNAME hacia el mismo dominio raíz; NXDOMAIN masivos (DGA — Domain Generation Algorithm); TTL anormalmente bajo (fast-flux).
http.log Método, URI, User-Agent, código de respuesta, Content-Length en ambos sentidos, referrer. User-Agent inconsistente con el resto del tráfico del host o hardcodeado de una herramienta (curl, python-requests, o UA por defecto de C2); URIs con patrón fijo repetido (checkin de beacon); Content-Length de request muy superior al de una petición normal (exfil vía POST); ausencia de Referer en peticiones que deberían tenerlo.
ssl.log SNI solicitado, versión de TLS, cifra negociada, JA3/JA3S (con el paquete correspondiente cargado), si la validación del certificado tuvo éxito. JA3 asociado a malware conocido (Cobalt Strike, Metasploit, herramientas ofensivas); SNI que no resuelve por DNS previo en el mismo host (dominio hardcodeado o fronting); validation_status con error de certificado ignorado por el cliente.
x509.log Detalle de certificados vistos: Subject, Issuer, número de serie, validez, SAN (Subject Alternative Names). Certificados autofirmados o con Issuer = Subject; validez extremadamente larga o corta; SAN con dominios genéricos tipo *.example.com reutilizados en varios C2 conocidos; certificados por defecto de frameworks ofensivos (p. ej. el cert por defecto de Cobalt Strike antes de personalizar el perfil).
files.log Ficheros vistos en cualquier protocolo soportado (HTTP, SMB, FTP…): hashes, tipo MIME, tamaño, si fue extraído a disco. Ejecutables (application/x-dosexec) descargados desde dominios recién vistos; ficheros comprimidos/cifrados de tamaño grande subidos (no descargados) hacia fuera — patrón de exfiltración; hash coincidente con IOC conocido.

5. Detección de beaconing de C2

El beaconing es el patrón de comunicación más característico del C2 post-explotación: el implante llama periódicamente a su servidor (check-in) para recibir tareas, típicamente con un intervalo (sleep time) configurado más un jitter (variación aleatoria en % para evitar un patrón perfectamente regular y así despistar la detección naive).

La forma manual de detectarlo es extraer los timestamps de todas las conexiones de un host hacia un destino concreto, calcular los deltas entre conexiones consecutivas y comprobar si la desviación estándar de esos deltas es pequeña en relación a la media — es decir, si el intervalo es «casi constante». Un jitter del 20-30% sigue produciendo una distribución muy reconocible frente a tráfico humano, que es mucho más irregular.

# Extraer timestamps de todas las conexiones de un host sospechoso a un destino
cat conn.log | zeek-cut ts id.orig_h id.resp_h | awk '$2=="10.0.5.23" && $3=="203.0.113.50"' | cut -f1 > timestamps.txt

# Calcular deltas entre conexiones consecutivas (en segundos)
awk 'NR>1{print $1-prev} {prev=$1}' timestamps.txt

# Media y desviación estándar de los deltas con awk
awk '{sum+=$1; sumsq+=$1*$1; n++} END{m=sum/n; print "media="m, "stdev="sqrt(sumsq/n - m*m)}' deltas.txt

5.1 RITA (Real Intelligence Threat Analytics)

RITA automatiza este análisis a escala sobre logs de Zeek. Ingiere los logs, los almacena en una base de datos (MongoDB en versiones clásicas; versiones más recientes usan otros backends) y calcula, para cada par de hosts que se comunican, una puntuación de beaconing basada en la regularidad de los intervalos, la consistencia del tamaño de los datos transferidos y el número de conexiones — cuanto más cerca de 1.0, más probable que sea beaconing automatizado.

# Importar logs de Zeek de un dataset a RITA
rita import /ruta/a/logs-zeek nombre_dataset

# Ejecutar el análisis de beaconing sobre el dataset importado
rita show-beacons nombre_dataset

# Ver también beaconing sobre TLS específicamente (usa SNI/JA3)
rita show-beacons-tls nombre_dataset

# Long connections: conexiones inusualmente largas (canales interactivos, no solo check-ins)
rita show-long-connections nombre_dataset

# Dominios más consultados — útil para cruzar con posible DGA o dominios de baja reputación
rita show-exploded-dns nombre_dataset

La salida de show-beacons incluye columnas como Score, Source IP, Destination IP, número de conexiones, intervalo más frecuente (Top_Interval) y su rango de tamaños. Un analista debe priorizar por Score descendente pero validar manualmente contra conn.log/PCAP: RITA reduce el espacio de búsqueda, no sustituye el análisis.

5.2 JA3, JA3S y JARM: fingerprinting TLS

JA3 (desarrollado por Salesforce) es un hash MD5 calculado a partir de los parámetros que el cliente ofrece en el Client Hello de TLS: versión de TLS, lista de cipher suites, lista de extensiones, curvas elípticas soportadas y formatos de punto de curva elíptica, concatenados en un orden fijo y hasheados. Como estos parámetros dependen de la librería TLS y de cómo la implementa el software (no del dominio ni de la IP), el mismo binario de malware genera el mismo JA3 aunque cambie de C2 server, dominio o IP entre campañas — de ahí su enorme valor como IOC persistente.

JA3S es el equivalente para el servidor, calculado sobre el Server Hello (versión negociada, cipher elegida, extensiones del servidor). La combinación JA3+JA3S de una sesión identifica de forma bastante fiable tanto al cliente como al framework de C2 del lado servidor cuando ambos son conocidos.

# Obtener JA3 desde una captura con tshark (requiere Wireshark/tshark reciente)
tshark -r captura.pcap -Y "tls.handshake.type==1" -T fields -e ip.src -e ip.dst -e tls.handshake.ja3

# Obtener JA3S del lado servidor
tshark -r captura.pcap -Y "tls.handshake.type==2" -T fields -e ip.src -e ip.dst -e tls.handshake.ja3s

# Con la herramienta standalone ja3 (python) sobre un pcap
python3 ja3.py --json captura.pcap

# Cruzar un JA3 obtenido contra listas de IOC conocidos (ejemplo con grep sobre un feed local)
grep "e7d705a3286e19ea42f587b344ee6865" ja3-fingerprints-conocidos.csv

JARM, desarrollado por Salesforce como evolución del concepto, va en dirección opuesta a JA3S: en lugar de observar pasivamente un handshake real, activamente envía 10 Client Hellos distintos y cuidadosamente construidos a un servidor y agrega las 10 respuestas en un único hash de 62 caracteres. Esto crea una huella del stack TLS del servidor (versión, orden de preferencia de cifras, comportamiento ante configuraciones no estándar) independiente del certificado o dominio que presente. JARM es especialmente útil para identificar servidores de C2 por su configuración TLS por defecto (p. ej., Cobalt Strike Team Server, Mythic, Sliver, Metasploit) antes incluso de que se sepa qué dominio están usando en una campaña concreta.

# Escanear un host con la herramienta JARM oficial
python3 jarm.py 203.0.113.50 -p 443

# Escanear una lista de hosts y volcar a CSV
python3 jarm.py -i lista_ips.txt -o resultados_jarm.csv

5.3 Perfiles maleables de Cobalt Strike

Cobalt Strike, el framework de post-explotación comercial más usado (y también el más «prestado» por adversarios en su versión crackeada), permite a los operadores definir perfiles maleables de C2 (Malleable C2 profiles): ficheros de configuración que controlan cómo se ve el tráfico HTTP/HTTPS/DNS del beacon — headers, User-Agent, forma del URI, dónde se esconden los datos dentro de la petición (parámetros, cookies, cuerpo), e incluso el JA3/JA3S si se fuerza una configuración TLS concreta. El objetivo es que el tráfico se camufle como legítimo (por ejemplo, imitando peticiones a un CDN o a Slack).

Pese a esto, hay indicios recurrentes: el beaconing con jitter constante sigue siendo estadísticamente detectable con RITA por muy bien camuflado que esté el contenido HTTP, ya que el perfil maleable solo cambia la forma del paquete, no la regularidad temporal; el JARM del Team Server puede seguir coincidiendo con el valor «de fábrica» si el operador no tocó la pila TLS subyacente (más costoso que cambiar el perfil HTTP); la estructura de las URIs de checkin/tasking, aunque personalizable, suele reutilizarse sin cambios en perfiles públicos que circulan en repositorios de red team, por lo que merece la pena mantener una colección de perfiles conocidos para contrastar patrones; el certificado en https-certificate puede seguir siendo el autofirmado por defecto si no se sustituyó por uno de una CA pública; y el uso de named pipes / SMB beacon para movimiento lateral interno aparece en conn.log como tráfico SMB (puerto 445) entre hosts internos con nombres de pipe poco habituales, visible también vía el analizador DCE-RPC/SMB de Zeek.

6. DNS tunneling

El DNS tunneling abusa del hecho de que las consultas DNS casi siempre atraviesan cortafuegos sin restricción (es un protocolo «de confianza» por defecto) para crear un canal de datos bidireccional codificando información en los subdominios consultados y recibiendo datos en las respuestas (habitualmente en registros TXT, aunque también NULL, CNAME o incluso A/AAAA con datos codificados en la propia IP de respuesta).

Indicios clave a buscar en dns.log o con Wireshark/tshark: longitud del subdominio anormalmente alta (un FQDN normal rara vez supera los 30-40 caracteres; el tunneling, al codificar datos en base32/base64 en el subdominio, tiende a acercarse al límite técnico de 253 caracteres totales / 63 por label); alta entropía (los subdominios de tunneling parecen cadenas aleatorias frente a los subdominios humanos, pronunciables o con patrones reconocibles); volumen de consultas TXT muy superior a lo habitual hacia el mismo dominio raíz (la mayoría de tráfico DNS legítimo es tipo A/AAAA; un pico sostenido de TXT es señal fuerte); alta tasa de consultas por unidad de tiempo hacia el mismo dominio raíz, muy por encima de lo que generaría una resolución normal que se cachea; y NXDOMAIN masivos combinados con lo anterior, indicativo de exploración/DGA más que de tunneling puro, pero que merece la misma atención.

# Calcular la longitud de cada subdominio consultado y ordenar de mayor a menor
cat dns.log | zeek-cut query | awk '{print length($0), $0}' | sort -rn | head -30

# Contar consultas TXT por dominio raíz (aproximación simple)
cat dns.log | zeek-cut query qtype_name | awk '$2=="TXT"' | awk -F. '{print $(NF-1)"."$NF}' | sort | uniq -c | sort -rn

# Filtro de Wireshark para localizar subdominios largos con alta probabilidad de tunneling
dns.qry.name and strlen(dns.qry.name) > 50

# Filtro para ver solo respuestas TXT
dns.qry.type == 16 and dns.flags.response == 1

# Cálculo de entropía de Shannon sobre los subdominios con un script Python rápido
python3 -c "
import math, collections, sys
def entropy(s):
    p = collections.Counter(s)
    n = len(s)
    return -sum((c/n) * math.log2(c/n) for c in p.values())
for line in sys.stdin:
    d = line.strip()
    if d:
        print(round(entropy(d), 2), d)
" < subdominios.txt | sort -rn | head -20

Herramientas específicas como dnstwist (más orientada a typosquatting) o análisis con Zeek + scripts custom que calculen entropía en tiempo real son habituales en producción. Suricata también incorpora reglas de la comunidad (ET INFO / ET POLICY) que disparan sobre patrones de tunneling conocidos (iodine, dnscat2, DNSCat, etc.).

7. Exfiltración de datos: volumen, horario y destino

Además del canal (HTTP, DNS, u otros como ICMP tunneling o exfiltración vía servicios cloud legítimos), tres dimensiones ayudan a distinguir exfiltración de tráfico normal. El volumen: en conn.log, la relación entre orig_bytes (lo que envía el host interno) y resp_bytes (lo que recibe) suele ser muy asimétrica en navegación normal (se descarga mucho más de lo que se sube); una inversión sostenida hacia el mismo destino es señal clásica de exfiltración, sobre todo agregada a lo largo de varias conexiones. El horario: transferencias grandes fuera del horario laboral habitual, o coincidentes con baja actividad de vigilancia (madrugada, festivos), son sospechosas, especialmente si el host implicado no tiene motivo operativo para estar activo entonces. Y el destino: IPs/ASN sin relación de negocio previa, geolocalización inconsistente con proveedores habituales, o — cada vez más común como evasión — servicios cloud legítimos (buckets de almacenamiento, Pastebin, Discord, Telegram, APIs de Dropbox/Google Drive) usados como "living off trusted sites" para mezclarse con tráfico permitido por política.

# Conexiones donde el host interno sube más de lo que baja, agregadas por destino
cat conn.log | zeek-cut id.orig_h id.resp_h orig_bytes resp_bytes | awk '$3 > $4 && $3 > 1000000' | sort -k3 -rn

# Agregación total de bytes subidos por host interno hacia cada destino externo en todo el periodo
cat conn.log | zeek-cut id.orig_h id.resp_h orig_bytes | awk '{sum[$1","$2]+=$3} END{for (k in sum) print sum[k], k}' | sort -rn | head -20

# Filtro Wireshark: conexiones con mucho más tráfico saliente que entrante en la sesión
tcp.analysis.bytes_in_flight and ip.src == 10.0.5.23

8. IDS: Suricata y Snort

Suricata (y su predecesor conceptual, Snort) permite generar alertas en tiempo real basadas en firmas y en tráfico anómalo, complementando el análisis retrospectivo de PCAP/Zeek con detección "en caliente".

# Ejecutar Suricata contra un PCAP en modo offline con un ruleset cargado
suricata -r captura.pcap -c /etc/suricata/suricata.yaml -l /var/log/suricata/

# Ver las alertas generadas en formato legible
cat /var/log/suricata/fast.log

# Consultar eve.json (formato JSON, más rico) filtrando solo alertas
jq 'select(.event_type=="alert")' /var/log/suricata/eve.json

# Ejemplo de regla Suricata para detectar un JA3 concreto asociado a C2 conocido
alert tls any any -> any any (msg:"Posible C2 - JA3 conocido de Cobalt Strike"; ja3.hash; content:"e7d705a3286e19ea42f587b344ee6865"; sid:9000001; rev:1;)

# Ejemplo de regla para detectar subdominios DNS anormalmente largos (posible tunneling)
alert dns any any -> any any (msg:"Posible DNS tunneling - subdominio largo"; dns.query; pcre:"/^.{50,}$/"; sid:9000002; rev:1;)

# Ejemplo de regla para detectar volumen alto de consultas TXT hacia el mismo host en poco tiempo
alert dns any any -> any 53 (msg:"Volumen alto de consultas TXT - posible exfil DNS"; dns.query; content:"TXT"; threshold:type both, track by_src, count 50, seconds 60; sid:9000003; rev:1;)

Suricata también soporta extracción y logging de JA3/JA3S de forma nativa (habilitando ja3-fingerprints: yes en suricata.yaml), lo que permite construir reglas de detección basadas en fingerprint sin necesidad de post-procesar el PCAP con tshark.

9. La Pirámide del Dolor aplicada a indicadores de red

La Pirámide del Dolor (David Bianco) clasifica los indicadores según cuánto "duele" al adversario que los detectes y bloquees — es decir, cuánto esfuerzo le cuesta cambiarlos. De abajo arriba: los valores hash (trivial — recompilar o repackar el payload en segundos) y las direcciones IP (fácil — rotar infraestructura con un VPS o CDN nuevo) son los indicadores más baratos de esquivar; los nombres de dominio (sencillo) cuestan algo más, pero con DGA o dominios baratos siguen siendo asequibles. A partir de aquí sube el coste real: los artefactos de red (molesto) — User-Agent específico, estructura de URI de un perfil maleable, combinación JA3/JA3S — obligan al operador a reconfigurar el perfil de C2 o el stack TLS, algo que muchos no hacen por pereza o reutilización de configuraciones; las herramientas (desafiante) — el patrón de beaconing con su intervalo/jitter característico, la forma en que el framework estructura el tasking — obligan a cambiar de herramienta o reescribirla sustancialmente; y en la cima, los TTPs (máximo dolor) — el patrón operativo completo: "este actor usa beaconing HTTPS con intervalo largo, exfiltra por lotes nocturnos hacia almacenamiento cloud, y pivota por SMB named pipes" — atacan directamente su metodología, obligando a rediseñar el modus operandi entero.

La lección práctica para el analista: bloquear una IP o un dominio da una victoria táctica inmediata, pero si te quedas ahí, el adversario vuelve en minutos con infraestructura nueva. Invertir en detectar el patrón de beaconing en sí (RITA), el fingerprint TLS de la herramienta (JA3/JARM) y el comportamiento de exfiltración (volumen/horario/destino agregado) sube al adversario mucho más arriba en la pirámide y genera detecciones que sobreviven a la rotación de infraestructura.

10. Laboratorio: identificar beaconing de C2 en un PCAP de ejemplo

Objetivo: dado un PCAP de una red comprometida (puedes usar capturas públicas de referencia como las del repositorio de Malware Traffic Analysis, o generar tu propio tráfico con un C2 en un laboratorio aislado tipo Cobalt Strike trial / Sliver / Mythic contra una VM víctima en una red interna sin salida a Internet real), sigue estos pasos:

  1. Visión general. Abre el PCAP en Wireshark y revisa Statistics > Protocol Hierarchy; cruza con tshark -r captura.pcap -q -z io,phs.
  2. Identifica conversaciones sostenidas. En Statistics > Conversations (TCP), ordena por número de paquetes y duración. Busca pares IP con muchas conexiones cortas y regulares hacia el mismo destino externo — candidato a beaconing.
  3. Procesa con Zeek. Ejecuta zeek -r captura.pcap para obtener conn.log, dns.log, ssl.log. Extrae con zeek-cut las conexiones del host sospechoso hacia el destino candidato y calcula los deltas entre timestamps (sección 5).
  4. Confirma regularidad con RITA (si está disponible): importa los logs y ejecuta rita show-beacons. Anota Score y Top_Interval del par sospechoso.
  5. Extrae el fingerprint TLS. Con tshark -Y "tls.handshake.type==1" obtén el JA3 del cliente y compáralo contra un feed de JA3 conocidos de herramientas ofensivas (p. ej. trisulnsm/ja3prints o abuse.ch). Si tienes acceso al servidor (en laboratorio, tu propio C2 server), calcula también el JARM.
  6. Inspecciona el contenido del beacon. Si el tráfico es HTTP en claro (o dispones de SSLKEYLOGFILE), usa Follow > HTTP Stream sobre una conexión: ¿URI fija? ¿cookies con datos codificados? ¿User-Agent hardcodeado?
  7. Evalúa exfiltración. Revisa si, además del beaconing regular, hay picos puntuales de orig_bytes mucho mayores que el resto — indicativo de que algún check-in subió datos robados en lugar de solo hacer polling vacío.
  8. Documenta el hallazgo siguiendo la Pirámide del Dolor: no te quedes en "la IP X es maliciosa" — documenta también el JA3, el intervalo de beaconing con su jitter aproximado, y el patrón de URI/headers, para que la detección sobreviva a un cambio de infraestructura del adversario.

11. Errores comunes

  • Fijarse solo en IPs o dominios como IOC y dar el caso por cerrado al bloquearlos, sin extraer JA3, patrón de beaconing o estructura del tráfico — el adversario rota infraestructura y vuelve sin ser detectado.
  • Ignorar el patrón temporal: mirar conexiones de forma aislada sin agregarlas por par de hosts a lo largo del tiempo hace invisible el beaconing, que solo se revela al observar la regularidad entre múltiples eventos.
  • Confiar en el puerto para identificar el protocolo: asumir que todo lo que va por el 443 es HTTPS legítimo, o descartar tráfico C2 que corre deliberadamente sobre el 80/443 para camuflarse.
  • No verificar el JA3 en contexto: coincide con la librería TLS usada, no es 100% exclusivo de una herramienta — puede compartirse entre curl, Python requests y algún malware si usan la misma pila. Hay que correlacionar antes de concluir.
  • Analizar el PCAP entero manualmente sin Zeek/RITA como capa de agregación previa en capturas grandes, lo que hace inviable detectar patrones estadísticos como el beaconing a simple vista.
  • Olvidar el horario y el volumen agregado en la búsqueda de exfiltración, centrándose solo en paquetes individuales en lugar del total transferido por host/destino a lo largo del incidente.
  • No aislar ni tratar como potencialmente activos los objetos exportados (ejecutables, scripts) — deben tratarse con las mismas precauciones que cualquier muestra de malware.

12. Ejercicio

Se te entrega un PCAP de 45 minutos capturado en el segmento de red de un puesto de trabajo tras una sospecha de compromiso (phishing con macro). Con las herramientas de este módulo:

  1. Genera los logs de Zeek y localiza, usando conn.log, el par de hosts (interno/externo) con mayor número de conexiones cortas y repetidas.
  2. Calcula el intervalo medio y la desviación estándar de esas conexiones. ¿Es compatible con beaconing (intervalo casi constante con jitter moderado) o con tráfico humano (irregular)?
  3. Extrae el JA3 del Client Hello de esas conexiones con tshark. Documenta el valor obtenido.
  4. Revisa dns.log: ¿hay alguna consulta previa a la IP de destino, o el dominio/IP está hardcodeado en el implante (sin resolución DNS visible desde ese host)?
  5. Con conn.log, calcula el total de orig_bytes acumulado a lo largo de la captura hacia ese destino. ¿Hay algún pico que rompa el patrón de tráfico "vacío" de un simple check-in?
  6. Redacta un informe breve de 10-15 líneas con los indicadores encontrados, clasificados según la Pirámide del Dolor, y una recomendación de contención y de reglas Suricata a desplegar (incluye al menos una regla basada en JA3 y una basada en el intervalo/volumen).

Preguntas frecuentes

¿Cuál es la diferencia práctica entre un filtro de captura y un filtro de display en Wireshark?

El filtro de captura (sintaxis BPF, tipo tcp port 443) se aplica antes de escribir el paquete a disco o memoria — reduce qué se captura y no se puede cambiar después sin recapturar. El filtro de display (sintaxis propia de Wireshark, tipo tls.handshake.type==1) se aplica después, sobre una captura ya guardada, y puedes cambiarlo tantas veces como quieras sin perder datos. En IR casi siempre capturas todo (o usas un filtro de captura muy amplio) y refinas con filtros de display, precisamente para no perder evidencia por un filtro de captura mal pensado.

¿Puede un atacante evadir la detección por JA3 simplemente cambiando algún parámetro del handshake?

Sí, en teoría — JA3 depende de la implementación de la librería TLS, así que cambiar de librería, de versión, o inyectar parámetros aleatorios ("JA3 randomization"/TLS fingerprint spoofing) cambia el hash. En la práctica muchos operadores no lo hacen porque no es trivial sin reescribir el cliente TLS, y por eso sigue siendo útil como indicio — pero nunca debe ser el único criterio: correlacionar con JARM del servidor y con el patrón de beaconing da mucha más robustez que confiar solo en un hash.

¿RITA sustituye el análisis manual de Zeek/Wireshark?

No. Es una herramienta de priorización: reduce miles de pares de hosts a un puñado de candidatos con puntuación alta de beaconing, pero genera falsos positivos (servicios de sincronización legítimos, heartbeats de monitorización, actualizaciones automáticas) y falsos negativos (jitter muy alto o estrategias "low and slow" deliberadas). El analista siempre debe validar los candidatos contra el PCAP/Zeek original antes de escalar el hallazgo.

¿Por qué se usa DNS para tunneling si es un protocolo tan monitorizado hoy en día?

Porque, pese a estar más vigilado que hace años, sigue siendo uno de los pocos protocolos que casi ningún cortafuegos bloquea de salida por defecto — hacerlo rompería la resolución de nombres de toda la organización. Esto lo hace fiable incluso en redes con HTTP/HTTPS de salida restringido a proxies con lista blanca. El coste para el atacante es la baja capacidad del canal, por lo que suele usarse para C2 de bajo volumen o como último recurso de exfiltración.

¿Qué diferencia hay entre Suricata y Zeek, y por qué se usan juntos?

Son complementarios. Suricata es un IDS/IPS orientado a alertar en tiempo real contra firmas y reglas. Zeek genera logs ricos y estructurados de todo el tráfico observado, con o sin coincidencia de firma, pensados para hunting retrospectivo. En un stack NSM maduro se despliegan ambos sobre el mismo TAP/SPAN: Suricata para alertas accionables, Zeek como base histórica sobre la que investigar cuando salta una alerta.

"JA3 is a technique developed by Salesforce […] that fingerprints the way that a client application communicates over TLS. […] The JA3 method is more effective at identifying malicious activity over SSL/TLS than IP or domain based IOCs because JA3 detects the client application, rather than looking at IP addresses, domains, or certificates."

— John B. Althouse, Jeff Atkinson, Josh Atkins, "JA3: A method for profiling SSL/TLS Clients", Salesforce Engineering