| ID | Technique | Tactic |
|---|---|---|
| T1190 | Exploit Public-Facing Application | Initial Access |
Detection: PHP Session Upload Progress with PHP Code in Upload Filename
Description
This analytic detects multipart POST requests containing a PHPSESSID form field and an uploaded filename with a PHP opening tag. When observed with "PHP_SESSION_UPLOAD_PROGRESS" behavior, this may indicate an attempt to place executable PHP content into session-related data as part of PHP2Shell exploitation.
Search
1`zeek_http`
2method="POST"
3request_headers="*"
4
5
6| eval src=coalesce(src, src_ip, 'id.orig_h'),
7 dest=coalesce(dest, dest_ip, 'id.resp_h'),
8 dest_port=coalesce(dest_port, 'id.resp_p')
9
10
11| eval has_phpsessid_field=if(match(request_headers, "(?im)\s*form-data;[^\\r\\n]*\\bname\\s*=\\s*\\\"?PHPSESSID\\\"?(?:;
12|[\\r\\n]
13|$)"), 1, 0)
14
15
16| rex max_match=0 field=request_headers "(?im)\s*form-data;(?<part_disposition>[^\\r\\n]*)"
17
18
19| eval php_open_tag_filenames=mvfilter(match(part_disposition, "(?i)\\bfilename\\s*=.*(?:<\\?php\\b
20|<\\?=)"))
21
22
23| where has_phpsessid_field=1 AND mvcount(php_open_tag_filenames)>0
24
25
26| stats count min(_time) as firstTime
27 max(_time) as lastTime
28 values(status_code) as status_code
29 values(user_agent) as user_agent
30 values(php_open_tag_filenames) as php_open_tag_filenames
31
32 by src dest dest_port uri
33
34
35| `security_content_ctime(firstTime)`
36
37| `security_content_ctime(lastTime)`
38
39| `php_session_upload_progress_with_php_code_in_upload_filename_filter`
Data Source
| Name | Platform | Sourcetype | Source |
|---|---|---|---|
| Zeek HTTP | Web | 'zeek:http' |
'http.log' |
Macros Used
| Name | Value |
|---|---|
| security_content_ctime | convert timeformat="%Y-%m-%dT%H:%M:%S" ctime($field$) |
| php_session_upload_progress_with_php_code_in_upload_filename_filter | search * |
php_session_upload_progress_with_php_code_in_upload_filename_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) | No |
| Creates Intermediate Finding (Risk Event) | Yes |
Implementation
Ingest Zeek http.log with the TA for Zeek (https://splunkbase.splunk.com/app/5466), then set the
zeek_http macro to select that data (the search expects sourcetype zeek:http by default). Standard
Zeek HTTP logs do not include full multipart request headers. Enable a Zeek HTTP header logging script or
package that captures client header names and values, and map them into request_headers. Each POST
record must include the Content-Disposition lines so the search can see name="PHPSESSID" and an
upload filename containing <?php or <?=.
Known False Positives
Security testing tools or development environments may upload files with PHP code in the filename. Review the request headers, destination application, and any follow-on requests or server-side execution evidence.
Associated Analytic Story
Intermediate Findings
| Message | Entity Field | Entity Type | Risk Score |
|---|---|---|---|
| A multipart POST request from [$src$] to [$dest$] included a PHPSESSID form field and a PHP opening tag in an upload filename. | dest | system | 40 |
Threat Objects
| Field | Type |
|---|---|
| src | ip_address |
| php_open_tag_filenames | file_name |
References
-
https://github.com/php/php-src/commit/3584a98bda0f2c0d367255b046798b0d3a221a19
-
https://docs.zeek.org/en/master/scripts/policy/protocols/http/header-names.zeek.html
Detection Testing
| Test Type | Status | Dataset | Source | Sourcetype |
|---|---|---|---|---|
| Validation | ✅ Passing | N/A | N/A | N/A |
| Unit | ✅ Passing | Dataset | http.log |
zeek:http |
| Integration | ✅ Passing | Dataset | http.log |
zeek:http |
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