← Back to sandbox
Security — Protocol Advanced 3 possible tests

HTTP Request Smuggling

A proxy and backend server disagree about where one request ends. By sending conflicting Content-Length and Transfer-Encoding headers an attacker poisons the backend's read buffer — prepending an arbitrary prefix to the next user's request.

What is HTTP Request Smuggling?

Modern stacks route HTTP through at least two hops: a frontend (CDN, load-balancer, reverse proxy) and a backend application server. Both must agree on exactly how many bytes each request contains. HTTP/1.1 allows two framing methods: Content-Length (a fixed byte count) and Transfer-Encoding: chunked (a streaming format). When the frontend and backend each pick a different framing rule for the same request, an attacker can craft a body that looks complete to one hop but leaves bytes in the other's buffer — bytes that get prepended to the next user's legitimate request.

What is hidden here

Bug FoundCL.TE — frontend uses Content-Length, backend uses Transfer-Encoding; smuggled prefix poisons next request
Bug FoundTE.TE — obfuscated second Transfer-Encoding header causes one server to fall back to Content-Length, recreating the desync
True PositiveHardened endpoint rejects any request containing conflicting or duplicate framing headers with 400 Bad Request

Test 1 — CL.TE: Content-Length Front, Transfer-Encoding Back

The frontend proxy reads Content-Length: 49 and forwards exactly 49 bytes. The backend ignores Content-Length when Transfer-Encoding is present, processes the body as chunked, and finds a chunk terminator before byte 49 — leaving the remainder as a dangling prefix for the next request.

✗ Unsafe — proxy/backend framing mismatch
Crafted request sent to the frontend
POST /search HTTP/1.1 Host: safronnynov.com Content-Type: application/x-www-form-urlencoded Content-Length: 49 ← frontend uses this Transfer-Encoding: chunked ← backend uses this 0e ← chunk size: 14 bytes q=smuggling+test 0 ← chunked terminator GET /admin HTTP/1.1 ← smuggled prefix (byte 40–49) Host: internal
Frontend (proxy) saw
Backend (app) saw

Test 2 — TE.TE: Obfuscated Transfer-Encoding

Both servers honour Transfer-Encoding, but the attacker sends two TE headers. The second uses an unrecognised token (xchunked). Whichever server drops the invalid header falls back to Content-Length — recreating a classic CL/TE desync without the two headers ever appearing obviously contradictory.

✗ Unsafe — TE obfuscation not normalised
Crafted request with duplicate Transfer-Encoding
POST /search HTTP/1.1 Host: safronnynov.com Content-Type: application/x-www-form-urlencoded Content-Length: 4 ← backend falls back to this Transfer-Encoding: chunked ← frontend honours Transfer-Encoding: xchunked ← backend rejects → uses CL instead 5c ← chunk size: 92 bytes POST /transfer HTTP/1.1 ← payload starts here Host: internal Content-Length: 50 amount=9999&to=attacker 0 ← chunked terminator
Frontend (proxy) saw
Backend (app) saw

Test 3 — Hardened Endpoint: Reject Ambiguous Framing

The safe endpoint inspects every incoming request before forwarding. Any request containing both Content-Length and Transfer-Encoding, or multiple TE headers, is returned with 400 Bad Request and the connection is closed — nothing is forwarded to the backend. Test both CL.TE and TE.TE payloads against it.

✓ Hardened — ambiguous framing rejected
Frontend (proxy) saw
Backend (app) saw

  • Test 1 — click Simulate Attack. The frontend forwards 49 bytes (per Content-Length). The backend reads the chunked terminator at byte 30, then has 19 leftover bytes that become GET /admin… prepended to the next user's request (bug found).
  • Test 2 — click Simulate Attack. The second Transfer-Encoding: xchunked causes the backend to discard both TE headers and fall back to Content-Length: 4. The 88 remaining bytes poison the next request with a forged transfer payload (bug found).
  • Test 3 — click either rejection button. The hardened proxy detects conflicting framing headers before forwarding and returns 400. The backend never receives the request and its buffer is never poisoned (true positive).