Spread
Spread turns a messy CSV into a clean, readable table — a one-person side project, built by someone who took a shortcut they were sure no customer would ever find.
The Scenario
Spread was a weekend build that quietly kept going: one developer, one server, a few users who just wanted their spreadsheets to read like less of a wall of commas.
Running everything yourself means nobody reviews your shortcuts. There's a corner of it the maker kept for themselves — a secret only ever meant for their eyes, behind a door they were sure the public side could never open. Prove them wrong.
Lab Intel
Synopsis
A weekend CSV tool whose ops console is blocked at an edge proxy but has no login. The edge trusts Content-Length while the app's HTTP server trusts Transfer-Encoding: chunked — a CL.TE desync smuggles a request to /admin past the proxy.
Architecture
A medium-difficulty two-service lab: a gateway (the edge, Content-Length invariant, enforcing the /admin path ACL) in front of an app service (a chunked-honoring HTTP front + gunicorn/Flask). /admin and /internal are blocked at the gateway but have NO application login — the app trusts the network. The gateway delimits each body by Content-Length and forwards bytes verbatim upstream over a pinned keep-alive connection; the app delimits by Transfer-Encoding: chunked. Send POST /api/v1/profile-upload (the avatar endpoint, where a chunked multipart body is unremarkable) carrying BOTH a Content-Length and Transfer-Encoding: chunked, with a body of a single zero-size chunk followed by a smuggled GET /admin/ request. The gateway forwards the whole Content-Length body; the app ends the body at the zero-chunk and treats the smuggled bytes as the next request. Pipeline a normal follow-up (e.g. GET /) on the same connection — its response is the /admin ops console, which renders the service token (the flag). A direct GET /admin returns the gateway's 403 ('restricted to the internal network'), the tell that a proxy — not the app — guards the path. Because the VPN reaches the gateway directly, the ambiguous request is never normalised by an upstream proxy.
Who It's For
Players ready for their first HTTP request-smuggling desync. You should be comfortable hand-crafting raw HTTP over a single keep-alive connection (Burp Repeater with HTTP/1.1, a socket script, netcat) and reading more than one response off one connection.
Skills You'll Practice
- Distinguishing a proxy-level block from an app-level one
- Recognising a CL.TE setup: front trusts Content-Length, back trusts chunked
- Hand-crafting a chunked body that hides a second request after the zero-chunk
- Pipelining a follow-up request to collect the smuggled response
What You'll Gain
- A working mental model of front-end/back-end request desynchronization
- Why 'block it at the load balancer' is not access control
- The CL.TE payload skeleton, reusable against real smuggling targets