Detecting Reverse Shells Without Pretending One Sigma Rule Is Enough
Reverse shell detection needs process, network, and context. Single-rule matching misses quiet callbacks and floods teams with false positives.
Detecting reverse shells is annoying because the primitive is simple. A process opens an outbound connection and wires input/output to a shell or interpreter. That can look malicious, or it can look like a legitimate admin tool doing legitimate admin work badly.
The weak detection is "alert when bash connects to the internet." You will catch some tests. You will also miss language-based callbacks, living-off-the-land wrappers, container escapes, and anything tunneled through tooling your environment already trusts.
Process Telemetry Carries The Intent
Network logs tell you that a connection happened. Process telemetry tells you why it is suspicious.
Good signals include shell processes with socket-oriented parents, interpreters launched from web server workers, command shells spawned by database engines, and short-lived processes that create outbound sessions right after suspicious input handling. On Linux, auditd, eBPF sensors, and EDR process trees are useful if they preserve argv and parent PID. On Windows, Sysmon Event ID 1 plus network connection events gives you a fighting chance.
A rough query pattern looks like this:
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
That is not production-ready. It is a starting hypothesis. The exclusions matter more than the match list.
Parent Process Is Where The Story Gets Ugly
bash launched by an interactive SSH session is normal. bash launched by nginx, apache2, php-fpm, postgres, jenkins, or a document converter is a different conversation.
Attackers know this. They try to hide behind interpreters and scheduled jobs because defenders often alert on tool names instead of behavior. A reverse shell generated in Python may not contain the word "shell" anywhere useful. It may just be a socket, a subprocess call, and file descriptor plumbing.
Do not rely on string matching alone.
Network Context Still Matters
Outbound connections to high ports on residential ASNs deserve scrutiny. So do long-lived sessions from workloads that normally speak only to databases, queues, object storage, or internal APIs. DNS can help when the destination is a throwaway domain, but direct IP callbacks are common in labs and opportunistic attacks.
In containers, enrich alerts with pod name, namespace, image, and service account. Without that context, the incident responder gets a node IP and a process name. That is barely a clue.
The False Positive Tax
Security teams burn out on noisy reverse shell rules because admin automation is messy. Backup scripts call shells. CI runners spawn interpreters. SREs run one-off diagnostics during outages. If the detection treats all shell networking as equal, people will mute it.
Build tiers instead. High severity for shell children of exposed services. Medium for unusual outbound shell networking from servers. Low for developer workstations unless the destination, parent process, or command line is ugly.
The best detection is not one rule. It is a small graph: parent process, command line, user, destination, workload role, time of day, and whether that host has ever done this before.