Week 10 · worksheet

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.py on :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

NameStudent IDDateGroup

Part 2 — Lecture Questions

  1. Define BOLA (API1:2023). Why is it the #1 API risk, and why can't a WAF reliably stop it?
  2. What is mass assignment / broken object property level authorization (API3:2023)? Contrast a blocklist vs. an allow-list of bindable fields.
  3. API4:2023 is unrestricted resource consumption. Give two distinct impacts (security and availability) of an unthrottled /api/login.
  4. In vulnerable_api.py, current_user() trusts the X-User-Id header. Why is a client-supplied header NOT authentication, and what should replace it?
  5. 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:

  1. curl http://localhost:8080/api/users/3/orders — note you receive the "Server rack" order with no auth.
  2. Iterate the id: curl http://localhost:8080/api/users/2/orders.
  3. 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:

  1. curl -X POST http://localhost:8080/api/users -H "Content-Type: application/json" -d '{"username":"mallory","password":"x","is_admin":true,"balance":1000000}'
  2. Confirm the response echoes "is_admin": true, "balance": 1000000.
  3. Repeat against :8081 and confirm the smuggled fields are forced to is_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:

  1. Run the brute-force loop from attack.md against :8080 (guesses incl. alice123) — all attempts processed.
  2. On :8081 loop 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
  3. 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

  1. Mapping: complete a table — finding | endpoint | OWASP API id | fix applied.
  2. 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.py ownership check have prevented it?
  3. 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)

CriterionWeight
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
Total100

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):
  1. What did you do, and why did the vulnerability work?
  2. 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.

  1. Ask an AI assistant to exploit or fix this week's vulnerability. Paste its full answer.
  2. 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).
  3. 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).