Detection rules › Elastic

Potential Privilege Escalation via a Suspicious UID Change

Time window
30s
Sequence by
process.entity_id
Source
github.com/elastic/protections-artifacts

Detects a potential privilege escalation sequence via a suspicious UID change sequence. This rule checks for non-root execution of a process executable in a user or world-writeable directory followed by a UID change event to 0 (root). This sequence is indicative of a potential local privilege escalation exploit.

MITRE ATT&CK coverage

TacticTechniques
Privilege Escalation

Rule body

[rule]
description = """
Detects a potential privilege escalation sequence via a suspicious UID change sequence. This rule checks for non-root
execution of a process executable in a user or world-writeable directory followed by a UID change event to 0 (root).
This sequence is indicative of a potential local privilege escalation exploit.
"""
id = "8a744999-9b0b-4674-b621-e1fc0fc3718e"
license = "Elastic License v2"
name = "Potential Privilege Escalation via a Suspicious UID Change"
os_list = ["linux"]
version = "1.0.4"

query = '''
sequence by process.entity_id with maxspan=30s
  [process where event.type == "start" and event.action == "exec" and
  user.id != 0 and process.parent.user.id != 0 and process.parent.group.id != 0 and
  process.interactive == true and
  (
    process.executable like (".*", "/tmp/*", "/dev/shm/*", "/var/tmp/*", "/home/*/*", "/run/user/*", "/var/run/user/*") or
    process.parent.executable like (".*", "/tmp/*", "/dev/shm/*", "/var/tmp/*", "/home/*/*", "/run/user/*", "/var/run/user/*")
  ) and
  not (
    process.parent.executable like (
      "/tmp/go-build*/*/sso.test", "/run/user/*/.bubblewrap/newroot/*", "/tmp/newroot/*", "/var/lib/snapd/snap/node/*/bin/node",
      "/usr/libexec/gnome-session-binary", "/home/*/.local/bin/codex", "/home/*/.bun/bin/bun", "/home/*/.local/bin/agy",
      "/home/*/.nvm/versions/node/*/bin/codex*", "/home/*/.npm-global/*/bin/codex", "/home/*/.local/bin/copilot",
      "/home/*/.local/share/uv/python/cpython-*-linux-x86_64-gnu/bin/python3*", "/home/linuxbrew/.linuxbrew/Caskroom/*",
      "/home/*/.local/share/kiro-cli/*", "/home/*/.codex/packages/standalone/releases/*/bin/codex", "/home/*/.opencode/bin/opencode"
    ) or
    process.executable like ("/run/user/*/.bubblewrap/*", "/tmp/newroot/usr/bin/sudo") or
    (
      process.parent.name like "python*" and
      process.parent.args in ("muckrake_runner.run_tests", "terraform.kafka_runner.run-test")
    ) or
    (
      process.parent.executable == "/usr/bin/gnome-shell" and process.command_line == "/snap/bin/gnome-calculator"
    ) 
  )]
  [process where event.type == "change" and event.action == "uid_change" and
  user.id == 0 and process.parent.user.id != 0 and process.parent.group.id != 0 and
  process.executable != "/usr/bin/sudo"]
'''

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

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

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

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

[[threat]]
framework = "MITRE ATT&CK"
[[threat.technique]]
id = "T1068"
name = "Exploitation for Privilege Escalation"
reference = "https://attack.mitre.org/techniques/T1068/"


[threat.tactic]
id = "TA0004"
name = "Privilege Escalation"
reference = "https://attack.mitre.org/tactics/TA0004/"

[internal]
min_endpoint_version = "8.2.0"

Stages and Predicates

Ordered sequence: each step below must occur in order within 30s, correlated by process.entity_id.

Stage 1: process

[process where event.type == "start" and event.action == "exec" and
  user.id != 0 and process.parent.user.id != 0 and process.parent.group.id != 0 and
  process.interactive == true and
  (
    process.executable like (".*", "/tmp/*", "/dev/shm/*", "/var/tmp/*", "/home/*/*", "/run/user/*", "/var/run/user/*") or
    process.parent.executable like (".*", "/tmp/*", "/dev/shm/*", "/var/tmp/*", "/home/*/*", "/run/user/*", "/var/run/user/*")
  ) and
  not (
    process.parent.executable like (
      "/tmp/go-build*/*/sso.test", "/run/user/*/.bubblewrap/newroot/*", "/tmp/newroot/*", "/var/lib/snapd/snap/node/*/bin/node",
      "/usr/libexec/gnome-session-binary", "/home/*/.local/bin/codex", "/home/*/.bun/bin/bun", "/home/*/.local/bin/agy",
      "/home/*/.nvm/versions/node/*/bin/codex*", "/home/*/.npm-global/*/bin/codex", "/home/*/.local/bin/copilot",
      "/home/*/.local/share/uv/python/cpython-*-linux-x86_64-gnu/bin/python3*", "/home/linuxbrew/.linuxbrew/Caskroom/*",
      "/home/*/.local/share/kiro-cli/*", "/home/*/.codex/packages/standalone/releases/*/bin/codex", "/home/*/.opencode/bin/opencode"
    ) or
    process.executable like ("/run/user/*/.bubblewrap/*", "/tmp/newroot/usr/bin/sudo") or
    (
      process.parent.name like "python*" and
      process.parent.args in ("muckrake_runner.run_tests", "terraform.kafka_runner.run-test")
    ) or
    (
      process.parent.executable == "/usr/bin/gnome-shell" and process.command_line == "/snap/bin/gnome-calculator"
    ) 
  )]

Stage 2: process

[process where event.type == "change" and event.action == "uid_change" and
  user.id == 0 and process.parent.user.id != 0 and process.parent.group.id != 0 and
  process.executable != "/usr/bin/sudo"]

Exclusions

The rule actively suppresses these predicates.

FieldKindExcluded valuesSearch
process.command_lineeq/snap/bin/gnome-calculatorexcludes:process.command_line field:"process.command_line" value:"/snap/bin/gnome-calculator"
process.parent.executableeq/usr/bin/gnome-shellexcludes:process.parent.executable field:"process.parent.executable" value:"/usr/bin/gnome-shell"
process.parent.argsinmuckrake_runner.run_tests, terraform.kafka_runner.run-testexcludes:process.parent.args field:"process.parent.args" value:"muckrake_runner.run_tests" field:"process.parent.args" value:"terraform.kafka_runner.run-test"
process.parent.namestarts_withpythonexcludes:process.parent.name field:"process.parent.name" value:"python"
process.executablewildcard/run/user/*/.bubblewrap/*, /tmp/newroot/usr/bin/sudoexcludes:process.executable field:"process.executable" value:"/run/user/*/.bubblewrap/*" field:"process.executable" value:"/tmp/newroot/usr/bin/sudo"
process.parent.executablewildcard/tmp/go-build*/*/sso.test, /run/user/*/.bubblewrap/newroot/*, /tmp/newroot/*, /var/lib/snapd/snap/node/*/bin/node, /usr/libexec/gnome-session-binary, /home/*/.local/bin/codex, /home/*/.bun/bin/bun, /home/*/.local/bin/agy, /home/*/.nvm/versions/node/*/bin/codex*, /home/*/.npm-global/*/bin/codex, /home/*/.local/bin/copilot, /home/*/.local/share/uv/python/cpython-*-linux-x86_64-gnu/bin/python3*, /home/linuxbrew/.linuxbrew/Caskroom/*, /home/*/.local/share/kiro-cli/*, /home/*/.codex/packages/standalone/releases/*/bin/codex, /home/*/.opencode/bin/opencodeexcludes:process.parent.executable

Indicators

These rows show field, operator, and value matches.