Skip to content
reverseshell

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.

Publicado el 3 min de lectura

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.

Artículos relacionados

Flujo práctico para generar reverse shells en entornos autorizados, preparar el listener y diagnosticar fallos reales.
Cómo depurar callbacks que no llegan por problemas de rutas, egreso, listeners, runtimes ausentes y comandos mal escapados.
Cómo escoger listener para pruebas reverse shell autorizadas, entre netcat, ncat y socat, sin complicar el laboratorio.