Detection rules › Elastic
Udev Execution Followed by Egress Network Connection
This rule detects a process execution by udev followed by a network connection. Udev is a device manager for the Linux kernel that manages device nodes in /dev. Udev is responsible for creating and removing device nodes in /dev when devices are added or removed from the system. Udev executes scripts when devices are added or removed from the system. An attacker may abuse udev to execute malicious scripts to establish a network connection to a command and control server.
MITRE ATT&CK coverage
| Tactic | Techniques |
|---|---|
| Execution | |
| Persistence | |
| Command & Control |
Rule body
[rule]
description = """
This rule detects a process execution by udev followed by a network connection. Udev is a device manager for the Linux
kernel that manages device nodes in /dev. Udev is responsible for creating and removing device nodes in /dev when
devices are added or removed from the system. Udev executes scripts when devices are added or removed from the system.
An attacker may abuse udev to execute malicious scripts to establish a network connection to a command and control
server.
"""
id = "21984abc-9efa-4de1-b1ad-bf797a7acec9"
license = "Elastic License v2"
name = "Udev Execution Followed by Egress Network Connection"
os_list = ["linux"]
reference = [
"https://ch4ik0.github.io/en/posts/leveraging-Linux-udev-for-persistence/",
"https://www.elastic.co/security-labs/sequel-on-persistence-mechanisms",
]
version = "1.0.12"
query = '''
sequence by process.entity_id with maxspan=3s
[process where event.type == "start" and event.action == "exec" and
descendant of [process where event.action == "exec" and process.name == "udevadm"] and not (
process.parent.executable == "/etc/telegraf/get-service-status.sh" or
process.args == "/sbin/vz-motd" or
process.command_line like "*petalinux.xilinx.com*"
)
]
[network where event.type == "start" and event.action == "connection_attempted" and not (
destination.ip == null or
destination.ip == "0.0.0.0" or
cidrmatch(
destination.ip, "10.0.0.0/8", "127.0.0.0/8", "169.254.0.0/16", "172.16.0.0/12", "192.0.0.0/24", "192.0.0.0/29",
"192.0.0.8/32", "192.0.0.9/32", "192.0.0.10/32", "192.0.0.170/32", "192.0.0.171/32", "192.0.2.0/24",
"192.31.196.0/24", "192.52.193.0/24", "192.168.0.0/16", "192.88.99.0/24", "224.0.0.0/4", "100.64.0.0/10",
"192.175.48.0/24","198.18.0.0/15", "198.51.100.0/24", "203.0.113.0/24", "240.0.0.0/4", "::1", "FE80::/10",
"FF00::/8", "172.31.0.0/16"
) or
process.name == "go" or
process.executable like (
"/var/lib/docker/overlay2/*gitlab-runner-helper", "/opt/tm/tools/go/usr/bin/go*", "/var/lib/docker/overlay2/*/aws_signing_helper",
"/home/*/cpython/*/python3", "/var/opt/gitlab/*", "/home/*/core3/src/plz-out/*/usr/python3.10/bin/python3*"
) or
process.executable in (
"/usr/local/bin/rclone", "/usr/lib/git/git-remote-https", "/usr/lib/apt/methods/https", "/usr/lib/apt/methods/http",
"/usr/sbin/send_nsca", "/usr/libexec/git-core/git-remote-http"
)
)
]
'''
min_endpoint_version = "7.15.0"
optional_actions = []
[[actions]]
action = "kill_process"
field = "process.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 = "T1037"
name = "Boot or Logon Initialization Scripts"
reference = "https://attack.mitre.org/techniques/T1037/"
[threat.tactic]
id = "TA0003"
name = "Persistence"
reference = "https://attack.mitre.org/tactics/TA0003/"
[[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
Ordered sequence: each step below must occur in order within 3s, correlated by process.entity_id.
Stage 1: process
[process where event.type == "start" and event.action == "exec" and
descendant of [process where event.action == "exec" and process.name == "udevadm"] and not (
process.parent.executable == "/etc/telegraf/get-service-status.sh" or
process.args == "/sbin/vz-motd" or
process.command_line like "*petalinux.xilinx.com*"
)
]
Stage 2: network
[network where event.type == "start" and event.action == "connection_attempted" and not (
destination.ip == null or
destination.ip == "0.0.0.0" or
cidrmatch(
destination.ip, "10.0.0.0/8", "127.0.0.0/8", "169.254.0.0/16", "172.16.0.0/12", "192.0.0.0/24", "192.0.0.0/29",
"192.0.0.8/32", "192.0.0.9/32", "192.0.0.10/32", "192.0.0.170/32", "192.0.0.171/32", "192.0.2.0/24",
"192.31.196.0/24", "192.52.193.0/24", "192.168.0.0/16", "192.88.99.0/24", "224.0.0.0/4", "100.64.0.0/10",
"192.175.48.0/24","198.18.0.0/15", "198.51.100.0/24", "203.0.113.0/24", "240.0.0.0/4", "::1", "FE80::/10",
"FF00::/8", "172.31.0.0/16"
) or
process.name == "go" or
process.executable like (
"/var/lib/docker/overlay2/*gitlab-runner-helper", "/opt/tm/tools/go/usr/bin/go*", "/var/lib/docker/overlay2/*/aws_signing_helper",
"/home/*/cpython/*/python3", "/var/opt/gitlab/*", "/home/*/core3/src/plz-out/*/usr/python3.10/bin/python3*"
) or
process.executable in (
"/usr/local/bin/rclone", "/usr/lib/git/git-remote-https", "/usr/lib/apt/methods/https", "/usr/lib/apt/methods/http",
"/usr/sbin/send_nsca", "/usr/libexec/git-core/git-remote-http"
)
)
]
Exclusions
The rule actively suppresses these predicates.
| Field | Kind | Excluded values | Search |
|---|---|---|---|
process.args | eq | /sbin/vz-motd | excludes:process.args field:"process.args" value:"/sbin/vz-motd" |
process.command_line | match | petalinux.xilinx.com | excludes:process.command_line field:"process.command_line" value:"petalinux.xilinx.com" |
process.parent.executable | eq | /etc/telegraf/get-service-status.sh | excludes:process.parent.executable field:"process.parent.executable" value:"/etc/telegraf/get-service-status.sh" |
destination.ip | cidr_match | 10.0.0.0/8, 127.0.0.0/8, 169.254.0.0/16, 172.16.0.0/12, 192.0.0.0/24, 192.0.0.0/29, 192.0.0.8/32, 192.0.0.9/32, 192.0.0.10/32, 192.0.0.170/32, 192.0.0.171/32, 192.0.2.0/24, 192.31.196.0/24, 192.52.193.0/24, 192.168.0.0/16, 192.88.99.0/24, 224.0.0.0/4, 100.64.0.0/10, 192.175.48.0/24, 198.18.0.0/15, 198.51.100.0/24, 203.0.113.0/24, 240.0.0.0/4, ::1, FE80::/10, FF00::/8, 172.31.0.0/16 | excludes:destination.ip |
destination.ip | eq | 0.0.0.0 | excludes:destination.ip field:"destination.ip" value:"0.0.0.0" |
destination.ip | is_null | excludes:destination.ip | |
process.executable | in | /usr/lib/apt/methods/http, /usr/lib/apt/methods/https, /usr/lib/git/git-remote-https, /usr/libexec/git-core/git-remote-http, /usr/local/bin/rclone, /usr/sbin/send_nsca | excludes:process.executable |
process.executable | wildcard | /var/lib/docker/overlay2/*gitlab-runner-helper, /opt/tm/tools/go/usr/bin/go*, /var/lib/docker/overlay2/*/aws_signing_helper, /home/*/cpython/*/python3, /var/opt/gitlab/*, /home/*/core3/src/plz-out/*/usr/python3.10/bin/python3* | excludes:process.executable |
process.name | eq | go | excludes:process.name field:"process.name" value:"go" |
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 value:"start" |