A SQL injection attack is the insertion (injection) of a malicious SQL query via the input data from a client to an application.
As a result, an attacker can execute any SQL query on the client's database with the access rights that are granted to the application. It means that the attacker can read, update, or delete sensitive data, or even administrate operations on the server side.
There are several main types of the SQL injections:
Blind Boolean Based: injection of a malicious SQL query to the database which asks the database TRUE or FALSE questions and determines the answer based on the application response.
Blind Time Based: injection of a malicious SQL query which uses intentional database pausing to obtain sensitive information for further attack.
Union Based: injection of the UNION SQL operator which combines the results of two or more SELECT statements into a single result and returns it as part of the response.
Database Error in Response: injection which uses error messages thrown by the database server to obtain sensitive information about the structure of the database.
This vulnerability allows an attacker to:
Modify application data
Bypass protection mechanism
Read application data
Example of the Union Based injection
The unprotected application executes the following query containing the user input Laptops:
SELECT name, price FROM products WHERE category = 'Laptops'
Instead of Laptops, an attacker can submit the input like ' UNION SELECT login, password FROM users--.
As a result, the application will return all usernames and passwords along with the names and descriptions of the products. The following SQL will be executed:
SELECT name, price FROM products WHERE category = '' UNION SELECT login, password FROM users--
The issue can be found in the source code on the server side.
Use the prepared statements with variable binding (aka parameterized queries). Parameterized queries force the developer to first define all the SQL code, and then pass each parameter (given below) to the query later. This coding style allows the database to distinguish between code and data, regardless of the input type a user supplies.
Java EE – use PreparedStatement() with bind variables
.NET – use parameterized queries like SqlCommand() or OleDbCommand() with bind variables
PHP – use PDO with strongly typed parameterized queries (using bindParam())
Hibernate - use createQuery() with bind variables (called named parameters in Hibernate)
SQLite - use sqlite3_prepare() to create a statement object
Avoid generation of dynamic SQL inside stored procedures. If it can't be avoided, the stored procedure must use input validation or proper escaping to make sure that all user supplied input to the stored procedure can't be used to inject SQL code into the dynamically generated query.
Use the least privilege approach to provide defense in depth and minimize the potential damage of a successful SQL injection attack. Minimize the privileges assigned to every database account in your environment (do not assign DBA or admin type access rights to your application accounts).