TL;DR
SQL injection happens when attackers insert malicious code into your database queries through user input fields. To prevent it, always use prepared statements (with parameterised queries) or an Object-Relational Mapper (ORM). Validate and sanitise all user inputs before using them in any database operation.
1. Understand SQL Injection
SQL injection exploits vulnerabilities in how your application handles user input when constructing database queries. Imagine a simple login form:
SELECT * FROM users WHERE username = '$username' AND password = '$password';
If an attacker enters ' OR '1'='1 as the username, the query becomes:
SELECT * FROM users WHERE username = '' OR '1'='1' AND password = '$password';
Because '1'='1' is always true, this bypasses the username check and potentially grants access to all user accounts. This is a simplified example; attacks can be much more complex.
2. Use Prepared Statements (Parameterised Queries)
Prepared statements are the most effective way to prevent SQL injection. They separate the query structure from the data, so the database treats user input as data, not as executable code.
Example (PHP with PDO):
$stmt = $pdo->prepare('SELECT * FROM users WHERE username = ? AND password = ?');
$stmt->execute([$username, $password]);
$user = $stmt->fetch();
Notice the ? placeholders. The database driver handles escaping and quoting the input values correctly when you execute the statement.
Example (Python with SQLite3):
cursor.execute('SELECT * FROM users WHERE username = ? AND password = ?', (username, password))
3. Use an Object-Relational Mapper (ORM)
ORMs provide a higher level of abstraction for database interactions. They automatically handle query construction and escaping, reducing the risk of SQL injection.
Popular ORMs include:
- Django’s ORM (Python)
- Hibernate (Java)
- Entity Framework (C#)
4. Input Validation
While prepared statements are the primary defence, input validation adds an extra layer of security.
- Whitelist Validation: Define allowed characters or patterns for each input field. Reject anything that doesn’t match.
- Data Type Validation: Ensure inputs are of the expected type (e.g., integer, string, email address).
- Length Validation: Limit the maximum length of input fields to prevent excessively long queries.
Example (PHP):
if (!preg_match('/^[a-zA-Z0-9]+$/', $_POST['username'])) {
// Invalid username - reject it.
}
5. Output Encoding
Although not directly preventing injection, encoding output helps mitigate the impact of successful attacks (e.g., Cross-Site Scripting). Encode data before displaying it on a web page.
6. Least Privilege Principle
Grant database users only the necessary permissions to perform their tasks. Avoid using administrative accounts for routine operations. If an attacker gains access, they’ll be limited by the user’s privileges.
7. Regularly Update Software
Keep your database software, web server, and application frameworks up-to-date with the latest security patches. Updates often address known vulnerabilities that attackers can exploit.

