Lion Cipher Lab
Exploit and fix HTTP parameter pollution in your own lab
- AppSec / DevSecOps
- Intermediate
- ~45 min
- Free · no account required
Why it matters
Most web bugs the world worries about — SQL injection, XSS — are about smuggling a payload into a place that executes it. HTTP parameter pollution is sneakier and, once you see it, alarmingly common: it needs no exotic payload at all, just the same ordinary parameter sent twice. It works because the web is a chain of components — a WAF, a load balancer, the application framework, a backend microservice — and nobody ever agreed on what a request with two 'amount' values or two 'role' values means. One component reads the first copy and says 'looks fine'; the next reads the last copy and acts…
What you'll learn
- explaining HTTP parameter pollution (HPP) in plain words: sending the SAME query/body parameter more than once, and exploiting the fact that different components disagree on which copy wins
- knowing how common stacks pick a duplicate: some take the FIRST value, some the LAST, some build an ARRAY, some CONCATENATE with a comma — and that HTTP itself does not define the answer
- seeing the exact Flask behavior that models the bug: request.args.get('x') returns the FIRST value while request.args.getlist('x')[-1] returns the LAST
- building a deliberately-vulnerable app whose security CHECK and business LOGIC read the same parameter through the two different APIs — the 'impedance mismatch' that makes HPP exploitable
- exploiting it: role=user&role=admin passes the check (which reads 'user') but reaches the sink as 'admin', an access-control bypass that a single role=admin is correctly blocked from
- fixing it by canonicalizing parameter handling — rejecting requests that carry duplicate copies of a single-valued parameter, and reading each value ONCE so the check and the action can never disagree
- measuring before and after with curl: the bypass returns the protected data before the fix and a 400 after it
- stating the honest limits: one fixed handler is not a fixed stack (HPP lives in disagreeing parsers across proxy/app/backend), and blanket duplicate-rejection breaks legitimately-repeatable parameters
Steps in this lab
- From zero: what HTTP parameter pollution is
- Set up: a Python virtual environment with Flask
- Build the deliberately-vulnerable app
- Exploit it: measure the BEFORE state with curl
- Fix it: canonicalize parameter handling, then measure the AFTER state
- The honest limits: one handler fixed is not one stack fixed