Share
## https://sploitus.com/exploit?id=E85076D0-53F3-526A-AA46-1BE5D805E52D
# Flask Web Application Security Audit

A hands-on penetration test of a deliberately vulnerable Flask application:
find the flaws, prove them with real tooling, and ship the fix for each one.

Course: **OCY1102 β€” Cybersecurity in Development**, IngenierΓ­a en Conectividad
y Redes, Duoc UC. Author: **Hugo Herrera**.

> **Ethics.** The target is a lab application I wrote for this purpose and run on
> `127.0.0.1`. Everything here was executed against my own machine. Do not point
> these techniques at systems you don't own or aren't authorized to test.

---

## What this shows

Not a checklist of theory β€” a full loop on each finding:

1. **Locate** the flaw in the source (`app/vulnerable_app.py`, `app/create_db.py`).
2. **Prove** it: an automated scan with OWASP ZAP plus a manual exploit.
3. **Fix** it, with the corrected code in `fixes/` and the reasoning written down.

The scan under `evidence/owasp-zap-scan.csv` is the real export: **999 requests**,
of which **359** carry command-injection payloads (`;sleep 15.0;`, `||sleep 15.0`,
`&sleep$u+15.0&`). The `sleep` is the tell β€” a response that takes 15 seconds
longer proves the input reached a shell.

---

## Findings

| # | Vulnerability | Where | Severity |
|---|---|---|---|
| 1 | **OS Command Injection** | `/ping` builds `ping -c 1 {ip}` and runs it through the shell | Critical |
| 2 | **Reflected XSS** | `/saludo` interpolates `?nombre=` into HTML via `render_template_string` | High |
| 3 | **Missing CSRF protection** | `/submit_comment` accepts POSTs with no anti-CSRF token | High |
| 4 | **Insecure password storage** | `create_db.py` uses unsalted `sha256` | High |
| 5 | **Debug mode / RCE** | `app.run(debug=True)` exposes the Werkzeug console | Critical |

### 1 β€” OS Command Injection (`/ping`)

```python
comando = f"ping -c 1 {ip}"          # ip comes straight from the form
resultado = os.popen(comando).read()  # handed to the shell
```

Input `8.8.8.8; cat /etc/passwd` runs both commands. In the ZAP capture this
shows up as hundreds of `sleep`-based time payloads β€” the server stalls exactly
when the injected command executes.

**Fix** (`fixes/secure_app.py`): validate the input as a real IP with
`ipaddress.ip_address()`, then run `subprocess.run([...], shell=False)` as an
argument list so nothing is ever shell-interpreted. Defence in depth β€” either
layer alone stops it.

### 2 β€” Reflected XSS (`/saludo`)

```python
template = f"Bienvenido, {nombre}!"
return render_template_string(template)   # nombre is attacker-controlled
```

`?nombre=alert(document.cookie)` executes in the victim's
browser. **Fix:** render through a real Jinja template, which auto-escapes β€” the
tags come back as visible text, not code.

### 3 β€” Missing CSRF token (`/submit_comment`)

`exploits/csrf_poc.html` is a standalone page that POSTs a comment to the app.
Loaded while the victim is logged in, it forges the request under their session.
**Fix:** `Flask-WTF`'s `CSRFProtect` requires a per-session token on every POST.

### 4 β€” Unsalted SHA-256 passwords (`create_db.py`)

```python
hashlib.sha256(password.encode()).hexdigest()
```

Fast to brute-force, and with no salt two identical passwords hash identically β€”
so rainbow tables apply and one crack breaks every reuse. **Fix**
(`fixes/create_db_secure.py`): `werkzeug.security.generate_password_hash`
(PBKDF2 + random per-hash salt). Same password, different hash every time.

### 5 β€” Debug mode enabled

`app.run(debug=True)` serves the interactive Werkzeug debugger. Anyone who can
reach it and trigger an exception gets a Python console on the server β€” remote
code execution. **Fix:** debug stays off, and the app binds to `127.0.0.1`
instead of `0.0.0.0`.

---

## Layout

```
app/       vulnerable_app.py, create_db.py   β€” the target, as audited
exploits/  csrf_poc.html                     β€” manual proof-of-concept
evidence/  owasp-zap-scan.csv                β€” 999-request ZAP export
fixes/     secure_app.py, create_db_secure.py β€” remediated code, per finding
```

## Tools

OWASP ZAP Β· Burp Suite Β· manual testing Β· Python Β· Flask Β· SQLite

## Reproduce

```bash
# Vulnerable target (lab only, localhost)
cd app && python create_db.py && python vulnerable_app.py

# Hardened version
cd fixes && pip install flask flask-wtf werkzeug && python secure_app.py
```