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