Week 4 · worksheet

Worksheet 4 — Injection & Input Handling (3 hrs)

← all weeks · readme · slides

Worksheet 4 — Injection & Input Handling (3 hrs)

Course: Software Security (KOSEN69) · Week 4 Aligned: OWASP 2025 A05 Injection · CWE-89 (SQLi), CWE-78 (OS command injection), CWE-434 (unrestricted upload) Signature game: 🐉 SQLi Boss Fight — each successful injection lands a "hit" on the boss; the boss falls when you dump every credential and land an RCE.

⚠️ Ethics note: All payloads here are for the provided sandbox (vulnerable_app.py) and your own DVWA/Juice Shop containers only. Never test systems you do not own or have written permission to test. Unauthorized injection is a crime under most computer-misuse laws.

Part 1 — Student Information

NameStudent IDDateGroup

Part 2 — Lecture Questions

Answer in 2–4 sentences each.

  1. Why does a parameterized query (execute(sql, (params,))) defeat SQL injection, while string formatting ("... '%s'" % user) does not? Reference how the database treats data vs. code.
  2. In the /ping endpoint, subprocess.run("ping -c 1 " + host, shell=True) is vulnerable. Explain how shell=True turns user input into CWE-78, and how an argument array (["ping","-c","1",host]) removes the shell.
  3. Distinguish input validation (allow-list) from output handling. Why is validation alone insufficient defense for SQLi?
  4. The /upload route saves any filename to disk (CWE-434). What two properties must a directory and a filename have for an upload to become remote code execution, and which does solution_app.py remove?
  5. What is a UNION-based SQLi, and why must the injected SELECT return the same number of columns as the original query? Relate to /search?q=' UNION SELECT username,password FROM users--.

Part 3 — Hands-on Lab (150 min)

Learning goals: extract data via SQLi, achieve OS command injection, exploit an unrestricted upload, then prove each fix in solution_app.py blocks the payload.

Prerequisites: Docker + Docker Compose, curl, a browser. Working dir: labs/week04-injection/.

Environment setup

cd labs/week04-injection
docker compose up            # builds python:3.12-slim, installs flask, runs vulnerable_app.py
# vulnerable app -> http://localhost:8080   (service name: injection-lab, port 8080)

Optional secondary targets:

docker run --rm -it -p 80:80 vulnerables/web-dvwa        # DVWA  -> http://localhost
docker run --rm -p 3000:3000 bkimminich/juice-shop       # Juice Shop -> http://localhost:3000

What to submit per task: the exact payload/command, a screenshot of the response proving success, and a 2–3 sentence mitigation in your own words.


Task 0 — Onboarding (5 min). Browse to http://localhost:8080/login?user=alice&pw=alicepw and confirm Welcome alice. Note the seeded users (alice, bob). Screenshot the working app. Deliverable: screenshot.

Before you start — see why concatenation is the flaw 🔬 Type any input and watch which characters the database will parse as SQL rather than as a name. The point is not the payload; it is that with concatenation the input becomes syntax, and with a parameterised query it structurally cannot. You will be asked to state that difference in your own words in Task 5.

How concatenation changes the SQL parse tree (Week 4) — open full size

Task 1 — Auth bypass via SQLi (25 min) 🐉 Hit #1.

  • Goal: log in as alice with no valid password.
  • Steps: hit /login?user=alice'--&pw=x, then /login?user=x' OR '1'='1'--&pw=x (the trailing -- is required: without it, SQL binds AND tighter than OR, so ... OR '1'='1' AND password='x' matches no row). Observe the comment in the query at lines 61–63 of vulnerable_app.py.
  • Deliverable: both URLs + screenshot of Welcome alice + explain why -- and OR '1'='1 work.

Task 2 — Credential dump via UNION SQLi (30 min) 🐉 Hit #2.

  • Goal: exfiltrate every username and password from the users table.
  • Steps: request /search?q=' UNION SELECT username,password FROM users--. Confirm alice:alicepw and bob:bobpw appear.
  • Deliverable: payload + screenshot of dumped credentials + note on why column count must match.

Task 3 — OS command injection (30 min) 🐉 Hit #3.

  • Goal: run an arbitrary command through /ping.
  • Steps: request /ping?host=127.0.0.1;id then /ping?host=$(whoami) (URL-encode if needed). Capture the injected command's output.
  • Deliverable: both payloads + screenshot of id/whoami output + explanation of the shell=True flaw (CWE-78).

Task 4 — Unrestricted upload (25 min) 🐉 Hit #4.

  • Goal: show the upload accepts a dangerous file type with no checks (CWE-434).
  • Steps: GET /upload (form), then upload a file named shell.py. Confirm saved to /tmp/uploads/shell.py. Discuss: if UPLOAD_DIR were web-served or executed, this is the RCE chain (here the dir is not served, so document the missing control rather than claiming auto-RCE).
  • Deliverable: upload command/screenshot + 2–3 sentences on why extension allow-listing matters.

Task 5 — Defend / fix it (35 min) 🛡️ Boss defeated.

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

Re-fire each payload from Tasks 1–4. Expected: Login failed, no credential dump, invalid host (400) on 127.0.0.1;id, and file type not allowed for shell.py.

  • Deliverable: screenshots of all four failures + name the fix line for each (parameterized query L52–55 login / L62–66 search, shell=False+regex L74–77, secure_filename+allow-list L86–93).

Part 4 — Reflection

  1. CWE/OWASP mapping: map each of your four exploits to its CWE (89/78/434) and to OWASP 2025 A05 Injection.
  2. Real breach: the 2017 Equifax breach exposed ~147M people after attackers exploited a known input-handling flaw (Apache Struts CVE-2017-5638). In 3–4 sentences, connect that failure to the lessons in this lab (untrusted input reaching a powerful interpreter; the cost of an unpatched/unvalidated input path).
  3. Best mitigation: of parameterized queries, allow-list validation, least privilege, and avoiding shell=True, which single control would have prevented the most damage in this lab, and why?

Grading rubric (100)

CriterionPoints
Part 2 — Lecture questions (conceptual accuracy)20
Part 3 — Exploitation + evidence (payloads + 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).