LAB-ONLY โ€” Vuln99 has real, working exploits. Run it only on localhost or an isolated lab VM with no route to the internet.
 127.0.0.1:5099 โ€” professional-track

VULN99

The live-fire range built specifically for Glacier's scanner โ€” 24 independently-tunable vulnerabilities, real routes, real SQL errors, the same signatures Glacier's active/scanner.py already looks for.

$ ./setup.sh && open http://127.0.0.1:5099
13 modules 24 vulnerabilities, 3 difficulty tiers each built to be scanned by Glacier by HackOps Academy
00WELCOME

What this course is

Get oriented before you boot a target with real, working exploits.

Vuln99 merges two prior HackOps Academy projects โ€” Glacier's own vulnerable_test_app.py and the fuller VulnMart storefront โ€” into one range: 24 independently-tunable vulnerabilities behind a realistic e-commerce app, purpose-built so its routes, parameter names, and SQL error format match what Glacier's active scanner already looks for. This course and Glacier's are meant to be read together โ€” Glacier teaches the scanner, this one teaches the target and how the two fit.

LOCALHOST / ISOLATED LAB VM ONLY Vuln99 contains real, working SQL injection, OS command injection, XXE, SSRF, SSTI, and insecure deserialization. It binds to 127.0.0.1 by default โ€” keep it that way unless you're on a host with no route to the internet or a shared network.
WHO THIS IS FORSomeone who already has Glacier running and wants a real, safe, self-hosted target to point it at instead of hitting production sites during practice.
01MODULE 01

Installation & setup

One script, one URL, a known state on every boot.

git clone https://github.com/hackops-academy/vuln99.git
cd vuln99
./setup.sh          # macOS/Linux โ€” venv, deps, and run in one step
# .\setup.ps1        Windows PowerShell equivalent

Or by hand:

python3 -m venv venv
source venv/bin/activate   # Windows: venv\Scripts\activate
pip install -r requirements.txt
python run.py

Open http://127.0.0.1:5099. The database is SQLite and reseeds from scratch on every process start โ€” you always boot into a known, clean state.

admin
admin123
john_doe / alice_smith / bob_jones
password123
PRO HABITRun ./setup.sh --test (or .\setup.ps1 -Test) once right after install โ€” the pytest smoke suite boots the app and hits every route at every difficulty tier to catch a broken install before you blame the scanner for a bad target.
02MODULE 02

Anatomy of the range

Know the shape of the target before you start pulling triggers.

Vuln99 is a full storefront โ€” catalog, cart, checkout, reviews, accounts, and an admin panel โ€” not just a page of isolated bugs. 24 vulnerabilities are wired into that realistic flow, each independently switchable between low/medium/hard from Admin โ†’ Difficulty settings (/admin/settings).

Every vulnerable route that has a hardened counterpart ships a /safe-* sibling โ€” /safe-search, /safe-product, /safe-read-file, /safe-ping, /safe-go โ€” the same pattern as Glacier's old test app, useful for confirming a scanner correctly stays quiet on a hardened endpoint instead of just firing on everything.

PRO HABITVisit / first โ€” the catalog page doubles as a QA diagnostics panel listing every route in the app, tagged. It's the fastest way to see the full attack surface before you touch the scanner.
03MODULE 03

Difficulty tiers

The same bug, three ways โ€” pick the lesson you actually want to teach or learn.

TierWhat it means
LOWFully vulnerable, no mitigation โ€” what Glacier's scanner is tuned to detect.
MEDIUMA partial, real-world-common mitigation that's still bypassable (blacklist filtering, naive escaping, rate-limiting mistaken for access control) โ€” practice filter/WAF bypass here.
HARDProperly fixed โ€” parameterized queries, allow-lists, real session checks, CSP-safe encoding.

Bulk "set all to low/medium/hard" buttons live on the same settings screen. Without a valid login, if broken_admin is set to LOW, visit /admin/become-admin-demo to set the forgeable is_admin cookie the low-difficulty check trusts.

PRO HABITStart every practice session at LOW across the board to confirm Glacier finds everything it should, then bump specific vulnerabilities to MEDIUM and re-run to practice bypasses instead of just detection.
04MODULE 04

SQL injection family

Seven distinct SQLi surfaces โ€” from a URL parameter to an HTTP header.

KeyWhereType
login_sqli/loginAuth bypass
search_sqli/search?q=UNION-based
product_sqli/product?id=Error-based
blind_sqli_bool/blind-product?id=Boolean-blind
blind_sqli_time/slow-product?id=Time-blind
recommend_sqlilast_category cookie on /recommendCookie-based
header_sqliUser-Agent/X-Forwarded-For on /categoryHTTP header, sink at /admin/logs
PRO HABITAlways confirm header_sqli manually โ€” set a crafted User-Agent with curl -A, hit /category, then check /admin/logs as admin to see the raw value land in the database.
05MODULE 05

XSS & CSRF

Reflected, stored, and the request-forgery classic โ€” right where a scanner and a human diverge.

KeyWhere
reflected_xss/search?q=
stored_xssProduct reviews (/product, /reviews)
csrf/checkout
PRO HABITCSRF on /checkout is a good one to walk through by hand in Repeater โ€” strip the session cookie, replay the request, and see exactly what protection (or lack of it) is actually in place at each difficulty tier.
06MODULE 06

Access control & logic flaws

The bugs no scanner finds without help โ€” this is where manual testing earns its keep.

KeyWhere
idor_orders/orders, /account?id=
broken_admin/admin, /admin/settings
mass_assignment/account (POST)
price_tamper/cart
THIS IS WHY MODULE 07 OF GLACIER'S COURSE SAYS "MANUALLY VERIFY"None of these four are payload-based โ€” Glacier's automated scanner will not flag them. Walk each one by hand in Repeater: increment an order ID, POST an extra role field, edit a cart's price parameter before checkout.
PRO HABITLog in as two different test accounts in two browser profiles and try to view one account's order from the other's session โ€” IDOR findings are most convincing in a report when you can show exactly whose data leaked to whom.
07MODULE 07

File & command vulnerabilities

Where the scanner's path-traversal and command-injection checks earn their keep.

KeyWhere
path_traversal/read-file
file_upload/account/avatar
command_injection/ping, /ping-slow
08MODULE 08

SSRF, XXE, SSTI & deserialization

The admin-only advanced labs โ€” highest impact, easiest to under-scope.

KeyWhere
ssrf/admin/import-image
xxe/admin/import-orders
ssti/admin/email-preview
insecure_deserialization"Remember me" on /login (pickle)

All four are admin-gated โ€” you'll need a valid admin session (or the /admin/become-admin-demo shortcut from Module 03) to reach them. None of these have automated Glacier checks; they're deliberately manual-only labs.

HANDLE WITH CARE, EVEN IN A LABInsecure deserialization via a pickle-based "Remember me" cookie can mean arbitrary code execution on whatever machine is running Vuln99. Keep this strictly on localhost or an isolated VM โ€” this is exactly the kind of finding that's catastrophic outside a lab.
09MODULE 09

Redirects & misc findings

The smaller findings that round out a full report.

KeyWhere
open_redirect/go
weak_crypto/register (unsalted MD5)
verbose_errors/product, /version
10MODULE 10

Running Glacier against Vuln99

Where the two courses actually meet.

Point Glacier's proxy and active scanner at http://127.0.0.1:5099/ with the injection-family and broken_admin vulnerabilities set to LOW (the default). Route paths, parameter names (username/password, q, id, file, host, url), and the SQL error format (sqlite3.OperationalError) all match what Glacier's check_* functions expect out of the box.

# from Glacier's course, Module 04
POST /api/spider/start
{ "start_url": "http://127.0.0.1:5099/" }

# from Glacier's course, Module 05 โ€” confirm scope is localhost before running this
POST /api/active/scan
{ "url": "http://127.0.0.1:5099/product?id=1", "confirm": true }
PRO HABITLog in first as john_doe and pass the session cookie via Glacier's auth object (cookie mode โ€” see Glacier's Module 06) so the spider and active scanner reach the authenticated routes: /account, /orders, /recommend.
11MODULE 11

The combined methodology

Glacier's methodology, run end-to-end against this specific range.

1 โ€” ./setup.sh, confirm LOW across the board, log the reseed
2 โ€” Walk the storefront manually and authenticated (catalog โ†’ cart โ†’ checkout โ†’ reviews)
3 โ€” Run Glacier's passive scan; expect weak_crypto and verbose_errors hits
4 โ€” Spider from an authenticated deep URL (/account)
5 โ€” Active-scan the SQLi/XSS/traversal/redirect/command-injection surfaces
6 โ€” Manually test IDOR, broken_admin, mass_assignment, price_tamper in Repeater
7 โ€” Manually test the admin-only SSRF/XXE/SSTI/deserialization labs
8 โ€” Cross-check every hit against Module 02โ€“09's table above
9 โ€” Bump found vulnerabilities to MEDIUM and repeat steps 3โ€“7 for bypass practice
WHAT SEPARATES A PROFESSIONAL RUN FROM A DEFAULT RUNSame lesson as Glacier's own Module 11: the automated scan only ever covers a fraction of this catalog. Steps 6 and 7 โ€” the logic flaws and admin-only labs โ€” are where the real skill shows up.
12MODULE 12

Multi-VM labs & next steps

Graduating from localhost without losing the safety rails.

If you're running a real isolated lab (a scanner on one VM, Vuln99 on another, both on a private network with no route to the internet), override the bind address:

VULN99_HOST=0.0.0.0 VULN99_PORT=5099 python run.py

run.py prints a warning banner whenever it's bound to anything other than localhost โ€” treat that banner as a hard stop-and-check, not noise. Every request lands in logs/access.log and every admin action in logs/events.log, both handy for lining up what the app saw against a simultaneous nmap scan or Wireshark capture.

NEVER ON A SHARED OR CORPORATE NETWORKThis app has real, working exploits with no additional sandboxing. Only bind beyond localhost on a host that has no route to the internet or a shared/corporate network.
  1. Run the full Module 11 methodology against Vuln99 at LOW, then again at MEDIUM.
  2. Diff your two Glacier findings exports and see exactly which findings a real-world mitigation would have hidden from an automated scan alone.
  3. Once this feels routine, go back to Glacier's own course Module 11 and run its full methodology against Vuln99 as the final exercise.
NEXTGlacier and Vuln99 are meant to be practiced together on a loop โ€” new Glacier scanner features get their regression check here, and new Vuln99 vulnerabilities are worth throwing at Glacier to see what it misses.