A practice shop · runs on 127.0.0.1 only
A junk shop that trusts everything it's told.
12 things on the shelf. Search box builds SQL by hand,
the greeter page renders what you type as a template, and
/api/exec?cmd=id does exactly what it looks like.
It's all on purpose — point a scanner at it and take notes.
Sign in as admin / admin123. Docs at /api/docs.
What's wrong with it
Full list →On the shelf
All 12 →A few loose floorboards
Try them in the lab →
These go somewhere real. The search box runs your words as SQL,
/greet?name={{7*7}} answers 49, and
/fetch?url=file:///etc/passwd reads files. Nothing here is faked.
SSRF (fetch any URL)
No allowlist: http(s), file:// and cloud metadata 169.254.169.254.
/fetch?url=http://127.0.0.1:5000/healthSSRF aliases
Same sink under many param names scanners fuzz.
/api/ssrf?url=http://127.0.0.1:5000/healthLFI / RFI
Local file read with ../ allowed; http(s) refs fetched remotely.
/page?page=readme.txtBlind SQLi (time-based)
SLEEP()/BENCHMARK in id stall the response - timing oracle.
/api/blind?id=1HPP + JSONP XSS
Repeated params joined into SQL; callback reflected as JS.
/api/user-jsonp?callback=showUser&id=1SSRF filter bypass
Blocklist rejects literals, then decodes decimal/hex IPs and fetches.
/fetch2?url=http://127.0.0.1:5000/healthBroken auth (enum/2FA/juggle)
User enumeration, guessable 2FA, type-juggling login.
/api/enumerate?username=adminIDOR API keys + mass assignment
Anyone reads anyone's key; profile update sets is_admin.
/api/apikey?user=adminOAuth redirect theft
redirect_uri never validated; code leaks to attacker domain.
/oauth/authorize?client_id=vulnshop&redirect_uri=https://example.comBackup files + console
database.sql, db.sqlite, app.py.bak and a PIN-shown console.
/database.sqladmin / admin123 — same pair you'll find in
/.env. Place an order, open its receipt at
/api/orders/<id>, then change the number.