TL;DR

  • Request smuggling happens when frontend and backend parse Content-Length and Transfer-Encoding differently.
  • Classic case: frontend uses CL, backend uses TE (CL.TE).
  • Look for desync: one request becomes two for the backend.

Concept

If the frontend trusts Content-Length and the backend trusts Transfer-Encoding: chunked, you can end the chunked body early and smuggle a second request in the remaining bytes.

Minimal CL.TE Example

POST / HTTP/1.1
Host: example.com
Content-Type: application/x-www-form-urlencoded
Content-Length: 35
Transfer-Encoding: chunked

0

GET /404 HTTP/1.1
X-Ignore: X

Why it works

  • Frontend: reads 35 bytes of body and forwards them as one request.
  • Backend: sees 0\r\n\r\n and ends the request early, then treats GET /404 as a new request.

What to Look For

  • Responses mismatching your visible request (e.g., you request / but get /404).
  • Desync only shows up on keep-alive connections.
  • Behavior depends on the proxy chain (nginx, HAProxy, load balancer).

Safe Testing Notes

  • Test in-scope only; be careful with payload counts.
  • Watch for unstable behavior or queue poisoning.
  • Use tooling that controls connection reuse and pipelining.