EXPLORE
← Back to Explore
splunk_escuAnomaly

HTTP Duplicated Header

Detects when a request has more than one of the same header. This is commonly used in request smuggling and other web based attacks. HTTP Request Smuggling exploits inconsistencies in how front-end and back-end servers parse HTTP requests by using ambiguous or malformed headers to hide malicious requests within legitimate ones. Attackers leverage duplicate headers, particularly Content-Length and Transfer-Encoding, to cause different servers in the chain to disagree on where one request ends and another begins. RFC7230 states that a sender MUST NOT generate multiple header fields with the same field name in a message unless either the entire field value for that header field is defined as a comma-separated list or the header field is a well-known exception.

MITRE ATT&CK

command-and-controlinitial-access

Detection Query

`suricata` http.request_headers{}.name="*"
  | rename dest_ip as dest
  | spath path=http.request_headers{}.name output=header_names
  | mvexpand header_names
  | where lower(header_names) != "set-cookie"
  | stats count
    BY _raw, header_names, src_ip,
       dest
  | where count > 1
  | stats values(header_names) as duplicate_headers
    BY _raw, count, src_ip,
       dest
  | `http_duplicated_header_filter`

Author

Raven Tait, Splunk

Created

2026-03-10

Data Sources

Suricata

Tags

HTTP Request Smuggling
Raw Content
name: HTTP Duplicated Header
id: 1606cc5b-fd5f-4865-9fe3-0ed1eaec2df6
version: 3
date: '2026-03-10'
author: Raven Tait, Splunk
status: production
type: Anomaly
description: Detects when a request has more than one of the same header. This is commonly used in request smuggling and other web based attacks. HTTP Request Smuggling exploits inconsistencies in how front-end and back-end servers parse HTTP requests by using ambiguous or malformed headers to hide malicious requests within legitimate ones. Attackers leverage duplicate headers, particularly Content-Length and Transfer-Encoding, to cause different servers in the chain to disagree on where one request ends and another begins. RFC7230 states that a sender MUST NOT generate multiple header fields with the same field name in a message unless either the entire field value for that header field is defined as a comma-separated list or the header field is a well-known exception.
data_source:
    - Suricata
search: |-
    `suricata` http.request_headers{}.name="*"
      | rename dest_ip as dest
      | spath path=http.request_headers{}.name output=header_names
      | mvexpand header_names
      | where lower(header_names) != "set-cookie"
      | stats count
        BY _raw, header_names, src_ip,
           dest
      | where count > 1
      | stats values(header_names) as duplicate_headers
        BY _raw, count, src_ip,
           dest
      | `http_duplicated_header_filter`
how_to_implement: This detection requires the Web datamodel to be populated from a supported Technology Add-On like Suricata, Splunk for Apache, Splunk for Nginx, or Splunk for Palo Alto. Some of these will need to have all headers dumped to contain the necessary fields.
known_false_positives: False positives are not expected, however, monitor, filter, and tune as needed based on organization log sources.
references:
    - https://portswigger.net/web-security/request-smuggling#what-is-http-request-smuggling
    - https://portswigger.net/research/http1-must-die
    - https://www.vaadata.com/blog/what-is-http-request-smuggling-exploitations-and-security-best-practices/
    - https://www.securityweek.com/new-http-request-smuggling-attacks-impacted-cdns-major-orgs-millions-of-websites/
drilldown_searches:
    - name: View the detection results for - "$dest$"
      search: '%original_detection_search% | search  dest = "$dest$"'
      earliest_offset: $info_min_time$
      latest_offset: $info_max_time$
    - name: View risk events for the last 7 days for - "$dest$"
      search: '| from datamodel Risk.All_Risk | search normalized_risk_object IN ("$dest$") starthoursago=168  | stats count min(_time) as firstTime max(_time) as lastTime values(search_name) as "Search Name" values(risk_message) as "Risk Message" values(analyticstories) as "Analytic Stories" values(annotations._all) as "Annotations" values(annotations.mitre_attack.mitre_tactic) as "ATT&CK Tactics" by normalized_risk_object | `security_content_ctime(firstTime)` | `security_content_ctime(lastTime)`'
      earliest_offset: $info_min_time$
      latest_offset: $info_max_time$
rba:
    message: Duplicated headers within a web request was detected. The source IP is $src_ip$ and the destination is $dest$.
    risk_objects:
        - field: dest
          type: system
          score: 20
    threat_objects:
        - field: src_ip
          type: ip_address
tags:
    analytic_story:
        - HTTP Request Smuggling
    asset_type: Network
    mitre_attack_id:
        - T1071.001
        - T1190
    product:
        - Splunk Enterprise
        - Splunk Enterprise Security
        - Splunk Cloud
    security_domain: network
tests:
    - name: True Positive Test
      attack_data:
        - data: https://media.githubusercontent.com/media/splunk/attack_data/master/datasets/attack_techniques/T1190/request_smuggling/suricata_request_smuggling.log
          sourcetype: suricata
          source: not_applicable