DDSS: Step-by-Step Explanation
Source: Dev.to
Important safety note – This guide is only for learning on a local machine.
Do not expose the vulnerable code to the internet.
1️⃣ Prerequisites
| What you need | Why it’s needed |
|---|---|
| A computer with Docker installed | Docker runs the app and the database in isolated containers. |
| Python 3.x (if you want to install the Python packages locally) | Required for the Flask code and the pip command. |
| A terminal / command prompt | To run the commands shown in the guide. |
If Docker isn’t installed yet, download it from docker.com and follow the installation instructions for your OS.
Test the installation:
docker --version
You should see something like Docker version 24.0.5, build abcdefg.
2️⃣ Get the project files
- Download the ZIP archive that was sent to you (named
ddss-2025-assignment2-rc-main-2.zip). - Unzip it:
| OS | How to unzip |
|---|---|
| Windows | Right‑click the ZIP → Extract All… |
| macOS | Double‑click the ZIP (it extracts automatically). |
| Linux | Open a terminal and run unzip ddss-2025-assignment2-rc-main-2.zip. |
After extraction you will have a folder (e.g. ddss-2025-assignment2-rc-main-2) containing:
- Python source files (
app.py, etc.) - Docker‑related files (
Dockerfile,docker-compose.yml,docker-compose-python-psql.sh) - Miscellaneous assets (templates, static files, README, …)
3️⃣ Start Docker
- Open Docker Desktop (or run the Docker daemon).
- Verify it’s running – you should see the Docker whale icon in your task‑bar / menu‑bar.
4️⃣ Open a terminal / command prompt
| Platform | How to open |
|---|---|
| Windows | Search for Command Prompt (or PowerShell). |
| macOS | Open Terminal (⌘ Space → “Terminal”). |
| Linux | Open your favourite terminal emulator. |
5️⃣ Navigate to the project folder
cd ~/Downloads # or wherever you saved the ZIP
cd ddss-2025-assignment2-rc-main-2
If you get “No such file or directory”, list the contents (ls on macOS/Linux, dir on Windows) and adjust the folder name accordingly.
6️⃣ Install the required Python packages
pip install flask psycopg2-binary werkzeug bandit
| Package | What it does |
|---|---|
| flask | Minimal web framework for Python. |
| psycopg2‑binary | PostgreSQL driver for Python. |
| werkzeug | Utility library used by Flask. |
| bandit | Static security analyzer (optional but useful). |
If you prefer an isolated environment, create a virtualenv first (python -m venv venv && source venv/bin/activate).
7️⃣ Build & start the Docker containers
The project ships a helper script that runs Docker Compose.
# Make the script executable (only needed the first time)
chmod +x docker-compose-python-psql.sh
# Run it
./docker-compose-python-psql.sh
What happens
- Docker Compose builds two containers:
- Python/Flask app (
web). - PostgreSQL database (
db).
- Python/Flask app (
- Images are pulled from Docker Hub (this may take a few minutes).
- When the script finishes you’ll see a “finished building” or similar message.
8️⃣ (Optional) Open a psql shell inside the DB container
Open a second terminal tab/window and run:
docker exec -it db psql -U ddss-database-assignment-2 -d ddss-database-assignment-2
You’ll land in a PostgreSQL prompt:
ddss-database-assignment-2=#
Use \q to quit.
This is handy for inspecting tables or debugging.
9️⃣ Access the web application
| Action | URL |
|---|---|
| Open the home page | http://localhost:8080 |
| Register a new user | http://localhost:8080/register |
Use any modern browser (Chrome, Firefox, Edge, Safari).
- Register a normal account (pick any username/password).
- You’ll now be able to log in and explore the different parts of the assignment.
🔟 Demonstrate the vulnerabilities
10.1 SQL Injection (vulnerable version)
- Go to the login page (often at
/loginor/part1). - Enter the following values:
| Field | Payload |
|---|---|
| Username | ' OR '1'='1' -- |
| Password | anything (e.g. blah) |
- Click Login.
Result: You should see a message like “VULNERABLE LOGIN SUCCESS”.
Why it works
The app builds a query similar to:
SELECT * FROM users WHERE username = '' OR '1'='1' --' AND password = 'blah';
OR '1'='1'is always true.--comments out the rest of the line, removing the password check.- The query returns a row, so the login succeeds without valid credentials.
10.2 SQL Injection (secure version)
- Use the same payloads on the secure login form (usually at
/secure-loginor a different route). - The app now uses parameterised queries (prepared statements), so the input is treated as data, not code.
Result: You should receive an “Invalid credentials” (or similar) message – the injection fails.
📚 What you’ve learned
| Concept | How it appeared in the guide |
|---|---|
| Docker containers | Isolate the Flask app and PostgreSQL database. |
| Flask | Minimal Python web framework used for the vulnerable app. |
| SQL injection | Demonstrated by injecting ' OR '1'='1' -- into the login form. |
| Parameterised queries | The fix that stops the injection. |
| XSS (cross‑site scripting) | (Not covered in the excerpt, but part of the assignment.) |
| Bandit | Tool to scan the Python code for security issues. |
✅ Next steps
-
Run Bandit on the source code to see what it flags:
bandit -r . -
Fix the XSS vulnerability (look for places where user input is rendered without escaping).
-
Write a short report describing each vulnerability, how you exploited it, and how you mitigated it.
Good luck, and remember: always test security flaws offline and never expose vulnerable code to the public internet!
Login Failure Explanation
Message: LOGIN FAILED.
Why?
The secure version uses prepared statements to prevent SQL injection. Inputs are treated as data, not as executable code.
Step 11 – Test Part 2: Session Authorization & More
1. Not Logged In
- Try accessing /part2.html and /part3.html.
- Expected behavior: you should be redirected to /part1.html (login required).
2. Logged In (Secure Way)
- Log in properly via the secure login form.
- Then access /part2.html and /part3.html – they should load correctly.
Why?
Even if the vulnerable login lets you in, the application uses sessions (e.g., cookies) to track authentication. Protected pages cannot be accessed without a valid session.
XSS (Cross‑Site Scripting) Demonstration
Vulnerable Form
-
In the message form (likely at /part2), submit the following payload:
alert('XSS') -
Reload the page.
Result: An alert popup appears.
Why?
The app stores the raw script in the database and renders it without escaping, so the browser executes it as JavaScript.
Secure Form
- Submit the same payload (
alert('XSS')). - Reload the page.
Result: No popup; the script is displayed as plain text.
Why?
The secure version escapes output (e.g., using Jinja’s auto‑escaping in Flask), converting < to <, making the script harmless.
Messages List
The guide shows example messages. Your own messages may differ, but the behavior (executed vs. escaped) should be the same.
Summary Table for Your Report
Copy the following markdown table into your assignment report:
| Version | Vulnerability | Result |
|---|---|---|
| Vulnerable | Stored XSS | JS executed |
| Secure | Escaped output | Safe display |
You have now demonstrated SQL injection (for login and possibly data access) and XSS, along with their mitigations.
SQL Injection Demonstration (Books Query)
Vulnerable Query
-
In the insecure form (look for “price more than”), enter:
0 OR 1=1 -- -
Submit the form.
Result: All books are listed.
Why?
The injection tricks the SQL engine into ignoring the price condition, returning every row (similar to a login bypass).
Secure Query
- Use the same input (
0 OR 1=1 --). - Expected behavior: no books are returned or the query fails safely.
Why?
Parameterized (prepared) statements prevent the injection from altering the query logic.
Final Tips
- Troubleshooting: If something fails, check the terminal for errors. Restart Docker with
docker-compose downand then rerun the setup script. - Learning Points: This exercise illustrates why input validation, prepared statements, and output escaping are essential in web applications.
- Report Guidance: Capture screenshots of both successful and failed attempts, explain each step as shown above, and include the summary table.
- Clean Up: When you’re finished, stop the Docker containers with
docker-compose downin the project folder.
If any step is unclear, feel free to ask for clarification on that specific part. You’ve got this—CS is all about experimenting! 🚀