Suspicious Python Shell Command Execution

Detects the execution of suspicious shell commands via the Python interpreter. Attackers may use Python to execute shell commands to gain access to the system or to perform other malicious activities, such as credential access, data exfiltration, or lateral movement.

Elastic rule (View on GitHub)

  1[metadata]
  2creation_date = "2026/03/26"
  3integration = ["endpoint"]
  4maturity = "production"
  5updated_date = "2026/03/26"
  6
  7[rule]
  8author = ["Elastic"]
  9description = """
 10Detects the execution of suspicious shell commands via the Python interpreter. Attackers 
 11may use Python to execute shell commands to gain access to the system or to perform other
 12malicious activities, such as credential access, data exfiltration, or lateral movement.
 13"""
 14from = "now-9m"
 15language = "esql"
 16license = "Elastic License v2"
 17name = "Suspicious Python Shell Command Execution"
 18risk_score = 47
 19rule_id = "b42e4b88-fc4a-417b-a45e-4d4a3db9fd41"
 20severity = "medium"
 21tags = [
 22    "Domain: Endpoint",
 23    "OS: Linux",
 24    "OS: macOS",
 25    "Use Case: Threat Detection",
 26    "Tactic: Execution",
 27    "Data Source: Elastic Defend",
 28]
 29type = "esql"
 30query = '''
 31FROM logs-endpoint.events.process-* METADATA _id, _version, _index
 32
 33| WHERE host.os.type in ("linux", "macos") and event.type == "start" and TO_LOWER(process.parent.name) like "python*" and
 34  process.name in ("bash", "dash", "sh", "tcsh", "csh", "zsh", "ksh", "fish", "busybox") and
 35  KQL("""event.action:"exec" and process.args:("-c" or "-cl" or "-lc")""")
 36
 37// truncate timestamp to 1-minute window
 38| EVAL Esql.time_window_date_trunc = DATE_TRUNC(1 minutes, @timestamp)
 39
 40| EVAL Esql.process_command_line_patterns = CASE(
 41  process.command_line like "*grep*", "grep",
 42  process.command_line like "*find*", "find",
 43  process.command_line like "*curl*", "curl",
 44  process.command_line like "*env *", "environment_enumeration",
 45  process.command_line like "*wget*", "wget",
 46  process.command_line like "*whoami*" or process.command_line like "*uname*" or process.command_line like "*hostname*", "discovery", "other"
 47)
 48
 49| KEEP
 50    @timestamp,
 51    _id,
 52    _index,
 53    _version,
 54    Esql.process_command_line_patterns,
 55    Esql.time_window_date_trunc,
 56    host.os.type,
 57    event.type,
 58    event.action,
 59    process.parent.name,
 60    process.working_directory,
 61    process.parent.working_directory,
 62    process.name,
 63    process.executable,
 64    process.command_line,
 65    process.parent.executable,
 66    process.parent.entity_id,
 67    agent.id,
 68    host.name,
 69    event.dataset,
 70    data_stream.namespace
 71
 72| STATS
 73  Esql.process_command_line_count_distinct = COUNT_DISTINCT(process.command_line),
 74  Esql.patterns_count_distinct = COUNT_DISTINCT(Esql.process_command_line_patterns),
 75  Esql.process_command_line_values = VALUES(process.command_line),
 76  Esql.host_name_values = values(host.name),
 77  Esql.agent_id_values = values(agent.id),
 78  Esql.event_dataset_values = values(event.dataset),
 79  Esql.data_stream_namespace_values = values(data_stream.namespace)
 80  BY process.parent.entity_id, agent.id, host.name, Esql.time_window_date_trunc
 81
 82| SORT Esql.process_command_line_count_distinct DESC
 83| WHERE Esql.process_command_line_count_distinct >= 5 AND Esql.patterns_count_distinct >= 4
 84'''
 85
 86[[rule.threat]]
 87framework = "MITRE ATT&CK"
 88
 89[[rule.threat.technique]]
 90id = "T1059"
 91name = "Command and Scripting Interpreter"
 92reference = "https://attack.mitre.org/techniques/T1059/"
 93
 94[[rule.threat.technique.subtechnique]]
 95id = "T1059.006"
 96name = "Python"
 97reference = "https://attack.mitre.org/techniques/T1059/006/"
 98
 99[rule.threat.tactic]
100id = "TA0002"
101name = "Execution"
102reference = "https://attack.mitre.org/tactics/TA0002/"

Related rules

to-top