Detection rules › Elastic
Potential Privilege Escalation via a Suspicious UID Change
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
| Tactic | Techniques |
|---|---|
| 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.
| Field | Kind | Excluded values | Search |
|---|---|---|---|
process.command_line | eq | /snap/bin/gnome-calculator | excludes:process.command_line field:"process.command_line" value:"/snap/bin/gnome-calculator" |
process.parent.executable | eq | /usr/bin/gnome-shell | excludes:process.parent.executable field:"process.parent.executable" value:"/usr/bin/gnome-shell" |
process.parent.args | in | muckrake_runner.run_tests, terraform.kafka_runner.run-test | excludes:process.parent.args field:"process.parent.args" value:"muckrake_runner.run_tests" field:"process.parent.args" value:"terraform.kafka_runner.run-test" |
process.parent.name | starts_with | python | excludes:process.parent.name field:"process.parent.name" value:"python" |
process.executable | wildcard | /run/user/*/.bubblewrap/*, /tmp/newroot/usr/bin/sudo | excludes:process.executable field:"process.executable" value:"/run/user/*/.bubblewrap/*" field:"process.executable" value:"/tmp/newroot/usr/bin/sudo" |
process.parent.executable | wildcard | /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 | excludes:process.parent.executable |
Indicators
These rows show field, operator, and value matches.
| Field | Kind | Values | Search |
|---|---|---|---|
event.action | eq |
| field:"EventType" kind:eq |
event.type | eq |
| field:"event.type" kind:eq |
process.executable | ne |
| field:"Image" kind:ne value:"/usr/bin/sudo" |
process.executable | wildcard |
| field:"Image" kind:wildcard |
process.interactive | eq |
| field:"process.interactive" kind:eq value:"true" |
process.parent.executable | wildcard |
| field:"ParentImage" kind:wildcard |
process.parent.group.id | ne |
| field:"process.parent.group.id" kind:ne value:"0" |
process.parent.user.id | ne |
| field:"process.parent.user.id" kind:ne value:"0" |
user.id | eq |
| field:"user.id" kind:eq value:"0" |
user.id | ne |
| field:"user.id" kind:ne value:"0" |