SQL injection occurs when an application constructs database queries by concatenating user input directly into SQL commands without proper sanitization or…
SQL injection occurs when an application constructs database queries by concatenating user input directly into SQL commands without proper sanitization or parameterization. An attacker can inject malicious SQL syntax to alter the query's logic, bypass authentication, extract unauthorized data, or modify/delete records. This is one of the most common and dangerous web application vulnerabilities.
02How It Happens
When an application builds SQL queries by string concatenation or simple string replacement, it treats user-supplied data as executable SQL code rather than as data. If the input contains SQL metacharacters (like single quotes, semicolons, or SQL keywords), the attacker can "break out" of the intended query structure and append or modify SQL commands. The vulnerability exists because the application does not distinguish between the query's static structure (written by the developer) and the dynamic data (supplied by the user). Even simple escaping functions are often insufficient, as they can be bypassed with encoding tricks or database-specific syntax variations.
03Real-World Impact
SQL injection can lead to complete compromise of a database. An attacker may extract sensitive data (usernames, passwords, personal information, financial records), bypass login mechanisms by manipulating WHERE clauses, modify or delete records, or in some database configurations, execute operating system commands on the server. The impact ranges from data theft and privacy violations to business disruption and regulatory fines.
04Vulnerable & Fixed Patterns
Vulnerable pattern
import sqlite3
def get_user(username):
conn = sqlite3.connect('app.db')
cursor = conn.cursor()
# Directly concatenating user input into the query
query = "SELECT * FROM users WHERE username = '" + username + "'"
cursor.execute(query)
return cursor.fetchone()
# An attacker could pass: admin' OR '1'='1
# This would return all users instead of a specific one
Why it's vulnerable: The username parameter is concatenated directly into the SQL string. An attacker can inject SQL syntax (e.g., ' OR '1'='1) to alter the query's logic and bypass intended restrictions.
Fixed pattern
import sqlite3
def get_user(username):
conn = sqlite3.connect('app.db')
cursor = conn.cursor()
# Use parameterized query with placeholder
query = "SELECT * FROM users WHERE username = ?"
cursor.execute(query, (username,))
return cursor.fetchone()
Vulnerable pattern
<?php
$username = $_GET['username'];
$mysqli = new mysqli('localhost', 'user', 'password', 'database');
// Directly interpolating user input into the query
$query = "SELECT * FROM users WHERE username = '" . $username . "'";
$result = $mysqli->query($query);
$user = $result->fetch_assoc();
?>
Why it's vulnerable: The $_GET['username'] variable is directly embedded in the SQL string. An attacker can inject SQL metacharacters to manipulate the query structure.
Fixed pattern
<?php
$username = $_GET['username'];
$mysqli = new mysqli('localhost', 'user', 'password', 'database');
// Use prepared statement with bound parameters
$stmt = $mysqli->prepare("SELECT * FROM users WHERE username = ?");
$stmt->bind_param("s", $username);
$stmt->execute();
$result = $stmt->get_result();
$user = $result->fetch_assoc();
?>
05Prevention Checklist
Use parameterized queries (prepared statements) for all database interactions; never concatenate or interpolate user input into SQL strings.
Apply input validation to reject unexpected data types, lengths, or formats before they reach the database layer.
Apply the principle of least privilege to database accounts; use separate credentials with minimal permissions for different application functions.
Use an ORM or query builder that abstracts SQL construction and enforces parameterization by default.
Enable SQL error suppression in production; do not display raw database error messages to users, as they can reveal schema information.
Conduct code review and security testing specifically for SQL injection; use static analysis tools and penetration testing to identify vulnerable patterns.
06Signs You May Already Be Affected
Check your application logs for unusual SQL syntax in query strings, unexpected database errors, or repeated failed login attempts with suspicious characters (quotes, semicolons, SQL keywords). Review database access logs for queries that retrieve or modify unexpected volumes of data, or for administrative operations from non-administrative user accounts. Unexpected new user accounts or privilege escalations in your database may also indicate a successful injection attack.