Detection rules › Elastic

Potential Reverse Shell Activity via Terminal

Source
github.com/elastic/protections-artifacts

Identifies the execution of a shell process with suspicious arguments which may be indicative of reverse shell activity.

MITRE ATT&CK coverage

Telemetry coverage

Rule body

[rule]
description = "Identifies the execution of a shell process with suspicious arguments which may be indicative of reverse shell activity."
id = "d0e45f6c-1f83-4d97-a8d9-c8f9eb61c15c"
license = "Elastic License v2"
name = "Potential Reverse Shell Activity via Terminal"
os_list = ["macos"]
reference = [
    "https://github.com/swisskyrepo/PayloadsAllTheThings/blob/master/Methodology%20and%20Resources/Reverse%20Shell%20Cheatsheet.md",
    "https://github.com/WangYihang/Reverse-Shell-Manager",
    "https://www.netsparker.com/blog/web-security/understanding-reverse-shells/",
]
version = "1.0.47"

query = '''
process where event.action == "exec" and process.name in ("sh", "bash", "zsh", "dash", "zmodload") and
process.command_line like~ ("*/dev/tcp/*", "*/dev/udp/*", "*zsh/net/tcp*", "*zsh/net/udp*") and 
process.parent.executable != null and 
not (
  process.parent.name == "timeout" or
  process.command_line like~ (
    "*/dev/tcp/sirh_db/*", "*/dev/tcp/itom-vault/8200*", "*/dev/tcp/remoteiot.com/*", "*dev/tcp/elk.stag.one/*",
    "*dev/tcp/kafka/*", "*/dev/tcp/$0/$1*", "*/dev/tcp/::1/*", "*/dev/tcp/livelog.default.svc.cluster.local*",
    "*/dev/tcp/db.default.svc.cluster.local*", "*/dev/tcp/127.*", "*/dev/udp/127.*", "*/dev/tcp/localhost/*",
    "*/dev/tcp/splunk*telconet.net/*",
    "bash -c timeout 2 bash -c 'echo > /dev/tcp/kafka*' 2>/dev/null && echo 'Connected' || echo 'Failed'", 
    "*/dev/tcp/*echo*", "*.claude/shell-snapshots/*echo*"
  ) or
  process.parent.command_line in ("runc init", "/usr/bin/python /opt/oracle/dcs/exacd_netchk/exacd_netchk.py") or
  process.parent.args in ("/usr/local/bin/runc", "/opt/bitnami/scripts/keycloak/setup.sh", "/usr/bin/testssl.sh") or
  process.working_directory == "/opt/rapid7/ir_agent/components/endpoint_broker/common" or
  process.parent.executable like (
    "/opt/cdf/data/containerd/*", "/usr/bin/consul", "/usr/sbin/sshd", "/usr/bin/runc", "/usr/share/cursor/cursor", 
    "/home/*/.nvm/versions/node/*/bin/node", "/home/*/t38-k8s/*/k8sts", "/home/*/.opencode/bin/opencode",
    "/usr/bin/gnome-shell", "/usr/bin/coreutils", "/home/*/.local/bin/kiro-cli-chat",
    "/opt/Tychon/Endpoint/bin/TychonCoreService", "/usr/local/bin/teleport", "/opt/teleport/system/bin/teleport",
    "/usr/bin/claude-bin", "/usr/local/share/npm-global/lib/node_modules/opencode-ai/bin/.opencode",
    "/home/*/.local/share/claude/versions/*", "/home/linuxbrew/.linuxbrew/Caskroom/codex/*/codex-x86_64-unknown-linux-musl",
    "/opt/homebrew/Cellar/coreutils/*/bin/gtimeout", "/usr/local/Cellar/coreutils/*/bin/gtimeout"
  ) or
  (process.parent.name == "sudo" and process.parent.command_line like "*teleport-installer*") or
  (
    process.args like "/dev/tcp/nomzk-client-svc/*" and
    process.executable like "/opt/cdf/data/containerd/state/io.containerd.runtime.v2.task/k8s.io/*/rootfs/usr/bin/bash"
  ) or
  (process.args like "-l source*/tmp/claude*" and process.parent.name == "node") or
  (process.working_directory == "/opt/Tychon/Endpoint/bin" and process.parent.command_line == "/usr/bin/bash -s") or
  (process.command_line like "*claude*" and process.parent.command_line == "claude")
)
'''

min_endpoint_version = "7.15.0"
optional_actions = []
[[actions]]
action = "kill_process"
field = "process.entity_id"
state = 0

[[actions]]
action = "kill_process"
field = "process.parent.entity_id"
state = 0

[[threat]]
framework = "MITRE ATT&CK"
[[threat.technique]]
id = "T1059"
name = "Command and Scripting Interpreter"
reference = "https://attack.mitre.org/techniques/T1059/"


[threat.tactic]
id = "TA0002"
name = "Execution"
reference = "https://attack.mitre.org/tactics/TA0002/"
[[threat]]
framework = "MITRE ATT&CK"
[[threat.technique]]
id = "T1071"
name = "Application Layer Protocol"
reference = "https://attack.mitre.org/techniques/T1071/"


[threat.tactic]
id = "TA0011"
name = "Command and Control"
reference = "https://attack.mitre.org/tactics/TA0011/"

[internal]
min_endpoint_version = "7.15.0"

Stages and Predicates

Stage 1: process

process where event.action == "exec" and process.name in ("sh", "bash", "zsh", "dash", "zmodload") and
process.command_line like~ ("*/dev/tcp/*", "*/dev/udp/*", "*zsh/net/tcp*", "*zsh/net/udp*") and 
process.parent.executable != null and 
not (
  process.parent.name == "timeout" or
  process.command_line like~ (
    "*/dev/tcp/sirh_db/*", "*/dev/tcp/itom-vault/8200*", "*/dev/tcp/remoteiot.com/*", "*dev/tcp/elk.stag.one/*",
    "*dev/tcp/kafka/*", "*/dev/tcp/$0/$1*", "*/dev/tcp/::1/*", "*/dev/tcp/livelog.default.svc.cluster.local*",
    "*/dev/tcp/db.default.svc.cluster.local*", "*/dev/tcp/127.*", "*/dev/udp/127.*", "*/dev/tcp/localhost/*",
    "*/dev/tcp/splunk*telconet.net/*",
    "bash -c timeout 2 bash -c 'echo > /dev/tcp/kafka*' 2>/dev/null && echo 'Connected' || echo 'Failed'", 
    "*/dev/tcp/*echo*", "*.claude/shell-snapshots/*echo*"
  ) or
  process.parent.command_line in ("runc init", "/usr/bin/python /opt/oracle/dcs/exacd_netchk/exacd_netchk.py") or
  process.parent.args in ("/usr/local/bin/runc", "/opt/bitnami/scripts/keycloak/setup.sh", "/usr/bin/testssl.sh") or
  process.working_directory == "/opt/rapid7/ir_agent/components/endpoint_broker/common" or
  process.parent.executable like (
    "/opt/cdf/data/containerd/*", "/usr/bin/consul", "/usr/sbin/sshd", "/usr/bin/runc", "/usr/share/cursor/cursor", 
    "/home/*/.nvm/versions/node/*/bin/node", "/home/*/t38-k8s/*/k8sts", "/home/*/.opencode/bin/opencode",
    "/usr/bin/gnome-shell", "/usr/bin/coreutils", "/home/*/.local/bin/kiro-cli-chat",
    "/opt/Tychon/Endpoint/bin/TychonCoreService", "/usr/local/bin/teleport", "/opt/teleport/system/bin/teleport",
    "/usr/bin/claude-bin", "/usr/local/share/npm-global/lib/node_modules/opencode-ai/bin/.opencode",
    "/home/*/.local/share/claude/versions/*", "/home/linuxbrew/.linuxbrew/Caskroom/codex/*/codex-x86_64-unknown-linux-musl",
    "/opt/homebrew/Cellar/coreutils/*/bin/gtimeout", "/usr/local/Cellar/coreutils/*/bin/gtimeout"
  ) or
  (process.parent.name == "sudo" and process.parent.command_line like "*teleport-installer*") or
  (
    process.args like "/dev/tcp/nomzk-client-svc/*" and
    process.executable like "/opt/cdf/data/containerd/state/io.containerd.runtime.v2.task/k8s.io/*/rootfs/usr/bin/bash"
  ) or
  (process.args like "-l source*/tmp/claude*" and process.parent.name == "node") or
  (process.working_directory == "/opt/Tychon/Endpoint/bin" and process.parent.command_line == "/usr/bin/bash -s") or
  (process.command_line like "*claude*" and process.parent.command_line == "claude")
)

Exclusions

The rule actively suppresses these predicates.

FieldKindExcluded valuesSearch
process.argsstarts_with/dev/tcp/nomzk-client-svc/excludes:process.args field:"process.args" value:"/dev/tcp/nomzk-client-svc/"
process.executablewildcard/opt/cdf/data/containerd/state/io.containerd.runtime.v2.task/k8s.io/*/rootfs/usr/bin/bashexcludes:process.executable field:"process.executable" value:"/opt/cdf/data/containerd/state/io.containerd.runtime.v2.task/k8s.io/*/rootfs/usr/bin/bash"
process.argswildcard-l source*/tmp/claude*excludes:process.args field:"process.args" value:"-l source*/tmp/claude*"
process.parent.nameeqnodeexcludes:process.parent.name field:"process.parent.name" value:"node"
process.command_linematchclaudeexcludes:process.command_line field:"process.command_line" value:"claude"
process.parent.command_lineeqclaudeexcludes:process.parent.command_line field:"process.parent.command_line" value:"claude"
process.parent.command_lineeq/usr/bin/bash -sexcludes:process.parent.command_line field:"process.parent.command_line" value:"/usr/bin/bash -s"
process.working_directoryeq/opt/Tychon/Endpoint/binexcludes:process.working_directory field:"process.working_directory" value:"/opt/Tychon/Endpoint/bin"
process.parent.command_linematchteleport-installerexcludes:process.parent.command_line field:"process.parent.command_line" value:"teleport-installer"
process.parent.nameeqsudoexcludes:process.parent.name field:"process.parent.name" value:"sudo"
process.command_linewildcard*/dev/tcp/sirh_db/*, */dev/tcp/itom-vault/8200*, */dev/tcp/remoteiot.com/*, *dev/tcp/elk.stag.one/*, *dev/tcp/kafka/*, */dev/tcp/$0/$1*, */dev/tcp/::1/*, */dev/tcp/livelog.default.svc.cluster.local*, */dev/tcp/db.default.svc.cluster.local*, */dev/tcp/127.*, */dev/udp/127.*, */dev/tcp/localhost/*, */dev/tcp/splunk*telconet.net/*, bash -c timeout 2 bash -c 'echo > /dev/tcp/kafka*' 2>/dev/null && echo 'Connected' || echo 'Failed', */dev/tcp/*echo*, *.claude/shell-snapshots/*echo*excludes:process.command_line
process.parent.argsin/opt/bitnami/scripts/keycloak/setup.sh, /usr/bin/testssl.sh, /usr/local/bin/runcexcludes:process.parent.args field:"process.parent.args" value:"/opt/bitnami/scripts/keycloak/setup.sh" field:"process.parent.args" value:"/usr/bin/testssl.sh" field:"process.parent.args" value:"/usr/local/bin/runc"
process.parent.command_linein/usr/bin/python /opt/oracle/dcs/exacd_netchk/exacd_netchk.py, runc initexcludes:process.parent.command_line field:"process.parent.command_line" value:"/usr/bin/python /opt/oracle/dcs/exacd_netchk/exacd_netchk.py" field:"process.parent.command_line" value:"runc init"
process.parent.executablewildcard/opt/cdf/data/containerd/*, /usr/bin/consul, /usr/sbin/sshd, /usr/bin/runc, /usr/share/cursor/cursor, /home/*/.nvm/versions/node/*/bin/node, /home/*/t38-k8s/*/k8sts, /home/*/.opencode/bin/opencode, /usr/bin/gnome-shell, /usr/bin/coreutils, /home/*/.local/bin/kiro-cli-chat, /opt/Tychon/Endpoint/bin/TychonCoreService, /usr/local/bin/teleport, /opt/teleport/system/bin/teleport, /usr/bin/claude-bin, /usr/local/share/npm-global/lib/node_modules/opencode-ai/bin/.opencode, /home/*/.local/share/claude/versions/*, /home/linuxbrew/.linuxbrew/Caskroom/codex/*/codex-x86_64-unknown-linux-musl, /opt/homebrew/Cellar/coreutils/*/bin/gtimeout, /usr/local/Cellar/coreutils/*/bin/gtimeoutexcludes:process.parent.executable
process.parent.nameeqtimeoutexcludes:process.parent.name field:"process.parent.name" value:"timeout"
process.working_directoryeq/opt/rapid7/ir_agent/components/endpoint_broker/commonexcludes:process.working_directory field:"process.working_directory" value:"/opt/rapid7/ir_agent/components/endpoint_broker/common"

Indicators

These rows show field, operator, and value matches.

FieldKindValuesSearch
event.actioneq
  • exec
field:"EventType" kind:eq value:"exec"
process.command_linewildcard
  • */dev/tcp/*
  • */dev/udp/*
  • *zsh/net/tcp*
  • *zsh/net/udp*
field:"CommandLine" kind:wildcard
process.namein
  • bash
  • dash
  • sh
  • zmodload
  • zsh
field:"process_name" kind:in
process.parent.executableis_not_null
  • (no value, null check)
field:"ParentImage" kind:is_not_null