Hey there! This guide is for an assignment (looks like "DDSS 2025 Assignment 2") where you'll set up a simple web app using Docker, Python (with Flask), and PostgreSQL. The goal is to demonstrate common security vulnerabilities like SQL injection and cross-site scripting (XSS), and then show how to fix them.
I'll explain every step in simple terms. We'll go slow, define new words, and I'll tell you why each step matters. You'll need a computer with Docker installed (it's a tool to run apps in "containers" like isolated boxes). If you don't have Docker, download it from the official website (docker.com) and install it.
Important Safety Note: This is for learning only. Don't run vulnerable code on the internet—it's just for your local machine to understand bugs.
Step 1: Download and Unzip the File
- The guide says: "Download the file I sent to you and unzip it."
- What to do: The file is a ZIP archive (like a compressed folder) named "ddss-2025-assignment2-rc-main-2.zip". Just sent on WhatsApp; save it to your Downloads folder.
-
How to unzip:
- On Windows: Right-click the ZIP file > Extract All.
- On Mac: Double-click the ZIP file—it unzips automatically.
- On Linux: Open a terminal and run
unzip ddss-2025-assignment2-rc-main-2.zip.
- Why? This gives you the code files, like Python scripts, a Docker setup file, and the app code.
- Result: You'll have a folder called "ddss-2025-assignment2-rc-main-2" (or similar).
Step 2: Start Docker
- The guide says: "Start docker."
- What to do: Open the Docker app on your computer. It might be called "Docker Desktop." Make sure it's running (look for an icon in your taskbar or menu bar showing a whale).
- Why? Docker will create containers for your database (PostgreSQL) and web app, so everything runs without messing up your computer.
-
Tip: If Docker isn't installed, pause here and install it. Test it by opening a terminal (Command Prompt on Windows, Terminal on Mac/Linux) and typing
docker --version. It should show a version number.
Step 3: Go to Your Terminal or Command Prompt
- The guide says: "Go to your terminal or cmd."
-
What to do:
- Windows: Search for "cmd" or "Command Prompt."
- Mac: Search for "Terminal."
- Linux: It's already there—open Terminal.
- Why? We'll run commands here to set up and run the app.
Step 4: Navigate to the Folder
- The guide says: "cd Downloads" then "cd ddss-2025-assignment2-rc-main-2".
-
What to do:
- Type
cd Downloadsand press Enter. (This "changes directory" to your Downloads folder.) - Then type
cd ddss-2025-assignment2-rc-main-2and press Enter. (Go into the unzipped folder.)
- Type
- Why? Commands need to run from inside the project folder where the files are.
-
Tip: If you get an error like "No such file or directory," double-check the folder name (use
lson Mac/Linux ordiron Windows to list files).
Step 5: Install Python Packages
- The guide says: "pip install flask psycopg2-binary werkzeug bandit".
- What to do: In the terminal, type that exact command and press Enter.
-
What is this?
-
pipis a tool to install Python libraries (like downloading apps for Python). - Flask: A framework to build web apps in Python.
- psycopg2-binary: Helps Python talk to PostgreSQL databases.
- Werkzeug: Helps with web stuff in Flask.
- Bandit: A tool to check code for security issues (optional here, but good practice).
-
- Why? Your app needs these to run.
- Tip: If you don't have Python, install it from python.org (version 3.x). Also, you might need a "virtual environment" for cleanliness, but for now, this is fine.
Step 6: Run the Docker Script
- The guide says: "./docker-compose-python-psql.sh".
-
What to do: In the terminal (still in the project folder), type
./docker-compose-python-psql.shand press Enter. - What is this? This is a shell script (a file with commands) that uses Docker Compose (a Docker tool) to build and start two containers: one for the Python/Flask app and one for the PostgreSQL database.
- Why? It sets up the environment automatically. It might take a few minutes to download and build stuff—be patient!
-
Tip: If it says "permission denied," run
chmod +x docker-compose-python-psql.shfirst to make it executable. Watch for "finished building" message.
Step 7: Connect to the Database
- The guide says: Open another tab on the same command prompt and paste "docker exec -it db psql -U ddss-database-assignment-2 -d ddss-database-assignment-2". Then "enter".
-
What to do:
- Open a new terminal tab (or window).
- Paste that command and press Enter.
-
What is this?
-
docker exec: Runs a command inside a running Docker container. -
-it db: Interactive mode in the "db" container (the database one). -
psql: The PostgreSQL command-line tool to interact with the database. -
-Uand-d: Username and database name.
-
- Why? This lets you access the database shell to run SQL commands if needed (but the guide doesn't specify more here—maybe for debugging).
-
Tip: You'll see a prompt like "ddss-database-assignment-2=#". Type
\qto exit when done. Then switch back to the first terminal tab.
Step 8: Open the App in Your Browser
- The guide says: "Go to your browser and paste http://localhost:8080".
-
What to do: Open Chrome, Firefox, or any browser. Type or paste
http://localhost:8080in the address bar. - Why? This is the web app's home page running on your local machine (port 8080).
- What you'll see: Probably a login page or menu for the assignment parts.
Step 9: Register a User
- The guide says: Open another browser tab and go to "http://localhost:8080/register".
- What to do: Do that—register with a username and password (real ones, not the exploit yet).
- Why? Some parts require being logged in.
Step 10: Test Part 1 - Vulnerable SQL Injection (Login Bypass)
- The guide explains testing SQL injection, a bug where bad input tricks the database.
-
Vulnerable Form:
- Go to the login page (probably at /part1 or similar—check the app).
- Username:
' OR '1'='1' -- - Password: Anything (e.g., "blah").
- Login. It should say "VULNERABLE LOGIN SUCCESS".
-
Why it works: This input injects SQL code. The query becomes something like
SELECT * WHERE username='' OR '1'='1' -- AND password=.... The--comments out the password check, and'1'='1'is always true, so it logs in without a real username/password. Why the explanation about precedence? In SQL, AND is stronger than OR, so without
--, the password part still blocks it.-
Secure Form:
- Try the same username/password.
- It should say "SECURE LOGIN FAILED".
Why? The secure version uses "prepared statements" to prevent injection—inputs are treated as data, not code.
Step 11: Test Part 2 - Session Authorization and More
-
Not Logged In:
- Try accessing /part2.html and /part3.html.
- Should redirect to /part1.html (login required).
-
Logged In (Secure Way):
- Login properly via the secure form.
- Then access /part2.html and /part3.html—should work.
- Why? Even if vulnerable login lets you in, sessions (like cookies tracking login) prevent accessing protected pages without proper auth.
Step 12: Test Stored XSS in Part 2
- XSS is a bug where bad input (like scripts) runs as code in the browser.
-
Vulnerable Form:
- In the message form (probably at /part2), submit:
<script>alert('XSS')</script>. - Reload the page—an alert popup should appear.
- In the message form (probably at /part2), submit:
Why? The app stores the script in the DB and displays it without escaping, so the browser runs it as JavaScript.
-
Secure Form:
- Submit the same:
<script>alert('XSS')</script>. - Reload—no popup. It shows as plain text.
- Submit the same:
Why? The secure version escapes output (e.g., using Jinja templates in Flask) so
<becomes<, making it harmless.Messages List: The guide shows example messages—yours might vary, but test to see the difference.
-
Summary Table for Report:
- Copy this into your assignment report: | Version | Vulnerability | Result | |-----------|---------------|-----------------| | Vulnerable| Stored XSS | JS executed | | Secure | Escaped output| Safe display |
Step 13: Core Work Complete
- You've now shown SQL injection (for login and possibly data access) and XSS, plus fixes.
- This covers "Exercise 1" in the assignment.
Step 14: Test Part 3 - SQL Injection in Queries
-
Vulnerable Query:
- In the insecure form (look for price more than), enter price:
0 OR 1=1 --. - Submit—it should list ALL books.
- In the insecure form (look for price more than), enter price:
Why? Injection tricks the SQL to ignore the price and return everything (similar to login bypass).
-
Secure Query:
- Same input—should list NO books or fail safely.
Why? Parameterized queries prevent the injection.
Final Tips for You
-
Troubleshooting: If something fails, check terminal errors. Restart Docker with
docker-compose downthen rerun the script. - Learning Points: This teaches why input validation, prepared statements, and output escaping are crucial in web apps.
- Report: Take screenshots of successes/failures, explain like I did, and include the table.
-
Clean Up: When done, stop Docker containers with
docker-compose downin the folder.
bandit
Great, this is exactly what Part 2.2 + 2.3 expects.
I’ll guide you step-by-step, in exam/report-ready order, with exact commands, what you should see, and what to write down.
You can literally follow this and tick boxes.
✅ PART 2.2 — Run the Tools
🔹 A. Run Bandit (Static Analysis)
From project root (where app.py exists):
bandit -r app.py
Or entire backend folder:
bandit -r app/
Step 3 — What Bandit should report (EXPECTED)
You should see findings like:
✅ SQL Injection (TRUE POSITIVE)
[B608:hardcoded_sql_expressions] Possible SQL injection vector through string-based query construction.
Triggered by:
query += f" AND price >= {pricemin}"
✔ This is INTENTIONAL (vulnerable route)
✅ Weak Cryptography (if applicable)
[B303:md5] Use of weak cryptographic hash
or
[B324:hashlib] Use of weak SHA256 for password hashing
✔ Counts as TP if you used SHA256 instead of bcrypt/PBKDF2.
Step 4 — Save Evidence
Take:
- Screenshot of Bandit output
- Copy Issue ID, Severity, File, Line number
You will reference this in Part 2.3 table.
zap
## 🔹 B. Run **OWASP ZAP (Dynamic Testing)
**
Step 1 — Download & Start ZAP
Download:
👉 https://www.zaproxy.org/download/
Run ZAP Desktop
Choose:
“No, I do not want to persist this session” (simpler)
Step 2 — Configure Browser Proxy
Proxy settings:
-
Host:
localhost -
Port:
8080
Do this in:
- Firefox → Settings → Network → Proxy
- Chrome → System → Open proxy settings
Step 3 — Verify Proxy Works
Visit:
http://localhost:8080
✔ You should see traffic appearing in ZAP “Sites” tree
❌ If not, proxy is wrong
🔹 C. ZAP Automated Scan (Quick Win)
Step 4 — Quick Start Scan
In ZAP:
- Open Quick Start
- Enter:
http://localhost:8080
- Click Attack
ZAP will:
- Spider your app
- Passive scan
- Active scan (SQLi/XSS)
⏱ Wait 5–10 minutes
Expected ZAP Alerts (IMPORTANT)
You SHOULD see:
✅ SQL Injection (TRUE POSITIVE)
- URL:
/login-vulnerableor/part3_vulnerable - Payload:
' OR 1=1 -- - Evidence: Authentication bypass / all rows returned
✅ XSS (TRUE POSITIVE)
- URL: message submission
- Payload:
<script>alert(1)</script>
- Evidence: Script execution in response
⚠ CSRF (Possible FALSE POSITIVE)
- “Form has no CSRF token”
✔ Allowed as FP depending on assignment scope
Step 5 — Manual Active Scan (Recommended)
- In Sites tree
- Right-click your app
- Select:
Attack → Active Scan
This improves SQLi detection.
🔹 D. Manual Exploration (IMPORTANT)
Step 6 — Manual Attacks (Through Browser)
While proxy is enabled:
SQL Injection Test
0 OR 1=1 --
- Works in vulnerable
- Fails in secure ✔
XSS Test
<script>alert("XSS")</script>
- Executes in vulnerable
- Escaped in secure ✔
ZAP records these.
🔹 E. Manual Undetected Vulnerability (REQUIRED)
Example 1 — Weak Password Hashing
If your app uses:
hashlib.sha256(password)
Explain:
- ZAP ❌ misses it (static issue)
- Bandit ✅ detects it
✔ Counts as Manual / Undetected by ZAP
Example 2 — Hardcoded secret_key
app.secret_key = "secret123"
Explain exploit:
- Predictable secret
- Session cookie forgery possible
✔ Excellent manual vulnerability
✅ PART 2.3 — Classification Table (REPORT)
Use this table exactly (you can paste it):
| Tool | Vulnerability | TP / FP | Reason |
|---|---|---|---|
| ZAP | SQL Injection (login-vuln) | TP | Payload ' OR 1=1 -- bypassed authentication |
| ZAP | Stored XSS (text-vuln) | TP | Script executed on message display |
| Bandit | SQL string concatenation | TP | f-strings used in vulnerable queries |
| ZAP | CSRF (no token) | FP | Forms lack tokens but CSRF not required in assignment |
| Bandit | Weak crypto (SHA256) | TP | Passwords not hashed with adaptive algorithm |
✅ Discussion Points (WRITE THIS)
You can use this verbatim:
OWASP ZAP is effective at identifying runtime vulnerabilities such as SQL injection and XSS, but it may miss implementation-level weaknesses like weak cryptographic choices. Bandit complements ZAP by identifying insecure coding patterns through static analysis but lacks execution context. Some vulnerabilities, such as hardcoded secrets or weak hashing, require manual inspection. The combined use of static and dynamic tools provides significantly better coverage than either tool alone.
🎯 Final Checklist (Tick These)
✔ Bandit run
✔ ZAP automated scan
✔ ZAP active scan
✔ Manual attacks performed
✔ One manual undetected vulnerability
✔ Classification table completed
✔ Discussion written
If anything confuses you, ask for clarification on a specific step! You've got this—CS is all about experimenting. 🚀
Top comments (0)