| ID | Technique | Tactic |
|---|---|---|
| T1059 | Command and Scripting Interpreter | Execution |
Detection: Linux Auditd Inline PHP Code Execution
Description
The following analytic detects PHP command-line interpreters executing code supplied directly on the command line with CLI code-execution options such as -r / --run and -B / -R / -E / -F, or PHP runtime INI overrides that can load code. It also detects code supplied to PHPDBG through the -s option and FrankenPHP php-cli execution. It covers common Linux CLI executable names, including php, versioned PHP binaries, phpdbg, and FrankenPHP. PHP-CGI and PHP-FPM are excluded from the CLI option branch because they do not support the PHP CLI inline -r option. This behavior can be used legitimately for administration and automation, but unexpected or obfuscated inline PHP execution may indicate an attacker using an installed interpreter to run commands without dropping a script file.
Search
1`linux_auditd`
2type=EXECVE
3"*php*"
4
5
6| eval process_name=lower(replace(coalesce(a0, ""), "^.*/", ""))
7
8| eval process=coalesce(execve_command, _raw)
9
10| rex "msg=audit\([^:]+:(?<audit_id>\d+)\)"
11
12
13| eval php_code_option=if(
14 match(process, "(^
15|[[:space:]])(-r
16|--run
17|-B
18|-R
19|-E
20|-F
21|--process-begin
22|--process-code
23|--process-file
24|--process-end)(=
25|[$[:space:]]
26|$)")
27 OR match(_raw, "a[0-9]+=\"(-r
28|--run
29|-B
30|-R
31|-E
32|-F
33|--process-begin
34|--process-code
35|--process-file
36|--process-end)(=
37|[$[:space:]]
38|\"
39|$)"),
40 1, 0
41 )
42
43| eval php_ini_override=if(
44 match(process, "(^
45|[[:space:]])(-d[[:space:]]+
46|-d
47|--define[[:space:]]+
48|--define=)(auto_prepend_file
49|auto_append_file
50|allow_url_include)=")
51 OR match(_raw, "a[0-9]+=\"(-d
52|--define)\" a[0-9]+=\"(auto_prepend_file
53|auto_append_file
54|allow_url_include)=")
55 OR match(_raw, "a[0-9]+=\"-d(auto_prepend_file
56|auto_append_file
57|allow_url_include)=")
58 OR match(_raw, "a[0-9]+=\"--define=(auto_prepend_file
59|auto_append_file
60|allow_url_include)=")
61 , 1, 0
62 )
63
64
65| where (
66 match(process_name, "^php([5-9](\\.[0-9]+)*)?(-cli)?$")
67 AND (php_code_option=1 OR php_ini_override=1)
68 AND NOT match(process_name, "(cgi
69|fpm)")
70 )
71 OR (
72 process_name="phpdbg"
73 AND (
74 match(process, "(^
75|[[:space:]])-s(=
76|[$[:space:]]
77|$)")
78 OR match(_raw, "a[0-9]+=\"-s(=
79|[$[:space:]]
80|\"
81|$)")
82 )
83 )
84 OR (
85 process_name="frankenphp"
86 AND match(process, "php-cli")
87 AND (php_code_option=1 OR php_ini_override=1)
88 )
89
90
91| rename host as dest
92
93
94| stats count min(_time) as firstTime max(_time) as lastTime
95 values(execve_command) as execve_command
96 values(a0) as argv0
97 values(auid) as auid
98 values(uid) as uid
99 values(audit_id) as audit_id
100 by dest process_name process
101
102
103| `security_content_ctime(firstTime)`
104
105| `security_content_ctime(lastTime)`
106
107| `linux_auditd_inline_php_code_execution_filter`
Data Source
| Name | Platform | Sourcetype | Source |
|---|---|---|---|
| Linux Auditd Execve | 'auditd' |
'auditd' |
Macros Used
| Name | Value |
|---|---|
| linux_auditd | sourcetype="auditd" |
| linux_auditd_inline_php_code_execution_filter | search * |
linux_auditd_inline_php_code_execution_filter is an empty macro by default. It allows the user to filter out any results (false positives) without editing the SPL.
Annotations
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) | No |
| Creates Intermediate Finding (Risk Event) | Yes |
Implementation
To implement this detection, the process begins by ingesting auditd data, that consists of 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. This approach enables effective monitoring and detection of Linux endpoints where auditd is deployed.
Known False Positives
Developers and administrators may use PHP CLI or PHPDBG for legitimate automation and troubleshooting. Review the command line, parent process, user, host, and execution context. Tune approved automation by host or parent process as needed.
Associated Analytic Story
Intermediate Findings
| Message | Entity Field | Entity Type | Risk Score |
|---|---|---|---|
| PHP inline code execution using [$process_name$] was observed on endpoint [$dest$] with command line [$process$]. | dest | system | 20 |
Threat Objects
| Field | Type |
|---|---|
| process_name | process_name |
| process | process |
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