In this cheat sheet, we will assume that:

  • You are a developer or you know programming
  • You have limited web application security knowledge
  • You need to know how SQL injection attacks happen
  • You need to know how to fix SQL injection issues in your code

In this cheat sheet, you will learn:

  • How do malicious hackers conduct SQL injection attacks
  • How to fix your code that has SQL injection vulnerabilities
  • How to avoid SQL injection vulnerabilities for the future

1. SQL Injection Attacks

1.1. General SQL Injection Information

SQL injections happen when:

  • Your code uses unsanitized data from user input in SQL statements
  • A malicious user includes SQL elements in the input in a tricky way
  • Your code executes these SQL elements as part of legitimate SQL statements

1.1.1. SQL Injection FAQ

  • What SQL servers are affected by SQL injections?
    All SQL servers may be affected by SQL injections: MySQL, MSSQL, Oracle, PostgreSQL, and more.
  • What programming languages are affected by SQL injections?
    SQL injections may happen in any programming language.
  • What may be the consequences of an SQL injection?
    An SQL injection may lead to data leaks but it may also lead to complete system compromise.
  • How common are SQL injections?
    SQL injections were found by Acunetix on average in 8% of web applications.
  • Do web application firewalls (WAF) protect against SQL injections?
    No, WAFs only make it more difficult for the attacker to send SQL injection payloads.

1.1.2. Simple SQL injection Example

Your code in PHP:

<?PHP
  $userid = $_GET["userid"];
  $query  = "SELECT user FROM users WHERE userid = $userid;";
  $result = pg_query($conn, $query);
?>

Attacker request:

http://www.example.com/test.php?userid=0;DELETE FROM users WHERE 1

Your code processes the following SQL query:

$query  = "SELECT user FROM users WHERE userid = 0; DELETE FROM users WHERE 1;";

As a result, if the current user (current database user) has suitable permissions, the entire users table is cleared.

1.2. SQL Injection Types

1.2.1. In-band SQL injection: Error-based SQL injection

  • The attacker creates the SQL injection to make the back-end display an error
  • The back-end returns an error to the attacker
  • The attacker uses information contained in the error to escalate the attack
  • This type of SQL injection is used to access sensitive information such as database type, file names, and more

Example:

  • Payload:
    http://testphp.vulnweb.com/listproducts.php?cat=1′
  • Result: The web application displays the following error in the browser:
    Error: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near ”’ at line 1 Warning: mysql_fetch_array() expects parameter 1 to be resource, boolean given in /hj/var/www/listproducts.php on line 74

1.2.2. In-band SQL injection: Union-based SQL injection

  • The attacker uses a UNION clause in the payload
  • The SQL engine combines sensitive information with legitimate information that the web application should display
  • The web application displays sensitive information

Example:

1.2.3. Blind SQL injection: Boolean-based SQL injection

  • The attacker sends many payloads that make the web application return a different result depending on whether the SQL query returns TRUE or FALSE
  • The attacker draws a conclusion from web application behavior for each payload
  • This type of an SQL injection is often used to check whether any other SQL injections are possible but it can also be used to access sensitive information

Example:

1.2.4. Blind SQL injection: Time-based SQL injection

  • If the web application doesn’t return errors and the returned information is the same for boolean-based payloads, the attacker sends a payload that includes a time delay command such as SLEEP, which delays the whole response
  • The attacker draws a conclusion from web application behavior and repeats the process as many times as possible with different arguments
  • This type of an SQL injection is often used to check whether any other SQL injections are possible
  • This type of SQL injection may also, for example, be used to guess the content of a database cell a character at a time by using different ASCII values in conjunction with a time delay

Example:

1.2.5. Out-of-band SQL injection:

  • This type of SQL injection is possible only for some databases, for example, Microsoft SQL Server and Oracle.
  • The attacker includes a special database command in the payload – this command causes a request to an external resource (controlled by the attacker)
  • The attacker monitors for attempts to contact the external resource, for example, DNS lookups or HTTP request logs of the external resource
  • If there is a request coming once the payload is executed, this confirms that the SQL injection is possible
  • The attacker accesses database information and can send it to the external resource

Example (Oracle):

  • Payload:
    1||UTL_HTTP.request(‘http://example.com/’)
  • Result: A request is made to example.com – you can monitor such requests if you control example.com.

2. SQL Injection Defense

2.1. Parameterized Queries (Prepared Statements)

  • This technique is available in many programming languages
  • Instead of forming the query by using functions such as concat or other forms of string concatenation, the query string includes parameters
  • The prepared statements library replaces these parameters with values supplied by the user and sanitized, so that SQL commands and user input (parameters) are passed separately

2.1.1. PHP Example

Using PHP Data Objects (PDO):

$dbh = new PDO('mysql:host=localhost;dbname=database', 'dbuser', 'dbpasswd');
$query = "SELECT column_name FROM table_name WHERE id = :id order by column_name desc";
$sth = $dbh->prepare($query);
$sth->bindParam(':id', $_GET[“id”]);
$sth->execute();
$result = $sth->fetchColumn();

2.1.2. Java Example

int id = Integer.parseInt(id);
String query = "SELECT column_name FROM table_name WHERE id = ? order by column_name desc";
PreparedStatement stmt = connection.prepareStatement(query);
stmt.setInt(1,id);
ResultSet results = stmt.executeQuery();

2.2. Stored Procedures

  • Use only if your programming language does not support prepared statements
  • To avoid SQL injections, you must use prepared statements in stored procedures
  • Available only for database engines that support stored procedures but most modern engines support them
  • The query is prepared and stored in the database engine
  • The application calls the stored procedure and passes variables to it

2.2.1 MySQL Example

Creating the procedure:

CREATE PROCEDURE example(IN suppliedId VARCHAR(8))
BEGIN
  SELECT column_name FROM table name WHERE id = suppliedId;
END

Calling the procedure with id = 1:

CALL example("1");

SQL injection payload will not work:

CALL example("0;DELETE FROM users WHERE 1");

2.2.2 MSSQL Example

Creating the procedure:

CREATE PROCEDURE dbo.example @id nvarchar(8)
AS
  SELECT column_name FROM table name WHERE id = @id;
GO

Calling the procedure with id = 1:

EXEC database.dbo.example 1;

SQL injection payload will not work:

EXEC database.dbo.example 0;DELETE FROM USERS WHERE 1

3. Additional Resources

SHARE THIS POST
THE AUTHOR
Tomasz Andrzej Nidecki
Technical Content Writer
Tomasz Andrzej Nidecki (also known as tonid) is a Technical Content Writer working for Acunetix. A journalist, translator, and technical writer with 25 years of IT experience, Tomasz has been the Managing Editor of the hakin9 IT Security magazine in its early years and used to run a major technical blog dedicated to email security.