Parameterized Queries

Parameterized Queries

One-liner: A secure coding technique that separates SQL commands from user input, preventing SQL Injection by treating data as data, not executable code.

🎯 What Is It?

Parameterized queries (also called prepared statements) are the primary defense against SQL Injection. Instead of concatenating user input directly into SQL commands, parameterized queries use placeholders (?, @param, :param) that the database engine treats strictly as data values, never as SQL code.

This separation ensures the SQL interpreter cannot be confusedβ€”it knows exactly what is command and what is data.

πŸ€” Why It Matters

Misconceptions About Defenses

❌ Input validation alone β€” Blocklists and allowlists can be bypassed
❌ String escaping β€” Complex, error-prone, and insufficient
❌ WAF only β€” Can be bypassed; doesn't fix the root cause
βœ… Parameterized queries β€” Address the vulnerability at its core

πŸ”¬ How It Works

Vulnerable Code (String Concatenation)

Python Example (Vulnerable)

# ❌ VULNERABLE: User input concatenated directly into query
username = request.form['username']
password = request.form['password']

query = f"SELECT * FROM users WHERE username = '{username}' AND password = '{password}'"
cursor.execute(query)

# Attack: username = "admin'--" bypasses password check!
# Resulting query: SELECT * FROM users WHERE username = 'admin'--' AND password = ''

C# Example (Vulnerable)

// ❌ VULNERABLE: String concatenation
string username = Request.Form["username"];
string password = Request.Form["password"];

string query = "SELECT * FROM Users WHERE Username = '" + username + "' AND Password = '" + password + "'";
SqlCommand command = new SqlCommand(query, connection);
SqlDataReader reader = command.ExecuteReader();

Secure Code (Parameterized Queries)

Python Example (Secure)

# βœ… SECURE: Parameterized query
username = request.form['username']
password = request.form['password']

query = "SELECT * FROM users WHERE username = ? AND password = ?"
cursor.execute(query, (username, password))

# Attack payload: username = "admin'--"
# Database treats entire string as username literal, no SQL injection possible

C# / .NET with MS SQL (Secure)

// βœ… SECURE: Parameterized query
string username = Request.Form["username"];
string password = Request.Form["password"];

string query = "SELECT * FROM Users WHERE Username = @username AND Password = @password";
SqlCommand command = new SqlCommand(query, connection);

// Add parameters - user input never touches the query string
command.Parameters.AddWithValue("@username", username);
command.Parameters.AddWithValue("@password", password);

SqlDataReader reader = command.ExecuteReader();

PHP with PDO (Secure)

// βœ… SECURE: Prepared statement with PDO
$username = $_POST['username'];
$password = $_POST['password'];

$stmt = $pdo->prepare("SELECT * FROM users WHERE username = :username AND password = :password");
$stmt->bindParam(':username', $username);
$stmt->bindParam(':password', $password);
$stmt->execute();

$user = $stmt->fetch();

Java with JDBC (Secure)

// βœ… SECURE: PreparedStatement
String username = request.getParameter("username");
String password = request.getParameter("password");

String query = "SELECT * FROM users WHERE username = ? AND password = ?";
PreparedStatement stmt = connection.prepareStatement(query);

stmt.setString(1, username);
stmt.setString(2, password);

ResultSet rs = stmt.executeQuery();

πŸ“Š Parameterization by Language/Framework

Language/Framework Placeholder Syntax Function/Class
Python (sqlite3) ? cursor.execute(query, params)
Python (psycopg2) %s cursor.execute(query, params)
C# / .NET @param SqlCommand.Parameters.Add()
PHP (PDO) :param or ? $pdo->prepare()
Java (JDBC) ? PreparedStatement
Node.js (mysql2) ? connection.execute(query, params)
Ruby (ActiveRecord) ? or named Model.where("id = ?", id)

πŸ›‘οΈ Detection & Prevention

How to Detect (Code Review)

How to Detect (Dynamic Testing)

How to Prevent

🎀 Interview Angles

Common Questions

STAR Story

Situation: During a penetration test, discovered SQL Injection in a login form that bypassed authentication using admin'--.
Task: Demonstrate the vulnerability and provide actionable remediation guidance.
Action: Showed the bypass in the pentest report with HTTP request/response evidence. Provided a code example converting the vulnerable Python code from string concatenation to parameterized queries using cursor.execute(query, (username, password)). Explained that input validation is defense-in-depth but parameterization is the root fix.
Result: Development team implemented parameterized queries across all database interactions. Follow-up testing found zero SQL injection vulnerabilities. Code examples were added to their secure coding standards.

βœ… Best Practices

❌ Common Misconceptions

πŸ“š References