Detection rules › Elastic

Linux Suspicious Child Process Execution via Interactive Shell

Source
github.com/elastic/protections-artifacts

Detects when a process is executed via an interactive shell. C2 platforms will commonly spawn an interactive shell providing the threat actor with a remote shell on the system as if they were physically at the terminal allowing them to send and execute commands manually.

MITRE ATT&CK coverage

Rule body

[rule]
description = """
Detects when a process is executed via an interactive shell. C2 platforms will commonly spawn an interactive shell
providing the threat actor with a remote shell on the system as if they were physically at the terminal allowing them to
send and execute commands manually.
"""
id = "aa02591f-c9e6-4317-841e-0b075b9515ff"
license = "Elastic License v2"
name = "Linux Suspicious Child Process Execution via Interactive Shell"
os_list = ["linux"]
version = "1.0.24"

query = '''
process where event.type == "start" and event.action == "exec" and process.args in ("-i", "-il", "-li") and process.args_count <= 2 and
process.name in ("bash", "dash", "ash", "sh", "tcsh", "csh", "zsh", "ksh", "fish") and process.parent.args_count > 1 and
process.parent.name like (
  "bash", "dash", "sh", "tcsh", "csh", "zsh", "ksh", "fish", "python*", "php*", "socat",
  "perl", "ruby", "lua*", "openssl", "nc", "ncat", "netcat", "netcat.openbsd",
  "netcat.traditional", "nc.openbsd", "nc.traditional", "telnet", "awk", "node"
) and not (
  process.parent.args like (
    "echo*| sudo -S su; sudo su;*SHELL -i", "/usr/share/kali-menu/exec-in-shell", "/usr/bin/kali-treecd", "pipenv",
    "/usr/scratch/xar/23e8559c/bin/python"
  ) or
  process.parent.command_line in (
    "/bin/sh -c bash -i </dev/tty >/dev/tty 2>/dev/tty", "/bin/bash --login --posix", "bash -c sudo su - oracle; $SHELL -i",
    "/bin/bash /opt/scripts/health-check.sh"
  ) or
  process.parent.command_line like (
    "/usr/scratch/*poetry shell", "*/u01/app/oracle.ahf/tfa/internal/tmp/*.sh*", "*/opt/oracle/oracle.ahf/tfa/internal/*.sh*",
    "bash -c ls -al; $SHELL -i", "bash -c cd ~/GIT/salt/pillars; $SHELL -i", "bash -c cd ~/GIT/ansible-infra; $SHELL -i",
    "bash -c cd ~/GIT/salt/states; $SHELL -i", "bash -c cd ~/GIT/puppet/hieradata; $SHELL -i",
    "bash -c cd ~/GIT/puppet/ind_legacy; $SHELL -i",
    """bash -c sudo -iu oracle bash -ic 'do_host P1 "hostname;/home/*/scripts/get_status;"'; $SHELL -i"""
  ) or
  process.command_line == "/opt/cursor.appimage -i" or
  process.parent.executable like (
    "/mnt/*/.vscode-server/bin/*/node", "/vscode/vscode-server/bin/*/node", "/home/*/.vscode-server/bin/*/node",
    "/usr/scratch/*/.vscode-server/bin/*/node", "/home/*/.vscode-server/*/server/node", "/scratch/user/*/.vscode-server/cli/servers/*/server/node",
    "/home/*/.vscode/cli/servers/*/server/node", "/root/.vscode-server/cli/servers/*/server/node", "/mnt/*/.vscode-server/cli/servers/*/server/node",
    "/home/*/.antigravity-server/bin/*/node", "/user/*/.trae-server/bin/*/node", "/var/lib/docker/overlay2/*/merged/vscode/vscode-server/bin/linux-x64/*/node",
    "/home/*/miniforge3/envs/*/bin/python*", "/home/*/.cursor-server/bin/linux-x64/*/node", "/home/*/.vscode-server-insiders/bin/*/node"
  ) or
  (process.parent.command_line like ("*pipenv*", "*poetry*") and process.parent.args:"shell")
)
'''

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.technique.subtechnique]]
id = "T1059.004"
name = "Unix Shell"
reference = "https://attack.mitre.org/techniques/T1059/004/"



[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.type == "start" and event.action == "exec" and process.args in ("-i", "-il", "-li") and process.args_count <= 2 and
process.name in ("bash", "dash", "ash", "sh", "tcsh", "csh", "zsh", "ksh", "fish") and process.parent.args_count > 1 and
process.parent.name like (
  "bash", "dash", "sh", "tcsh", "csh", "zsh", "ksh", "fish", "python*", "php*", "socat",
  "perl", "ruby", "lua*", "openssl", "nc", "ncat", "netcat", "netcat.openbsd",
  "netcat.traditional", "nc.openbsd", "nc.traditional", "telnet", "awk", "node"
) and not (
  process.parent.args like (
    "echo*| sudo -S su; sudo su;*SHELL -i", "/usr/share/kali-menu/exec-in-shell", "/usr/bin/kali-treecd", "pipenv",
    "/usr/scratch/xar/23e8559c/bin/python"
  ) or
  process.parent.command_line in (
    "/bin/sh -c bash -i </dev/tty >/dev/tty 2>/dev/tty", "/bin/bash --login --posix", "bash -c sudo su - oracle; $SHELL -i",
    "/bin/bash /opt/scripts/health-check.sh"
  ) or
  process.parent.command_line like (
    "/usr/scratch/*poetry shell", "*/u01/app/oracle.ahf/tfa/internal/tmp/*.sh*", "*/opt/oracle/oracle.ahf/tfa/internal/*.sh*",
    "bash -c ls -al; $SHELL -i", "bash -c cd ~/GIT/salt/pillars; $SHELL -i", "bash -c cd ~/GIT/ansible-infra; $SHELL -i",
    "bash -c cd ~/GIT/salt/states; $SHELL -i", "bash -c cd ~/GIT/puppet/hieradata; $SHELL -i",
    "bash -c cd ~/GIT/puppet/ind_legacy; $SHELL -i",
    """bash -c sudo -iu oracle bash -ic 'do_host P1 "hostname;/home/*/scripts/get_status;"'; $SHELL -i"""
  ) or
  process.command_line == "/opt/cursor.appimage -i" or
  process.parent.executable like (
    "/mnt/*/.vscode-server/bin/*/node", "/vscode/vscode-server/bin/*/node", "/home/*/.vscode-server/bin/*/node",
    "/usr/scratch/*/.vscode-server/bin/*/node", "/home/*/.vscode-server/*/server/node", "/scratch/user/*/.vscode-server/cli/servers/*/server/node",
    "/home/*/.vscode/cli/servers/*/server/node", "/root/.vscode-server/cli/servers/*/server/node", "/mnt/*/.vscode-server/cli/servers/*/server/node",
    "/home/*/.antigravity-server/bin/*/node", "/user/*/.trae-server/bin/*/node", "/var/lib/docker/overlay2/*/merged/vscode/vscode-server/bin/linux-x64/*/node",
    "/home/*/miniforge3/envs/*/bin/python*", "/home/*/.cursor-server/bin/linux-x64/*/node", "/home/*/.vscode-server-insiders/bin/*/node"
  ) or
  (process.parent.command_line like ("*pipenv*", "*poetry*") and process.parent.args:"shell")
)

Exclusions

The rule actively suppresses these predicates.

FieldKindExcluded valuesSearch
process.parent.argseqshellexcludes:process.parent.args field:"process.parent.args" value:"shell"
process.parent.command_linematchpipenv, poetryexcludes:process.parent.command_line field:"process.parent.command_line" value:"pipenv" field:"process.parent.command_line" value:"poetry"
process.command_lineeq/opt/cursor.appimage -iexcludes:process.command_line field:"process.command_line" value:"/opt/cursor.appimage -i"
process.parent.argswildcardecho*| sudo -S su; sudo su;*SHELL -i, /usr/share/kali-menu/exec-in-shell, /usr/bin/kali-treecd, pipenv, /usr/scratch/xar/23e8559c/bin/pythonexcludes:process.parent.args
process.parent.command_linein/bin/bash --login --posix, /bin/bash /opt/scripts/health-check.sh, /bin/sh -c bash -i </dev/tty >/dev/tty 2>/dev/tty, bash -c sudo su - oracle; $SHELL -iexcludes:process.parent.command_line
process.parent.command_linewildcard/usr/scratch/*poetry shell, */u01/app/oracle.ahf/tfa/internal/tmp/*.sh*, */opt/oracle/oracle.ahf/tfa/internal/*.sh*, bash -c ls -al; $SHELL -i, bash -c cd ~/GIT/salt/pillars; $SHELL -i, bash -c cd ~/GIT/ansible-infra; $SHELL -i, bash -c cd ~/GIT/salt/states; $SHELL -i, bash -c cd ~/GIT/puppet/hieradata; $SHELL -i, bash -c cd ~/GIT/puppet/ind_legacy; $SHELL -i, bash -c sudo -iu oracle bash -ic 'do_host P1 "hostname;/home/*/scripts/get_status;"'; $SHELL -iexcludes:process.parent.command_line
process.parent.executablewildcard/mnt/*/.vscode-server/bin/*/node, /vscode/vscode-server/bin/*/node, /home/*/.vscode-server/bin/*/node, /usr/scratch/*/.vscode-server/bin/*/node, /home/*/.vscode-server/*/server/node, /scratch/user/*/.vscode-server/cli/servers/*/server/node, /home/*/.vscode/cli/servers/*/server/node, /root/.vscode-server/cli/servers/*/server/node, /mnt/*/.vscode-server/cli/servers/*/server/node, /home/*/.antigravity-server/bin/*/node, /user/*/.trae-server/bin/*/node, /var/lib/docker/overlay2/*/merged/vscode/vscode-server/bin/linux-x64/*/node, /home/*/miniforge3/envs/*/bin/python*, /home/*/.cursor-server/bin/linux-x64/*/node, /home/*/.vscode-server-insiders/bin/*/nodeexcludes:process.parent.executable

Indicators

These rows show field, operator, and value matches.

FieldKindValuesSearch
event.actioneq
  • exec
field:"EventType" kind:eq value:"exec"
event.typeeq
  • start
field:"event.type" kind:eq value:"start"
process.argsin
  • -i
  • -il
  • -li
field:"process.args" kind:in
process.args_countle
  • 2 transforms: number
field:"process.args_count" kind:le value:"2"
process.namein
  • ash
  • bash
  • csh
  • dash
  • fish
  • ksh
  • sh
  • tcsh
  • zsh
field:"process_name" kind:in
process.parent.args_countgt
  • 1 transforms: number
field:"process.parent.args_count" kind:gt value:"1"
process.parent.namewildcard
  • awk
  • bash
  • csh
  • dash
  • fish
  • ksh
  • lua*
  • nc
  • nc.openbsd
  • nc.traditional
  • ncat
  • netcat
  • netcat.openbsd
  • netcat.traditional
  • node
  • openssl
  • perl
  • php*
  • python*
  • ruby
  • sh
  • socat
  • tcsh
  • telnet
  • zsh
field:"parent_process_name" kind:wildcard