HTTP Smuggling: Understanding the Attack Techniques and Detection Methods

Question: Is HTTP smuggling only applicable to HTTP and not HTTPS?

HTTP smuggling is not limited to HTTP; it can also be applied to HTTPS.

HTTP smuggling is an attack technique that exploits the differences in how front-end servers and back-end servers parse HTTP requests. By cleverly constructing requests, attackers can confuse the server when processing request boundaries, leading to unauthorized operations. Although HTTPS adds an SSL/TLS encryption layer on top of HTTP, it fundamentally still relies on the HTTP protocol for data transmission. There can still be inconsistencies in how front-end and back-end servers handle request headers, making them susceptible to HTTP smuggling attacks. For example, an attacker can exploit the different parsing methods of the Content-Length and Transfer-Encoding headers in an HTTPS connection to construct special requests for smuggling attacks.

Concept:

HTTP smuggling is an attack technique that utilizes vulnerabilities in HTTP protocol parsing. By constructing special HTTP requests, it creates discrepancies in how the front-end proxy server and the back-end origin server interpret the requests, allowing attackers to bypass security controls, steal data, or execute unauthorized operations.

Core Principles

The HTTP protocol relies on the <span>Content-Length</span> (CL) and <span>Transfer-Encoding: chunked</span> (TE) headers to determine the boundaries of the request body. When both headers are present in a request, or when there are differences in how proxies and back-end servers interpret the protocol parsing rules, it can lead to:

  • The proxy server believes a request has ended, but the back-end server still considers subsequent data as part of that request;
  • Or conversely, the proxy thinks the request is not finished, while the back-end has already processed it and is waiting for a new request, causing the malicious content injected by the attacker to be misinterpreted by the back-end as a new request.

Common Attack Types

1. CL-TE Smuggling

  • Scenario The front-end proxy only processes <span>Content-Length</span>, while the back-end server prioritizes <span>Transfer-Encoding: chunked</span>.
POST / HTTP/1.1
Host: example.com
Content-Length: 10
Transfer-Encoding: chunked
0
SMUGGLED

The proxy interprets the request body as CL=10 and believes the request has ended; the back-end interprets it as TE, treating <span>0</span> as the chunk terminator, and the subsequent <span>SMUGGLED</span> is treated as a new request.

2. TE-CL Smuggling

  • Scenario The front-end proxy processes <span>Transfer-Encoding</span>, while the back-end server only processes <span>Content-Length</span>.
  • Constructing the Request
    POST / HTTP/1.1
    Host: example.com
    Content-Length: 6
    Transfer-Encoding: chunked
    5caaaaa... (total 92 bytes)
    0
  • The front-end interprets it as TE and believes the chunked data has ended;
  • The back-end interprets it as CL=6, reading only the first 6 bytes, treating the remaining data as a new request.

3. Other Variants

  • CL-CL The request contains two different <span>Content-Length</span> headers, with the proxy and back-end choosing different values for parsing.
  • TE-TE By obfuscating the <span>Transfer-Encoding</span> field (e.g., adding spaces, changing case), one side may ignore that header.

Attack Consequences

  1. Bypassing Security Controls For example, bypassing WAF interception on specific paths and directly sending malicious requests to the back-end.
  2. Request Hijacking Stealing other users’ request data (e.g., session cookies, form submission content).
  3. Cache Pollution Causing the proxy to cache malicious content, affecting all users accessing that cache.
  4. Server-Side Request Forgery (SSRF) Forcing the back-end server to make unauthorized internal requests through smuggled requests.
  5. Remote Code Execution (RCE) If the back-end has vulnerabilities, smuggled requests can trigger them (e.g., command injection).

How to Determine the Type of Smuggling Present on the Server?

1. Basic Detection Approach

The essence of HTTP smuggling is the inconsistency in how the front-end proxy and back-end server interpret request boundaries. During detection, one should:

  1. Construct ambiguous HTTP requests (e.g., carrying both <span>Content-Length</span> and <span>Transfer-Encoding</span>).
  2. Observe whether the response exhibits characteristics of “parsing differences” (e.g., abnormal status codes, delays, content leakage, etc.).
  3. Match the response characteristics to the corresponding smuggling type (CL-TE, TE-CL, etc.).

2. Detection Methods for Different Smuggling Types

1. Detecting CL-TE Type (Front-end recognizes CL, back-end recognizes TE)

Characteristics: The front-end proxy only processes <span>Content-Length</span>, while the back-end server prioritizes <span>Transfer-Encoding: chunked</span>.

Test Request:

POST / HTTP/1.1
Host: example.com
Content-Length: 10
Transfer-Encoding: chunked
0
SMUGGLED
  • In the request body, <span>0</span> is the chunked encoding terminator (indicating the end of chunked data), and the subsequent <span>SMUGGLED</span> is the deliberately added “smuggled data”.

Expected Result:

  • If CL-TE smuggling exists:
    • The front-end proxy interprets it as <span>Content-Length:10</span>, believing the request body length is 10 bytes (including <span>0</span>, newline, and part of <span>SMUGGLED</span>), and forwards the complete request to the back-end.
    • The back-end interprets it as <span>Transfer-Encoding</span>, believing the request has ended after <span>0</span>, treating <span>SMUGGLED</span> as a new request, which may return an abnormal response (e.g., 404, 500) or delay (waiting for a new request).
  • If it does not exist: The server may directly reject requests containing ambiguous headers (e.g., 400 Bad Request).

2. Detecting TE-CL Type (Front-end recognizes TE, back-end recognizes CL)

Characteristics: The front-end proxy processes <span>Transfer-Encoding</span>, while the back-end server only processes <span>Content-Length</span>.

Test Request:

POST / HTTP/1.1
Host: example.com
Content-Length: 6
Transfer-Encoding: chunked
5caaaaa... (total 92 bytes of padding)
0
  • <span>Content-Length:6</span> indicates that the front-end believes the request body length is 6 bytes, while <span>Transfer-Encoding: chunked</span> indicates that it is parsed as chunked encoding, where <span>5c</span> is hexadecimal for 92 (indicating that the subsequent 92 bytes are chunk data), and <span>0</span> is the chunk terminator.

Expected Result:

  • If TE-CL smuggling exists:
    • The front-end interprets it as TE, believing the 92 bytes of chunk data + <span>0</span> is the complete request, and forwards it to the back-end.
    • The back-end interprets it as CL=6, reading only the first 6 bytes, treating the remaining data as a new request, leading to an abnormal back-end response (e.g., waiting for more data, resulting in a timeout).
  • If it does not exist: The server may reject the request or respond normally (no timeout).

3. Detecting CL-CL Type (Different CL recognized by front-end and back-end)

Characteristics: The request contains two different <span>Content-Length</span> headers, with the front-end and back-end choosing different values for parsing.

Test Request:

POST / HTTP/1.1
Host: example.com
Content-Length: 5
Content-Length: 10
abcde
  • The two <span>Content-Length</span> headers are 5 and 10, while the actual request body is 5 bytes (<span>abcde</span>).

Expected Result:

  • If CL-CL smuggling exists:
    • The front-end may take the first CL=5, believing the request body has ended, and forwards the complete content.
    • The back-end may take the second CL=10, believing the request body is incomplete, waiting for the remaining 5 bytes, resulting in a response timeout.
  • If it does not exist: The server usually rejects requests containing duplicate CL (e.g., 400 error).

4. Detecting TE-TE Type (Obfuscating TE header to evade parsing)

Characteristics: By transforming the <span>Transfer-Encoding</span> field (e.g., spaces, case), one side may ignore the TE header while the other parses it normally.

Test Request:

POST / HTTP/1.1
Host: example.com
Content-Length: 4
Transfer-Encoding: xchunked
Transfer-Encoding: chunked
0
  • Deliberately adding an invalid <span>Transfer-Encoding: xchunked</span> interferes with front-end parsing.

Expected Result:

  • If TE-TE smuggling exists:
    • The front-end may ignore the invalid <span>xchunked</span>, recognizing only <span>chunked</span>, and parses it as TE.
    • The back-end may ignore the entire TE header due to <span>xchunked</span> being invalid, parsing it as CL=4, leading to a parsing discrepancy.
  • If it does not exist: The server may reject requests with malformed TE headers.

3. Key Response Characteristics for Judgment

  1. Timeout or Delayed Response The back-end waits for an incomplete request body (as seen in TE-CL, CL-CL tests), indicating a discrepancy in how the front-end and back-end assess request length.
  2. Abnormal Status Codes Such as 404 (the smuggled path does not exist), 500 (back-end parsing error), which may indicate that the smuggled data is being treated as a new request.
  3. Content Leakage If the smuggled data contains other users’ request content (e.g., cookies from subsequent requests), it indicates request hijacking (a severe smuggling vulnerability).
  4. Request Rejection Returning 400 Bad Request may indicate that the server has defenses against ambiguous headers, suggesting no smuggling exists.

4. Tools for Assisted Detection

  1. Burp Suite Plugin<span>HTTP Smuggler</span> can automate the generation of the above test requests, analyze response differences, and determine the type of smuggling.
  2. Custom Scripts Use Python/Java to send test requests, record response times, status codes, etc., and compare results from different requests.

Tip 1:

Sometimes when we use bp to capture packets, sending some payloads may return HTTP Status 505 – Http Version Not Supported.

In this case, we can use the built-in copy fetch feature of Google Chrome:

Steps: Press F12, initiate the request, go to Network, then right-click on that request, select copy -> copy as fetch, and then paste it into the Console. Then add fetch().then(e => e.json()).then(res => {console.log(res)}) to print the response!

Tip 2:

If we want to see where credentials exist in the browser, such as Local Storage or Session Storage?

In this case, we can still press F12, then select Application, and the left side will show us what we want!

Leave a Comment