Python Docker MySQL

📌 Project Overview

Hack MAC 2025 is a Capture The Flag (CTF) competition where I contributed as a challenge creator. I designed two web exploitation challenges focusing on real-world vulnerabilities: Business Logic Errors and Blind SQL Injection.

The goal was to create educational yet challenging scenarios that require participants to analyze source code and understand underlying architectural flaws. All challenges were containerized using Docker to ensure isolated and reproducible environments.


🕹️ Challenge 1: business-logic-error

Category: Web
Difficulty: Easy

Scenario

A simple e-commerce page allows users to buy items. The “Flag” item costs 9,999,999 credits, but users start with only 10,000 credits. The server fails to validate whether the purchase quantity is positive.

Vulnerability Analysis

The backend code directly calculates the cost without checking for negative numbers.

# Vulnerable Logic
try:
    qty = int(request.form.get("quantity", "1"))
except ValueError:
    qty = 1

cost = item["price"] * qty
session["balance"] = pre_balance - cost  # Subtracting a negative becomes addition!

Exploitation (Write-up)

Participants can exploit this by sending a negative quantity for a cheap item.

  1. Open the store page.

  2. Inspect the quantity input for ice_cream.

  3. Edit the min value and type -10000).

  4. Click Buy.

  5. Since cost = 1000 * (-10000) = -10,000,000, the server does balance = balance - (-10,000,000) → balance increases by 10,000,000.

  6. Buy Flag: With the inflated balance, the user can legally purchase the Flag.

🕹️ Challenge 2: Find-The-Pass

Category: Web / SQL Injection (Blind)
Difficulty: Hard

Scenario

A login page asks for a username and password. It behaves securely on the surface—no error messages are displayed, and no data is returned other than a generic “Success” or “Fail” page. The goal is to log in as admin, but the password is the Flag.

Vulnerability Analysis

The application uses Raw SQL instead of SQLAlchemy’s ORM features, making it vulnerable to injection.

# app/main.py - Vulnerable Code
query = text(f"SELECT * FROM user WHERE username = '{username}' AND password = '{password}'")
with db.engine.connect() as connection:
    result = connection.execute(query)
    user = result.fetchone()

Exploitation (Write-up)

Since the application swallows errors (Error-based injection doesn’t work) and doesn’t return data (Union-based doesn’t work), participants must use Boolean-based Blind SQL Injection.

  1. Determine Password Length: Inject a condition to check the length.
admin' AND length(password)=16 --

If the page returns “Success”, the length is 16.

  1. Extract Password (The Flag): Iterate through each character using ASCII functions.
admin' AND ascii(s1111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111ubstr(password,1,1)) > 70 --

By analyzing the True/False response, attackers can brute-force the password character by character (e.g., finding ‘H’, ‘M’, ‘2’…).

🛠️ Infrastructure

Each challenge was deployed as a standalone service using Docker Compose to ensure stability during the competition.

# docker-compose.yml (Snippet)
services:
  web:
    build: .
    ports:
      - "5001:5001"
    environment:
      MYSQL_USER: ctf
      MYSQL_PASSWORD: ctfpass
    depends_on:
      db:
        condition: service_healthy

🎯 Learning Outcomes

Through this project, I deepened my understanding of:

Defensive Coding: How strictly validating inputs (e.g., qty > 0) and using Parameterized Queries (Prepared Statements) effectively prevents these attacks.

Containerization: Managing multi-container applications (Flask + MySQL) for CTF deployment.

Updated: