Trust no request
Stage 2 of a hands-on security series. One small Python service on your own machine, ten real web weaknesses, and a check that proves each fix: SQL injection, XSS, CSRF, IDOR, broken access control, SSRF, path traversal, mass assignment and open redirects.
New here? Stage 1, How systems talk, covers DNS, TLS, cookies and sessions. This stage is the application on top.
built from text
SELECT id FROM users WHERE email = 'x' OR '1'='1' -- ' AND password = 'anything'bound parameters
SELECT id FROM users WHERE email = ? AND password = ? -- bound: [email, password]The same input. On the left it is pasted into the query text, so a quote can end the string and the rest becomes query. On the right it is bound as a value, so it only ever matches a row or does not.
Ten cases, one per chapter
Each case is one small service with one deliberate weakness, an attack that runs only on 127.0.0.1, a fix you write, and a check that rejects the lazy non-fix. Grouped from the foundations to what senior engineers still get wrong.
Foundations
Untrusted input becomes code: injection and cross-site scripting.
Access and identity
Who may touch what: object and function access, forged requests, over-posting.
Server-side and redirects
The server acting on a request: its network, its files, and where it sends you.
Numbers from real runs
The four try experiments measure the attacks and the defences on your own machine. These figures come from the runs the workshop was written from.
- 3
- Tokens dumped through the login
- 3 of 3
- Rows a string-built query leaks
- 142,144
- Collisions in 200,000 weak tokens
- 3 of 6
- Internal URLs a blocklist lets through
every user token recovered in 3 requests and 581 bytes (try exfiltrate)
the OR-always-true email returns every user; bound parameters return 0 (try inject)
a predictable scheme repeats; token_urlsafe(24) repeats 0 times (try tokens)
an allowlist lets 0 of 6 through on the same URLs (try ssrf)
You need uv and git
uv installs Python for you, and the lab uses only Python's standard library. Every service binds to 127.0.0.1 and nothing leaves your machine.
git clone https://github.com/jars-demo/web-security-demo.git cd web-security-demo/lab uv sync uv run python -m trust run 1
The series
- Stage 1
How systems talk
Stage 1
- Stage 2
Trust no request
You are here