| ID | Technique | Tactic |
|---|---|---|
| T1068 | Exploitation for Privilege Escalation | Privilege Escalation |
Detection: Linux Suspicious Namespace Creation
Description
The following analytic detects an unprivileged user invoking the unshare syscall with user namespace flags followed within 120 seconds by a root-owned shell or interpreter spawning under the same parent process, correlating auditd syscall telemetry with Sysmon process creation events to identify the two-step sequence characteristic of user-namespace-based Linux kernel privilege escalation exploits such as DirtyFrag.
Search
1type=SYSCALL SYSCALL=unshare
2
3| where uid != "0" AND uid != "4294967295"
4
5| where a0 IN ("10000000","50000000","70000000","10020000","50020000","70020000")
6
7| eval unshare_time=_time,
8 unshare_pid=pid,
9 unshare_ppid=ppid,
10 trigger_uid=uid,
11 trigger_auid=auid,
12 trigger_exe=exe,
13 ns_flags=a0
14
15| table host, unshare_time, comm, syscall, unshare_pid, unshare_ppid,
16 trigger_uid, trigger_auid, trigger_exe, ns_flags
17
18| join type=inner host unshare_ppid [
19 search `sysmon` EventID=1 User=root
20
21| where match(Image, "/(su
22|sudo
23|pkexec
24|passwd
25|chsh
26|newgrp
27|doas
28|run0
29|sg
30|dash
31|sh
32|bash
33|zsh
34|fish
35|ksh
36|csh
37|tcsh
38|ash
39|mksh
40|busybox
41|tmux
42|screen
43|node
44|python[^/]*
45|perl[^/]*
46|ruby[^/]*
47|php[^/]*
48|lua[^/]*)$")
49
50| eval root_spawn_time=_time, root_pid=ProcessId,
51 root_exe=Image, root_cmdline=CommandLine, root_parent=ParentProcessId
52
53| rename ParentProcessId AS unshare_ppid
54
55| table host, unshare_ppid, root_spawn_time, root_pid,
56 root_exe, root_cmdline, root_parent, unshare_time,
57 action, original_file_name, parent_process, parent_process_exec,
58 parent_process_guid, parent_process_id, parent_process_name,
59 parent_process_path, process, process_exec, process_guid,
60 process_hash, process_id, process_integrity_level,
61 process_name, process_path, user, user_id, vendor_product
62]
63
64| where (root_spawn_time - unshare_time) >= 0
65
66| where (root_spawn_time - unshare_time) <= 120
67
68| eval elapsed_sec=round(root_spawn_time - unshare_time, 2)
69
70| eval ioc_match=case(
71 ns_flags="50000000", "dirtyfrag (CLONE_NEWUSER
72|CLONE_NEWNET)",
73 ns_flags="10000000", "CLONE_NEWUSER only",
74 ns_flags="70000000", "CLONE_NEWUSER
75|CLONE_NEWNET
76|CLONE_NEWPID",
77 1=1, "namespace flags="+ns_flags
78 )
79
80| rename host as dest
81
82| stats
83 count AS count,
84 min(unshare_time) AS firstTime,
85 max(unshare_time) AS lastTime,
86 values(trigger_uid) AS trigger_uid,
87 values(trigger_auid) AS trigger_auid,
88 values(trigger_exe) AS trigger_exe,
89 values(ns_flags) AS ns_flags,
90 values(ioc_match) AS ioc_match,
91 values(unshare_pid) AS unshare_pid,
92 values(unshare_ppid) AS unshare_ppid,
93 values(root_exe) AS root_exe,
94 values(root_cmdline) AS root_cmdline,
95 values(root_pid) AS root_pid,
96 values(elapsed_sec) AS elapsed_sec,
97 values(process_hash) AS process_hash,
98 values(vendor_product) AS vendor_product
99 by dest, comm, syscall
100
101| `security_content_ctime(firstTime)`
102
103| `security_content_ctime(lastTime)`
104
105| `linux_suspicious_namespace_creation_filter`
Data Source
| Name | Platform | Sourcetype | Source |
|---|---|---|---|
| Sysmon for Linux EventID 1 | 'sysmon:linux' |
'Syslog:Linux-Sysmon/Operational' |
|
| Linux Auditd Syscall | 'auditd' |
'auditd' |
Macros Used
| Name | Value |
|---|---|
| security_content_ctime | convert timeformat="%Y-%m-%dT%H:%M:%S" ctime($field$) |
| linux_suspicious_namespace_creation_filter | search * |
linux_suspicious_namespace_creation_filter is an empty macro by default. It allows the user to filter out any results (false positives) without editing the SPL.
Annotations
CVE
Default Configuration
This detection is configured by default in Splunk Enterprise Security to run with the following settings:
| Setting | Value |
|---|---|
| Disabled | true |
| Cron Schedule | 0 * * * * |
| Earliest Time | -70m@m |
| Latest Time | -10m@m |
| Schedule Window | auto |
| Creates Finding (Notable) | Yes |
| Rule Title | %name% |
| Rule Description | %description% |
| Notable Event Fields | user, dest |
| Creates Intermediate Finding (Risk Event) | No |
Implementation
To implement this detection, the process begins by ingesting auditd data, that consist SYSCALL, TYPE, EXECVE and PROCTITLE events, which captures command-line executions and process details on Unix/Linux systems. These logs should be ingested and processed using Splunk Add-on for Unix and Linux (https://splunkbase.splunk.com/app/833), which is essential for correctly parsing and categorizing the data. The next step involves normalizing the field names to match the field names set by the Splunk Common Information Model (CIM) to ensure consistency across different data sources and enhance the efficiency of data modeling and make sure the type=CWD record type is activate in your auditd configuration. This approach enables effective monitoring and detection of linux endpoints where auditd is deployed.
Known False Positives
No false positives have been identified at this time.
Associated Analytic Story
Finding
| Title | Entity Field | Entity Type | Risk Score |
|---|---|---|---|
| Suspicious namespace created on $dest$ indicating possible privilege escalation via DirtyFrag. | dest | system | 50 |
References
Detection Testing
| Test Type | Status | Dataset | Source | Sourcetype |
|---|---|---|---|---|
| Validation | ✅ Passing | N/A | N/A | N/A |
| Unit | ✅ Passing | Dataset | auditd |
auditd |
| Integration | ✅ Passing | Dataset | auditd |
auditd |
Replay any dataset to Splunk Enterprise by using our replay.py tool or the UI.
Alternatively you can replay a dataset into a Splunk Attack Range
Source: GitHub | Version: 1