Threat Hunting con Splunk: SPL, Stats, Tstats y Tecnicas Avanzadas
Guia practica de threat hunting con Splunk y SPL. Comandos esenciales (stats, tstats, eventstats, transaction), macros de hunting, lookups para enriquecimiento, dashboards de investigacion y workflows de caza de amenazas optimizados para rendimiento.
Splunk como Plataforma de Hunting
Splunk es una de las plataformas SIEM mas potentes para threat hunting. Su lenguaje de busqueda (SPL, Search Processing Language) ofrece capacidades de analisis estadistico, correlacion temporal y transformacion de datos que lo hacen ideal para investigaciones complejas.
Para el hunter, Splunk destaca en tres areas: busquedas estadisticas sobre grandes volumenes (stats, tstats), correlacion de eventos en secuencia (transaction), y enriquecimiento de datos con lookups.
Fundamentos de SPL para Hunting
Estructura de una busqueda SPL
index=sysmon EventCode=1 # Fuente de datos y filtro base
| where match(CommandLine, "(?i)powershell") # Filtro regex
| stats count by Computer, User, CommandLine # Agregacion
| sort -count # Ordenar
| head 20 # Limitar resultados
Comandos esenciales para hunting
search / where. Filtros base. search es el comando implicito del inicio de la query. where permite condiciones mas complejas con funciones.
# search: filtro directo
index=sysmon EventCode=1 Image="*powershell.exe"
# where: condiciones complejas
index=sysmon EventCode=1
| where like(Image, "%powershell%") AND len(CommandLine) > 500
stats. Agregacion de datos. El comando mas usado en hunting para resumir y agrupar resultados.
# Conteo de procesos por host y usuario
index=sysmon EventCode=1
| stats count, dc(Image) as unique_processes by Computer, User
| sort -unique_processes
# Primera y ultima vez vista de una conexion
index=sysmon EventCode=3
| stats earliest(_time) as first_seen, latest(_time) as last_seen,
count by DestinationIp, DestinationPort, Image
| convert ctime(first_seen) ctime(last_seen)
eventstats. Calcula estadisticas y anade los resultados como campos a cada evento (sin eliminar los eventos originales). Ideal para comparar cada evento contra el baseline del grupo.
# Identificar comandos PowerShell con longitud anomala
index=sysmon EventCode=1 Image="*powershell.exe"
| eval cmd_len = len(CommandLine)
| eventstats avg(cmd_len) as avg_len, stdev(cmd_len) as std_len by Computer
| where cmd_len > (avg_len + 3 * std_len)
| table _time, Computer, User, cmd_len, avg_len, CommandLine
transaction. Agrupa eventos relacionados en transacciones. Util para reconstruir cadenas de ejecucion.
# Reconstruir cadenas de procesos por ProcessGuid
index=sysmon EventCode=1
| transaction ProcessGuid maxspan=5m
| where eventcount > 3
| table _time, Computer, User, Image, CommandLine
Tstats: Busquedas de Alto Rendimiento
tstats es la clave para hunting eficiente sobre grandes volumenes de datos. Opera sobre data models acelerados y es ordenes de magnitud mas rapido que stats.
Configurar data models acelerados
Para usar tstats, los data models relevantes deben estar acelerados:
Settings > Data Models > Endpoint > Edit > Acceleration > Enable
Settings > Data Models > Network_Traffic > Enable
Settings > Data Models > Authentication > Enable
Consultas tstats para hunting
# Procesos desde rutas temporales (Endpoint data model)
| tstats count from datamodel=Endpoint.Processes
where Processes.process_path="*\\Temp\\*"
by Processes.dest, Processes.user, Processes.process_name, Processes.process
| rename Processes.* as *
| sort -count
# Conexiones salientes por destino (Network data model)
| tstats sum(All_Traffic.bytes_out) as bytes_out
from datamodel=Network_Traffic.All_Traffic
where All_Traffic.direction=outbound
by All_Traffic.src, All_Traffic.dest, All_Traffic.dest_port
| rename All_Traffic.* as *
| where bytes_out > 104857600
| sort -bytes_out
# Fallos de autenticacion por IP (Authentication data model)
| tstats count from datamodel=Authentication.Authentication
where Authentication.action=failure
by Authentication.src, Authentication.user, Authentication.app
| rename Authentication.* as *
| where count > 20
| sort -count
Macros de Hunting
Las macros de Splunk permiten encapsular consultas complejas en funciones reutilizables.
Definir macros
En Settings, Advanced Search, Search Macros:
# Macro: hunting_lolbins
# Definicion:
index=sysmon EventCode=1 (
(Image="*certutil.exe" (CommandLine="*-urlcache*" OR CommandLine="*-split*")) OR
(Image="*bitsadmin.exe" CommandLine="*/transfer*") OR
(Image="*mshta.exe" CommandLine="*http*") OR
(Image="*regsvr32.exe" CommandLine="*/s*" CommandLine="*/i*" CommandLine="*http*") OR
(Image="*rundll32.exe" CommandLine="*http*")
)
| stats count by Computer, User, Image, CommandLine, ParentImage
| sort -count
# Uso en busqueda:
`hunting_lolbins`
# Macro: hunting_lateral_movement
# Definicion:
index=wineventlog (
(EventCode=4624 LogonType=3 AuthenticationPackageName=NTLM
NOT SourceNetworkAddress IN ("known_admin_ips")) OR
(EventCode=7045 NOT ServiceName IN ("known_services")) OR
(EventCode=4648)
)
| stats count by EventCode, Computer, SourceNetworkAddress, TargetUserName
| sort -count
Macros con argumentos
# Macro: hunting_process_by_hash(1) donde $1$ es el hash
index=sysmon EventCode=1 Hashes="*$hash$*"
| stats count, values(Computer) as hosts, values(User) as users,
values(Image) as paths by Hashes
| sort -count
# Uso:
`hunting_process_by_hash("abc123def456...")`
Lookups para Enriquecimiento
Los lookups permiten cruzar datos de Splunk con listas externas: IOCs, baselines, whitelists.
Lookup de IOCs
# Crear un CSV con IOCs (iocs.csv)
# Columnas: ioc_value, ioc_type, source, confidence
# Configurar el lookup en Splunk:
# Settings > Lookups > Lookup table files > Add new
# Buscar IOCs en los datos
index=sysmon EventCode=3
| lookup iocs.csv ioc_value as DestinationIp OUTPUT ioc_type, source, confidence
| where isnotnull(ioc_type)
| table _time, Computer, Image, DestinationIp, ioc_type, source, confidence
Lookup de baseline de procesos
# Crear baseline (process_baseline.csv)
# Columnas: process_name, expected, notes
# Buscar procesos fuera del baseline
index=sysmon EventCode=1
| stats dc(Computer) as host_count by Image
| lookup process_baseline.csv process_name as Image OUTPUT expected
| where isnull(expected)
| sort -host_count
Lookup de JA3 conocidos
# ja3_malicious.csv con hashes JA3 de C2 frameworks
index=zeek sourcetype=bro_ssl
| lookup ja3_malicious.csv ja3 as ja3 OUTPUT tool_name, description
| where isnotnull(tool_name)
| table _time, id_orig_h, id_resp_h, id_resp_p, ja3, tool_name, server_name
Consultas de Hunting Avanzadas
Deteccion de beaconing con SPL
# Analisis de beaconing: intervalos entre conexiones
index=zeek sourcetype=bro_conn id_resp_h="198.51.100.42"
| sort _time
| streamstats current=f last(_time) as prev_time by id_orig_h
| eval interval = _time - prev_time
| stats count, avg(interval) as avg_interval,
stdev(interval) as std_interval,
min(interval) as min_interval,
max(interval) as max_interval
by id_orig_h, id_resp_h
| eval cv = std_interval / avg_interval
| where cv < 0.3 AND count > 20
| sort cv
Un coeficiente de variacion (cv) bajo indica intervalos regulares, tipico de beaconing.
Deteccion de password spraying
# Password spraying: muchas cuentas con fallo desde misma IP
index=wineventlog EventCode=4625 SubStatus=0xC000006A
| bin _time span=30m
| stats dc(TargetUserName) as unique_users,
values(TargetUserName) as users,
count as total_attempts
by _time, IpAddress
| where unique_users > 10
| sort -unique_users
Hunting de DNS tunneling
# DNS con subdominios de longitud anomala
index=zeek sourcetype=bro_dns
| eval query_parts = split(query, ".")
| eval subdomain_len = len(mvindex(query_parts, 0))
| eval base_domain = mvindex(query_parts, -2) . "." . mvindex(query_parts, -1)
| where subdomain_len > 30
| stats count, sum(subdomain_len) as total_data_bytes by id_orig_h, base_domain
| sort -count
Cadena de ataque completa con transaction
# Reconstruir secuencia: phishing -> ejecucion -> C2
index=sysmon (EventCode=1 OR EventCode=3 OR EventCode=11)
| eval chain_id = Computer . "-" . User
| transaction chain_id maxspan=10m
startswith="ParentImage=*outlook.exe*"
endswith="EventCode=3"
| where eventcount > 3
| table _time, Computer, User, Image, CommandLine, DestinationIp
Dashboards de Hunting en Splunk
Panel de resumen ejecutivo
<!-- Saved Search para panel de metricas de hunting -->
<search>
<query>
index=sysmon EventCode=1
| stats dc(Image) as unique_processes,
dc(Computer) as unique_hosts,
dc(User) as unique_users,
count as total_events
</query>
</search>
Panel de procesos anomalos
# Procesos raros: ejecutados en menos de 3 hosts
index=sysmon EventCode=1
| stats dc(Computer) as host_count, values(Computer) as hosts by Image
| where host_count < 3 AND NOT match(Image, "(?i)(chrome|firefox|edge|code)")
| sort host_count
Panel de conexiones externas sospechosas
# Conexiones a IPs externas por proceso (excluyendo navegadores)
index=sysmon EventCode=3 NOT DestinationIp IN (10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16)
| where NOT match(Image, "(?i)(chrome|firefox|edge|teams|outlook|onedrive)")
| stats count, dc(DestinationIp) as unique_dests by Computer, Image
| where unique_dests > 5
| sort -unique_dests
Splunk Enterprise Security (ES)
Splunk ES anade capacidades avanzadas de hunting sobre Splunk Enterprise:
Notable Events. Alertas enriquecidas con contexto de assets e identities. Las consultas de hunting se pueden convertir en Correlation Searches que generan Notable Events.
Threat Intelligence Framework. Integracion nativa con feeds de CTI. Los IOCs se cruzan automaticamente con los datos indexados.
Risk-Based Alerting (RBA). En lugar de alertar por cada evento individual, RBA acumula puntos de riesgo por entidad (host, usuario). Cuando una entidad acumula riesgo suficiente, se genera una alerta. Esto reduce drasticamente los falsos positivos.
# Ejemplo de Risk Rule: asignar puntos de riesgo
index=sysmon EventCode=1 Image="*mimikatz*"
| eval risk_score = 80
| eval risk_object = Computer
| eval risk_object_type = "system"
| eval risk_message = "Posible ejecucion de Mimikatz en " . Computer
Optimizacion de Rendimiento
Reglas de oro para SPL eficiente
- Filtrar temprano. Los filtros de index, sourcetype y campos indexados deben ir al principio
- Usar tstats cuando sea posible. Es ordenes de magnitud mas rapido que stats sobre raw events
- Evitar wildcards al inicio.
*malware.exees lento.Image="C:\\Users\\*\\malware.exe"es mas rapido - Limitar el rango temporal. Buscar en 24 horas es mucho mas rapido que en 90 dias. Empezar con rangos cortos y expandir
- Usar summary indexing. Para busquedas frecuentes, crear indices de resumen que precomputen las estadisticas
Tstats vs Stats: cuando usar cada uno
| Escenario | Usar | Razon |
|---|---|---|
| Conteo de procesos por host | tstats | Campos en data model |
| Analisis de CommandLine con regex | stats | CommandLine no esta en TSIDX |
| Volumen de trafico por destino | tstats | Campos de Network Traffic |
| Correlacion de campos custom | stats | Campos no acelerados |
| Busqueda exploratoria inicial | stats | Flexibilidad |
| Dashboard de produccion | tstats | Rendimiento |
Conclusion
Splunk con SPL es una herramienta de hunting extremadamente potente. La combinacion de stats para analisis detallado, tstats para busquedas rapidas sobre grandes volumenes, transaction para correlacion temporal, lookups para enriquecimiento y macros para reutilizacion de consultas proporciona un toolkit completo para el hunter.
La clave para ser efectivo en Splunk es dominar la optimizacion de consultas (filtrar temprano, usar tstats, limitar rangos temporales) y crear una biblioteca de macros y lookups que encapsulen los patrones de hunting mas frecuentes. Cada hunt exitoso deberia convertirse en una Correlation Search que detecte la misma tecnica automaticamente en el futuro.
Preguntas frecuentes
Libros recomendados
Artículos relacionados
ELK Stack para Threat Hunting: KQL, Dashboards y Reglas de Deteccion
Threat Hunting con Sysmon en Windows: Eventos Clave y Consultas Practicas
Threat Hunting con Zeek: Analisis de Trafico de Red para Detectar Amenazas
Hunting de Command and Control (C2): Beaconing, DNS Tunneling y Domain Fronting
Reglas Sigma: Sintaxis, Estructura y Tu Primer Caso Práctico
Sigma Pipelines: Procesamiento, Backends y Conversión Avanzada a tu SIEM
Este contenido tiene fines exclusivamente educativos y de investigación en ciberseguridad defensiva. No se proporcionan binarios maliciosos ni payloads ejecutables. El uso indebido de esta información es responsabilidad exclusiva del usuario. Leer disclaimer completo.