sqliparameterized-queriesdatabasepython DOCKER KIT

The SQLi Killer: Parameterized Queries

The fix isn't filtering. It isn't escaping. Here's why parameterized queries actually stop SQL injection.

You built a login form. An attacker types this into the username field:

' OR '1'='1

Your query becomes:

SELECT * FROM users WHERE username = '' OR '1'='1' AND password = '...'

'1'='1' is always true. They’re in. No password needed.

The fix isn’t filtering. It isn’t escaping. It’s parameterized queries — and here’s why they actually work:

# Vulnerable — you're building SQL as a string
cursor.execute(f"SELECT * FROM users WHERE username = '{username}'")

# Safe — query structure is sent first, data arrives separately
cursor.execute("SELECT * FROM users WHERE username = %s", (username,))

In the safe version, the database receives the query template, compiles it, then receives the data as a bound value. The parser already finished its job before your input arrived. ' OR '1'='1 is just a string — the database never considers it as instructions.

The attack has nowhere to land.

One gotcha to know about: parameterized queries protect the point of execution. If you store malicious input safely, then later build a different query by concatenating that stored value — you’re vulnerable again. That’s called second-order injection, and it catches teams who think they’re fully covered.

DOCKER KIT — vulnerable and safe endpoints side by side. Run the attack on both:

docker run --rm -p 8080:8080 ayfr/lab-sqli-params