Preventing SQL Injection: How Prepared Statements Work

How SQL Injection Occurs

SQL Injection (SQLi) is one of the oldest and most dangerous web vulnerabilities. It happens when untrusted user input is directly concatenated into database queries, allowing attackers to manipulate query structures.

Case Study: The Leaked Accounts Table

An administrative login form was bypassed by entering admin' OR '1'='1 in the username field. This allowed full access to the control panel and triggered database leakage.

The Bug: Query String Concatenation

The code dynamically built query strings using PHP variable interpolation:

// Vulnerable Code
$user = $_POST['user'];
$pass = $_POST['pass'];
$query = "SELECT * FROM users WHERE username = '$user' AND password = '$pass'";
$db->query($query);

Because the input is not isolated, the SQL engine compiles the attacker’s syntax, changing the query behavior to execute without a valid password check.

The Fix: PDO Prepared Statements

We refactored the login code to use prepared queries. Prepared statements compile the SQL query structure first, then bind user variables separately, preventing injection parameters from altering the SQL logic:

// Secure Code
$stmt = $pdo->prepare('SELECT * FROM users WHERE username = :username AND password = :password');
$stmt->execute([
    'username' => $_POST['user'],
    'password' => password_hash($_POST['pass'], PASSWORD_BCRYPT) // Example hash check
]);
$user = $stmt->fetch();

Even if an attacker inputs SQL syntax, the database engine treats it strictly as a literal string value, rendering the injection harmless.

Scroll to Top