SQL

Time-Tested Ways on How to Prevent SQL Injection Attacks

intro

Injection attacks are always at the top of database threats and it’s safe to say that they will remain at the top of the pile for years to come. Learn how to prevent SQL injection attacks.

Tools used in the tutorial
Tool Description Link
Dbvisualizer DBVISUALIZER
TOP RATED DATABASE MANAGEMENT TOOL AND SQL CLIENT

Injection. Once you hear this word, what associations does it bring? For many, this keyword associates with data breaches, for others — it reminds them of ways to fight against it. So, how to prevent SQL injection attacks?

In this blog, we tell you what injection is, how to protect against it, and what can you do to prevent it from striking in the first place.

What Is SQL Injection?

To find out how to prevent SQL injection, first, we must understand what SQL injection is and what it means.

Injection, in simple terms, stems from the failure of developers to validate user input before passing it on to a database. In other words, if you have write code like this, you have problems:

SQL Injection Example
SQL Injection Example

You have problems not only because your code has errors (you cannot use MySQLi and fetch results with PDO — you have to use one or the other to query the database and return results from it), but also because you pass user input straight into a database.

What Makes SQL Injection so Dangerous?

Passing user input straight into a database is dangerous because by doing so, you open the doors for attackers to submit malformed data. If an attacker submits a query like ";DROP TABLE demo_table;-- the query will then become SELECT * FROM demo_table WHERE details = "";DROP TABLE demo_table;-- and your database will:

  1. Stop executing the query it is supposed to execute (”;)
  2. Drop the table specified in the DROP TABLE statement
  3. Ignore everything succeeding the statement (-- tells your database “treat all other input in this line as a comment and don’t act on it”)

DbVisualizer visualizes the resulting malicious query well:

Understanding a SQL Query with DbVisualizer
Understanding a SQL Query with DbVisualizer

There’s no need even to execute this query — everything’s as clear as water to begin with. One query ends, another drops the table, and the rest of the input is ignored.

Granted, a full understanding of how to prevent SQL injection also necessitates you to understand that SQL injection can be complex and that there are multiple types of SQL injection in the first place: most developers do know that writing code in such a way is a highway to disaster (the SQL injection payloads you will see in the wild will differ, some significantly), but combined sloppiness in your queries, code, and server development do open doors for injection regardless.

SQL Injection Attacks in the Real World

The SQL injection examples you will see in the wild will differ because no one attack is the same. Blind time-based SQL injection attacks will rely on the following factors:

  1. No errors or inadequate errors shown by the server (error_reporting or alternative parameter turned to 0)
  2. Time — an attacker will craft a query that will purposefully wait a couple of seconds to return a result set. If it is returned after a specified time period, the application is vulnerable
  3. A malformed SQL query (a query taking input from the user) — a query should take input from the user in the first place. Without a query doing that, any form of SQL injection is impossible.

Blind time-based attacks will rely on those three because they rely on an application not providing errors and a time-based factor. Other types of SQL injection can wiggle with the steps 1 and 2, however the third step will always be the same. That’s why before understanding how to prevent SQL injection you must first consider the types of SQL injection, too.

There are three — classic (user input passed straight into a database), time-based due to server configuration or other factors (see example above), and out-of-band when the “channels” between which an attacker sends and receives information differ.

How to Prevent SQL Injection?

This piece of code is not vulnerable to SQL injection:

PDO-Based Example of SQL Injection
PDO-Based Example of SQL Injection

This piece of code is not vulnerable to SQLi (short for SQL injection) because we don’t pass user input straight into a database and instead, bind a value separating it from the query. That’s all you need to do — the answer to the question how to prevent SQL injection is “don’t pass user input to the database.”

Avoid passing user input to the database by:

  1. Using data objects (example above — other languages will have similar approaches.)
  2. Binding user input after constructing the query (you can also do that by using data objects.)
  3. Using whitelist-based input validation techniques (create an array of allowed values and block all the rest.) Blacklist-based input validation would be more risky because it’d count on you knowing all of the SQL queries that may be used in malicious ways.
  4. Minimizing the privileges assigned to each account in the database (that ensures that even if user input is passed to a database, the damage will be minimized.)

That’s it, really — not rocket science, is it? You can also use a mixed approach in that you can use data objects, whitelist input validation and minimize privileges, but be advised that each step towards security will likely have a drawback on something else (e.g. users may no longer be able to run queries like “Nissan Selecta” if you’re running a car sales website because it contains the select keyword which your application/input validation functions may interpret as malicious.) Using a firewall also helps — don’t rely on it, but if you can, implement a firewall into your application to block (and, even better, monitor intrusion attempts) so you can sleep soundly at night.

What to Consider When Preventing SQL Injection

Before looking into ways how to prevent SQL injection and looking at the downsides (most security solutions will have a drawback on user experience), consider:

  1. Your application and how it serves your use case — queries run through an application and considering the use case that the application serves is vital to understand how best to protect it. A wooden shield may work when protecting from a blade — a pistol, not so much.
  2. Your database and the types of data it contains — the data stored in your database is not only subject to regulations like GDPR, HIPAA, CCPA and others, but also a target for hackers. If there’s nothing of value for an attacker, why try bypass a firewall? Not the best advice, but I once heard someone recommend weighing the cost/benefit of attacking your application for an attacker, then employing security measures from that perspective. e.g. a firewall might be enough of a deterrent from certain SQL injection scenarios where the cost/risk ratio is too high.
  3. Your SQL queries and the types of data they act on — it’s also vital to consider your queries themselves. TRUNCATE TABLEqueries will take a single argument, while SELECTs can be more exotic. Also consider the user that runs the queries in the database in the first place — if it only has TRUNCATE privileges and it’s the only user in your DB, there’s little use of an attacker exploiting a hole in your code even if it exists.
  4. Your backups — your data can be destroyed and it’s vital to be prepared for such a scenario; your data can be destroyed not only because of SQL injection but because of a variety of other factors and having a couple of (working) backups at hand never hurts.

After these things, also think about your use case from a user perspective once again:

  • Utilizing input validation (no matter if you opt for the white or black card here) will hurt users. The stronger your security measures in this scene are, the more unhappy users will be.
  • Using PDO requires PHP 5.3 or later, other programming languages will have similar requirements — this shouldn’t be a problem for most of you (if you’re running PHP 5 for your application, good God, upgrade), but if you’re running a older version of a programming language for any kind of a reason (I know of developers running outdated software to save on server costs), consider this too.
  • Injection only works if there’s a database to act on. Is a database even necessary? I’ve heard of developers swapping MySQL for text-based storage to operate a pastebin-like website: perhaps you don’t even need a database? If text-based storage is enough, why worry about injection attacks in the first place?
  • Lessened user privileges hurts attackers and users — a user without SELECT privileges may be “worth” less to an attacker, but what if your use case is a forum? How will you display threads, comments to such an user? Don’t overdo things and don’t imagine injection as some kind of a boogeyman — “normal” approaches will do.

Other Things to Consider

Finally, make use of simple things — use arrays for input validation, make use of roles (roles are collections of privileges), and consider using SQL clients for your use case.

SQL clients will not prevent your application from being exploited by SQL injection — they will, however, make you better understand your queries and the components within them.

Good SQL clients will let you take them for a test drive, too — grab a free 21-day trial of DbVisualizer by clicking on this link and explore its internals: with support for 50+ data sources, you will surely find your beloved database in the list.

Lastly, keep a cool head on your shoulders: no need to over-obsess over injection attacks (or any attacks for that matter) — do what you can and delegate some tasks to other applications/people. Chances are that a firewall for $10 a month will do a better job in terms of preventing attacks than one developer familiarizing himself with your code base. Do be wary and vigilant — and remember that simplicity is sometimes the best policy.

Summary

How to prevent SQL injection? That is a question on the top of mind of many developers, engineers, DBAs, and even security experts — the answer is “don’t pass user input to a database.” There are various ways to protect yourself from such attacks (PDO, firewalls, input validation, etc.), however, the best way will always be to avoid introducing such attacks into your database in the first place.

FAQ

How to prevent SQL injection?

Prevent SQL injection by using prepared statements, firewalls, input validation, and other measures that help ensure that user input is not acted on by your database.

Why is SQL injection so important?

Injection is important because injection attacks were, are, and presumably, will remain to be the top attack vector regardless of the application you’re building. Injection attacks are prevalent because they’re easy to come across, easy to exploit, and the rewards for attackers exploiting them are often huge enough to warrant the risk.

What resources do you recommend to brush up on database attacks and other interesting topics?

For those searching for ways to brush up on database internals and ways to improve performance, I’d recommend the book “Hacking MySQL: Breaking, Optimizing, and Securing MySQL for Your Use Case.” The book will not only walk you through the security measures you can implement into your database and application to prevent injection attacks but also tell you what makes your database performance dive and how to optimize it for the future.

Dbvis download link img
About the author
LukasVileikisPhoto
Lukas Vileikis
Lukas Vileikis is an ethical hacker and a frequent conference speaker. He runs one of the biggest & fastest data breach search engines in the world - BreachDirectory.com, frequently speaks at conferences and blogs in multiple places including his blog over at lukasvileikis.com.
The Table Icon
Sign up to receive The Table's roundup
More from the table
Title Author Tags Length Published
title

How Often Should SQL Transaction Logs Be Backed Up?

author Antonello Zanini tags MySQL POSTGRESQL SQL SQL SERVER 7 min 2025-04-28
title

TRUNCATE vs DELETE: SQL Comparison of the Two Statements

author Antonello Zanini tags MySQL ORACLE POSTGRESQL SQL SQL SERVER 9 min 2025-04-23
title

SQL Performance Tuning in Relational Databases: A Walkthrough

author Lukas Vileikis tags SQL 10 min 2025-04-22
title

How to Extract the Year from a Date in SQL

author Antonello Zanini tags MySQL ORACLE POSTGRESQL SQL SQL SERVER 5 min 2025-04-21
title

A Complete Guide to an SQL Recursive Query Expression

author Lukas Vileikis tags MySQL SQL 5 min 2025-04-16
title

A Guide to the SQL Standard Deviation Functions

author Antonello Zanini tags MySQL ORACLE POSTGRESQL SQL SQL SERVER 6 min 2025-04-15
title

SQL EXISTS: Syntax and Use Cases with Examples

author Leslie S. Gyamfi tags MySQL ORACLE POSTGRESQL SQL SQL SERVER 6 min 2025-04-14
title

Welcoming Tables with Foreign Keys Into Your Database

author Lukas Vileikis tags MySQL SQL 5 min 2025-04-10
title

Dealing With NULL in SQL: Complete Guide

author Leslie S. Gyamfi tags SQL 7 min 2025-04-09
title

Data Backup and Recovery: Implement the Golden Rule in Your Database

author Lukas Vileikis tags Backup Recovery SQL 6 min 2025-04-07

The content provided on dbvis.com/thetable, including but not limited to code and examples, is intended for educational and informational purposes only. We do not make any warranties or representations of any kind. Read more here.