| ID | Technique | Tactic |
|---|---|---|
| T1071.001 | Web Protocols | Command and Control |
| T1132.001 | Standard Encoding | Command and Control |
Detection: HTTP POST Request with Encoded Payload
Description
The following analytic detects HTTP POST requests containing heavily encoded data in the post body, specifically looking for sequences of hex, base64, URL, XML, Unicode, or Octal encoded strings. It leverages Zeek HTTP logs to identify POST requests where the body contains eight or more consecutive hex, URL, XML, Unicode, or Octal escape sequences or sixteen or more consecutive base64 character groups. This activity is significant as adversaries commonly use various encoding schemes to obfuscate C2 communication, exfiltrate data, or deliver encoded payloads.
Search
1`zeek_http`
2method="POST"
3post_body="*"
4
5NOT orig_mime_type_first_stated IN (
6 "application/x-www-form-urlencoded",
7 "application/ocsp-request"
8)
9
10NOT user_agent IN (
11 "MicroMessenger Client",
12 "Dalvik*",
13 "AliPayWallet*"
14)
15
16
17| eval dest_port=coalesce(dest_port, 'id.resp_p'),
18 dest=coalesce(dest, dest_ip, 'id.resp_h'),
19 src=coalesce(src, src_ip, 'id.orig_h')
20
21
22| eval encoding=ltrim(if(match(post_body, "(?:\\\\x[0-9a-fA-F]{2}){8,}
23|(?:%[0-9a-fA-F]{2}){8,}"), "Hexadecimal", ""), " + ")
24
25| eval encoding=ltrim(if(match(post_body, "(?:[A-Za-z0-9+\\/]{4}){16,}={0,2}"), encoding." + Base64", encoding), " + ")
26
27| eval encoding=ltrim(if(match(post_body, "(?:0x[A-Fa-f0-9]{2}){8,}"), encoding." + URL Encoding", encoding), " + ")
28
29| eval encoding=ltrim(if(match(post_body, "(?:\\&\\#x?[A-Za-z0-9]{2,3}\;?){8,}"), encoding." + XML Encoding", encoding), " + ")
30
31| eval encoding=ltrim(if(match(post_body, "(?:\\\\u[A-Fa-f0-9]{4}
32|\\\\u\{[A-Fa-f0-9]+\}){8,}"), encoding." + Unicode", encoding), " + ")
33
34| eval encoding=ltrim(if(match(post_body, "(?:\\\\\\d{3}){8,}"), encoding." + Octal", encoding), " + ")
35
36
37| where encoding!=""
38
39
40| stats count min(_time) as firstTime
41 max(_time) as lastTime
42 values(uri) as uri
43 values(encoding) as encoding
44 values(post_body) as post_body
45
46 by src dest dest_port method status_code
47
48
49| `security_content_ctime(firstTime)`
50
51| `security_content_ctime(lastTime)`
52
53| `http_post_request_with_encoded_payload_filter`
Data Source
| Name | Platform | Sourcetype | Source |
|---|---|---|---|
| Zeek HTTP | Web | 'zeek:http' |
'http.log' |
Macros Used
| Name | Value |
|---|---|
| zeek_http | sourcetype="zeek:http" |
| http_post_request_with_encoded_payload_filter | search * |
http_post_request_with_encoded_payload_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
Zeek HTTP logs must be ingested into Splunk using the latest version of Splunk Add-on for Zeek (https://splunkbase.splunk.com/app/5466).
The "post_body" field must be populated, which requires Zeek to be configured with the HTTP post body extraction policy.
Configure the zeek_http macro to match the sourcetype used by your Zeek add-on.
Known False Positives
Legitimate applications may POST base64-encoded data, particularly APIs that transmit binary content. Review the destination, URI, and post body content to confirm whether the activity is expected.
Associated Analytic Story
Intermediate Findings
| Message | Entity Field | Entity Type | Risk Score |
|---|---|---|---|
| An HTTP POST request with an encoded body of type [$encoding$] was detected from [$src$] to [$dest$] over port [$dest_port$] to URI - [$uri$]. | src | system | 20 |
Threat Objects
| Field | Type |
|---|---|
| uri | uri |
References
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