Skip to content
← Rule library
critical SPL Windows / Linux

Web Server Process Spawning a Shell

The post-exploitation tell. A web server should never parent a shell; when it does, the exploit already worked and you are looking at what came next.

Rule source

webshell-response-from-appserver.spl
# Web Server Spawning a Shell Process
# T1190 - Exploit Public-Facing Application
# The post-exploitation tell. A web server process should never be the parent
# of a shell; when it is, the exploit already succeeded.

index=sysmon EventCode=1
| search parent_process_name IN (
      "w3wp.exe", "httpd", "httpd.exe", "nginx", "java", "tomcat*",
      "php-fpm", "node")
| search process_name IN (
      "cmd.exe", "powershell.exe", "pwsh.exe", "sh", "bash", "dash",
      "whoami.exe", "whoami", "net.exe", "curl", "wget", "certutil.exe")
| eval risk=case(
      process_name IN ("powershell.exe", "pwsh.exe", "certutil.exe"), "high",
      process_name IN ("whoami", "whoami.exe"),                        "high",
      true(),                                                          "medium")
| stats
    count                       as executions,
    values(process_name)        as children,
    values(CommandLine)         as command_lines,
    min(_time)                  as first_seen
  by Computer, parent_process_name, user, risk
| convert ctime(first_seen)
| sort - executions

Required telemetry

Sysmon - Event ID 1, auditd execve on Linux

Confirm this source is arriving before you judge the rule. A detection built on telemetry you do not collect looks identical to one that simply never fires.

Known false positives

  • Application health checks that shell out - allowlist the exact command line
  • CI agents running on the same host as a web server, which they should not be

Validation

Deployed a test webshell on a lab IIS and Tomcat host, confirmed both fire

Re-run quarterly. Rules decay because the environment moves underneath them - agent upgrades, schema changes and config edits all break detections silently.