Short Description of the Issue

SQL Injection vulnerabilities occur whenever input is used in the construction of a SQL query without being adequately constrained or sanitized. The use of dynamic SQL (the construction of SQL queries by concatenation of strings) opens the door to these vulnerabilities. SQL injection allows an attacker to access the SQL servers. It allows for the execution of SQL code under the privileges of the user used to connect to the database.

MySQL server has a few particularities so that some exploits need to be
specially customized for this application. That's the subject of this section.

Black Box testing and example

How to Test

When an SQL injection vulnerability is found in an application backed by a MySQL database,
there are a number of attacks that could be performed depending
on the MySQL version and user privileges on DBMS.

MySQL comes with at least four versions which are used in production worldwide.
3.23.x, 4.0.x, 4.1.x and 5.0.x.
Every version has a set of features proportional to version number.

From Version 4.0: UNION

From Version 4.1: Subqueries

From Version 5.0: Stored procedures, Stored functions and the view named INFORMATION_SCHEMA

From Version 5.0.2: Triggers

It should be noted that for MySQL versions before 4.0.x, only Boolean or time-based Blind Injection attacks could be used, since the subquery functionality or UNION statements were not implemented.

From now on, we will assume that there is a classic SQL injection vulnerability, which can be triggered by a request similar to the the one described in the Section on Testing for SQL Injection.

http://www.example.com/page.php?id=2

The Single Quotes Problem

Before taking advantage of MySQL features,
it has to be taken in consideration how strings could be represented
in a statement, as often web applications escape single quotes.

MySQL quote escaping is the following: 'A string with \'quotes\''

That is, MySQL interprets escaped apostrophes (\') as characters and not as
metacharacters.

So if the application, to work properly, needs to use constant strings,
two cases are to be differentiated:

Web app escapes single quotes (' => \')

Web app does not escape single quotes (' => ')

Under MySQL, there is a standard way to bypass the need of single quotes, having a constant string to be declared without the need for single quotes.

Let's suppose we want to know the value of a field named 'password' in a record,
with a condition like the following:
password like 'A%'

The ASCII values in a concatenated hex:

password LIKE 0x4125

The char() function:

password LIKE CHAR(65,37)

Multiple mixed queries:

MySQL library connectors do not support multiple queries separated
by ';' so there's no way to inject multiple non-homogeneous SQL commands inside a single SQL injection vulnerability like in Microsoft SQL Server.

For example the following injection will result in an error:

1 ; update tablename set code='javascript code' where 1 --

Information gathering

Fingerprinting MySQL

Of course, the first thing to know is if there's MySQL DBMS as a backend.

MySQL server has a feature that is used to let other DBMS ignore a clause in MySQL
dialect. When a comment block ('/**/') contains an exclamation mark ('/*! sql here*/') it is interpreted by MySQL, and is considered as a normal comment block by other DBMS
as explained in MySQL manual.

Example:

1 /*! and 1=0 */

Result Expected:If MySQL is present, the clause inside the comment block will be interpreted.

Result Expected: Results are stored in a file with rw-rw-rw privileges owned by
MySQL user and group.

Where /var/www/root/test.jsp will contain:

//field values//
<%jsp code here%>

Read from a File

Load_file is a native function that can read a file when allowed by
filesystem permissions.

If a connected user has FILE privileges, it could be used to get the files' content.

Single quotes escape sanitization can by bypassed by using previously described
techniques.

load_file('filename')

Result Expected:

The whole file will be available for exporting by using standard techniques.

Standard SQL Injection Attack

In a standard SQL injection you can have results displayed directly
in a page as normal output or as a MySQL error.
By using already mentioned SQL Injection attacks and the already described
MySQL features, direct SQL injection could be easily accomplished at a level
depth depending primarily on the MySQL version the pentester is facing.

A good attack is to know the results by forcing a function/procedure
or the server itself to throw an error.
A list of errors thrown by MySQL and in particular native functions could
be found on MySQL Manual.

Out of band SQL Injection

Out of band injection could be accomplished by using the 'into outfile' clause.

Blind SQL Injection

For blind SQL injection, there is a set of useful function natively provided by MySQL server.

String Length:

LENGTH(str)

Extract a substring from a given string:

SUBSTRING(string, offset, #chars_returned)

Time based Blind Injection: BENCHMARK and SLEEP

BENCHMARK(#ofcycles,action_to_be_performed )

The benchmark function could be used to perform timing attacks, when blind injection by boolean values does not yield any results.