| ID | Technique | Tactic |
|---|---|---|
| T1190 | Exploit Public-Facing Application | Initial Access |
Detection: PHP Session Upload Progress Serialized Payload in Upload Filename
Description
This analytic detects multipart POST requests containing the "PHP_SESSION_UPLOAD_PROGRESS" form field and a serialized PHP structure in an uploaded filename. This combination may indicate an attempt to exploit PHP session upload-progress handling and can be associated with PHP2Shell activity.
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_upload_progress_field=if(match(request_headers, "(?im)\s*form-data;\\s*name=\\\"PHP_SESSION_UPLOAD_PROGRESS\\\""), 1, 0)
12
13
14| rex max_match=0 field=request_headers "(?im)\s*form-data;(?<part_disposition>[^\\r\\n]*)"
15
16
17| eval serialized_filename_headers=mvfilter(match(part_disposition, "(?i)\\bfilename\\s*=.*(?:\\
18|?O:\\d+:
19|C:\\d+:
20|a:\\d+:\\{
21|s:\\d+:
22|E:\\d+:
23|R:\\d+;
24|i:-?\\d+;
25|d:(?:[-+]?(?:\\d+(?:\\.\\d*)?
26|\\.\\d+)(?:[eE][-+]?\\d+)?
27|INF
28|NAN);
29|b:[01];
30|N;)"))
31
32
33| where has_upload_progress_field=1 AND mvcount(serialized_filename_headers)>0
34
35
36| stats count min(_time) as firstTime
37 max(_time) as lastTime
38 values(method) as method
39 values(status_code) as status_code
40 values(user_agent) as user_agent
41 values(serialized_filename_headers) as serialized_filename_headers
42
43 by src dest dest_port uri
44
45
46| `security_content_ctime(firstTime)`
47
48| `security_content_ctime(lastTime)`
49
50| `php_session_upload_progress_serialized_payload_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_serialized_payload_in_upload_filename_filter | search * |
php_session_upload_progress_serialized_payload_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="PHP_SESSION_UPLOAD_PROGRESS" and an upload filename containing a serialized PHP token.
Known False Positives
Applications may upload files with names containing serialized-looking text as part of testing or unusual workflows. Review the complete request headers, source, destination, and application context before determining intent.
Associated Analytic Story
Intermediate Findings
| Message | Entity Field | Entity Type | Risk Score |
|---|---|---|---|
| A multipart POST request from [$src$] to [$dest$] included PHP_SESSION_UPLOAD_PROGRESS and a serialized PHP structure in an upload filename. | dest | system | 40 |
Threat Objects
| Field | Type |
|---|---|
| src | ip_address |
| serialized_filename_headers | 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