Detectar reverse shells sin fingir que una sola regla Sigma basta
La detección de reverse shells necesita contexto de procesos, red y workload. Las firmas aisladas generan ruido y pierden casos reales.
Detectar reverse shells es incómodo porque la técnica es simple. Un proceso abre una conexión saliente y conecta entrada y salida con un shell o intérprete. Eso puede ser una intrusión, o puede ser una automatización legítima escrita deprisa por alguien de operaciones.
La detección pobre dice: alerta cuando bash se conecta a Internet. Va a capturar algunas pruebas. También va a perder callbacks en Python, PowerShell, herramientas administrativas, contenedores y procesos que ya generan mucho ruido en tu entorno.
La telemetría de proceso explica la intención
Los logs de red dicen que hubo una conexión. El árbol de procesos dice por qué deberías preocuparte.
Buenas señales: shells hijos de servidores web, intérpretes lanzados por php-fpm, cmd.exe o PowerShell creados por servicios expuestos, procesos muy cortos que abren conexión justo después de una entrada sospechosa, o binarios de sistema iniciando sesiones salientes que no corresponden al rol del host. En Linux, auditd, sensores eBPF y EDR pueden servir si conservan argv, usuario y parent PID. En Windows, Sysmon Event ID 1 combinado con eventos de red ya permite empezar.
Una hipótesis básica:
process.name in ("sh", "bash", "dash", "zsh", "cmd.exe", "powershell.exe", "python", "perl", "php", "ruby")
AND network.direction = "outbound"
AND destination.ip NOT IN approved_admin_ranges
No es una regla de producción. Es una forma de buscar. Las exclusiones importan más que la lista inicial.
El proceso padre suele contar la historia
bash desde una sesión SSH interactiva puede ser normal. bash lanzado por nginx, apache2, php-fpm, postgres, jenkins o un conversor de documentos merece otra reacción.
Los atacantes lo saben. Prefieren intérpretes y herramientas presentes en el sistema porque muchas reglas miran nombres, no comportamiento. Un reverse shell en Python puede no contener ninguna cadena evidente. Solo socket, subprocess y redirección de descriptores.
El matching de texto no alcanza.
El contexto de red sigue pesando
Conexiones salientes a puertos altos en ASN residenciales desde servidores son raras. Sesiones largas desde workloads que normalmente solo hablan con bases de datos, colas o APIs internas también son interesantes. DNS ayuda cuando se usan dominios desechables, aunque los callbacks directos a IP siguen siendo comunes.
En contenedores, añade pod, namespace, imagen y service account. Sin eso, el analista recibe una IP de nodo y un proceso. Es muy poco para investigar rápido.
El impuesto de falsos positivos
Las reglas ruidosas terminan silenciadas. Scripts de backup lanzan shells. Runners CI ejecutan intérpretes. SREs hacen diagnósticos durante incidentes. Si todo shell con conexión saliente es crítico, la regla no sobrevivirá una semana.
Usa niveles. Alto para shells hijos de servicios expuestos. Medio para networking inusual desde servidores. Bajo en workstations de desarrollo salvo que destino, proceso padre o línea de comandos sean claramente sospechosos.
La detección útil no es una firma. Es un pequeño grafo: padre, comando, usuario, destino, rol del workload, hora y si ese host ya hizo algo parecido antes.