Worksheet 10 — API Security (3 hrs)
← all weeks · readme · attack · slides
Worksheet 10 — API Security (3 hrs)
Course: Software Security (KOSEN69) · Week 10 Aligned: OWASP API Security Top 10:2023 — API1 BOLA · API3 Broken Object Property Level Auth (Mass Assignment) · API4 Unrestricted Resource Consumption Signature game: 🥷 crAPI Raid Ethics note: Run exploits only against the lab targets shipped here (
vulnerable_api.pyon:8080) or your own OWASP crAPI instance. Never test BOLA, mass assignment, or brute-force against systems you do not own or are not explicitly authorized to test.
Part 1 — Student Information
| Name | Student ID | Date | Group |
|---|---|---|---|
Part 2 — Lecture Questions
- Define BOLA (API1:2023). Why is it the #1 API risk, and why can't a WAF reliably stop it?
- What is mass assignment / broken object property level authorization (API3:2023)? Contrast a blocklist vs. an allow-list of bindable fields.
- API4:2023 is unrestricted resource consumption. Give two distinct impacts (security and availability) of an unthrottled
/api/login. - In
vulnerable_api.py,current_user()trusts theX-User-Idheader. Why is a client-supplied header NOT authentication, and what should replace it? - Why does object-level authorization have to be checked per request, per object rather than once at login?
Part 3 — Hands-on Lab (145 min)
Learning goals: Exploit BOLA, mass assignment, and a missing rate limit against a live API; then read the secure version and explain each fix.
Prerequisites: Docker + Docker Compose, curl. (Optional bonus: cloned OWASP crAPI.)
Environment setup
cd labs/week10-api-security
docker compose up # INSECURE API on :8080, SECURE API on :8081
# Seeded users: alice(id 1) bob(id 2) carol(id 3, admin, balance 9999)
What to submit per task: the exact command(s) + raw response/HTTP status, a screenshot, and a 2–3 sentence mitigation note mapping the bug to its OWASP API id.
Task 0 — Onboarding (15 min)
Confirm both APIs respond: curl http://localhost:8080/ and curl http://localhost:8081/. Note which port is insecure. Record the three seeded users. Deliverable: both root responses + the user table.
Task 1 — BOLA: read another user's orders (35 min)
Goal: Read carol's (admin) orders without being carol — API1:2023. Steps:
curl http://localhost:8080/api/users/3/orders— note you receive the "Server rack" order with no auth.- Iterate the id:
curl http://localhost:8080/api/users/2/orders. - On the secure API observe the ladder:
curl -i http://localhost:8081/api/users/3/orders(401),curl -i -H "X-User-Id: 1" http://localhost:8081/api/users/3/orders(403),curl -i -H "X-User-Id: 1" http://localhost:8081/api/users/1/orders(200).
Deliverable: the leaked order JSON + the 401/403/200 transcript + mitigation note.
Task 2 — Mass assignment: self-promote to admin (30 min)
Goal: Smuggle is_admin + balance into user creation — API3:2023. Steps:
curl -X POST http://localhost:8080/api/users -H "Content-Type: application/json" -d '{"username":"mallory","password":"x","is_admin":true,"balance":1000000}'- Confirm the response echoes
"is_admin": true, "balance": 1000000. - Repeat against
:8081and confirm the smuggled fields are forced tois_admin:false, balance:0.
Deliverable: both responses side by side + mitigation note (allow-list in solution_api.py).
Task 3 — Unrestricted resource consumption: brute-force login (25 min)
Goal: Show /api/login has no throttle — API4:2023. Steps:
- Run the brute-force loop from
attack.mdagainst:8080(guesses incl.alice123) — all attempts processed. - On
:8081loop 7 times:for i in $(seq 1 7); do curl -s -o /dev/null -w "%{http_code}\n" -X POST http://localhost:8081/api/login -H "Content-Type: application/json" -d '{"username":"alice","password":"wrong"}'; done - Confirm the 6th/7th attempt returns
429.
Deliverable: the 401 401 401 401 401 429 429 sequence + mitigation note.
Task 4 — Bonus: crAPI Raid (optional, 20 min)
Against your own OWASP crAPI instance (git clone https://github.com/OWASP/crAPI.git), capture one BOLA or mass-assignment flag. Deliverable: flag + endpoint + which API Top 10 id it maps to.
Task 5 — Defend / fix it (20 min)
Goal: Explain the fixes using the secure reference solution_api.py. Steps: Read the three # --- FIX ... blocks. For each, quote the line(s) that defeat your Task 1–3 exploit: the per-object ownership check (caller["id"] != uid and not caller["is_admin"]), ALLOWED_CREATE_FIELDS binding, and the RATE_LIMIT=5 / RATE_WINDOW=60 limiter. Deliverable: for each of API1/API3/API4 — the exploit that worked on :8080, the line in solution_api.py that blocks it, and the new HTTP status on :8081.
Part 4 — Reflection
- Mapping: complete a table — finding | endpoint | OWASP API id | fix applied.
- Real breach: research an API authorization breach (e.g., the Optus or T-Mobile BOLA/IDOR incidents). Which API Top 10 id matches, and would the
solution_api.pyownership check have prevented it? - Best mitigation: of object-level auth, allow-list binding, and rate limiting — which gives the most risk reduction for an API platform, and why?
Grading rubric (100)
| Criterion | Weight |
|---|---|
| Lecture questions (Part 2) | 20 |
| Exploitation + evidence (Tasks 1–4: commands, output, screenshots) | 40 |
Defense (Task 5: fixes mapped to solution_api.py) | 25 |
| Reflection (Part 4: mapping, breach, best mitigation) | 15 |
| Total | 100 |
Evidence & Integrity (required)
- Identity proof: every screenshot/diagram must show your **
whoami/ login email / student ID and a timestamp**. Generic or borrowed evidence is not accepted. - Personalized flag (if this lab issues one): ____________________
Flags are unique per student — submitting another student's flag is a violation. See SUBMISSION.md.
- Explain in your own words (graded on your reasoning, not copied text):
- What did you do, and why did the vulnerability work?
- Why does your fix actually stop it — and what could still break it?
🤖 Audit the AI (required)
AI is a power tool you must distrust — you are graded on your critique, not the AI's answer.
- Ask an AI assistant to exploit or fix this week's vulnerability. Paste its full answer.
- Find what's wrong or risky in it — insecure code, a subtly incomplete fix, a hallucinated API/function/CVE, a missed edge case, or wrong reasoning. Quote the exact line(s).
- Produce the correct, verified version yourself and explain in 2–3 sentences why the AI's output was insufficient.
Disclose your AI use in the Part 1 table. This task counts toward your Defense + Reflection score.
🧠 Comprehension & Prompt (required)
A. Explain in Plain English (EiPE). In 2–3 sentences, in your own words, describe what this week's vulnerable code/endpoint actually does and why it is exploitable — explain the mechanism, don't dump jargon.
B. Prompt Problem. Write a single prompt that makes an AI produce a correct, secure fix for one finding. Run it: does the exploit now fail? If not, refine the prompt and try again. Submit the final prompt + the verified result. Graded on the prompt's precision and your verification — this trains problem decomposition and AI literacy (Denny et al. 2024).