In the world of web security, no vulnerability has been as old, widespread, and destructive as SQL Injection (SQLi). Consistently ranking at the top of the OWASP Top 10 for years, this flaw allows malicious actors to gain unauthorized access to your database, steal data, or delete it entirely.
But what exactly is this attack, and how do we solve this problem at its root by writing secure code that aligns with the CodeBlanks philosophy?
What is SQL Injection (SQLi)?
SQL Injection is a logic flaw that occurs when an application takes user input and includes it directly in a database query (SQL) without filtering or sanitizing it. An attacker manipulates the original background query by typing malicious SQL commands into input fields (such as a search box or login form).
How Does an Attack Happen?
Let's consider a classic and insecure PHP login query:
$username = $_POST['username'];
$password = $_POST['password'];
// ❌ BAD AND DANGEROUS PRACTICE
$query = "SELECT * FROM users WHERE username = '$username' AND password = '$password'";
Normally, a user types their name and password here. But if an attacker enters the following text into the username field:
' OR '1'='1' --
The SQL query running in the background suddenly turns into this:
SELECT * FROM users WHERE username = '' OR '1'='1' -- ' AND password = ''
Because '1'='1' is always TRUE, the WHERE condition matches every row, and the -- sequence turns the rest of the query, including the password check, into a comment. The query returns the first user in the table, which is often the administrator, and the attacker logs in without a password.
The Devastating Consequences of SQL Injection
- Data Breach: User passwords, credit card details, or personal data can be stolen.
- Data Loss: The attacker can delete the entire database using the
DROP TABLEcommand. - Server Takeover: With advanced SQLi attacks, commands can be executed at the operating system level.
How to Prevent SQL Injection?
The only absolute way to protect against this vulnerability is to never concatenate user input directly with the query string. For this, Prepared Statements are used.
Modern frameworks like CodeIgniter 4 provide this security automatically through their Query Builder:
// ✅ SECURE USAGE WITH CODEIGNITER 4
$userModel = new \App\Models\UserModel();
$user = $userModel->where('username', $username)->first();
// Passwords are stored as hashes (password_hash) and checked in PHP, never in SQL
if ($user === null || ! password_verify($password, $user->password_hash)) {
return redirect()->back()->with('error', 'Invalid username or password.');
}
If you are using raw PHP (PDO):
// ✅ SECURE USAGE WITH PDO (Prepared Statements)
$stmt = $pdo->prepare('SELECT id, username, password_hash FROM users WHERE username = :user');
$stmt->execute(['user' => $username]);
$user = $stmt->fetch();
Extra Layers of Defense
- Validate input: check type, length and format (for example, an ID must be an integer) before it reaches the query.
- Allow-list dynamic parts: table names, column names and
ORDER BYdirections cannot be bound as parameters, so only accept values from a fixed list. - Use least privilege: the database user of your web application should not have permissions such as
DROPor access to other databases. - Hide database errors: never show raw SQL errors to visitors; they help attackers map your schema.
- Hash passwords: store passwords with
password_hash()so that even a successful attack does not expose them in plain text.
Conclusion
SQL Injection is a vulnerability that feeds on developer carelessness. By abandoning traditional string concatenation methods and utilizing ORM or Query Builder structures offered by modern frameworks, you can make your applications bulletproof. Remember, secure code is the foundation of quality code.
No comments yet. Be the first to comment!