When an SQL injection vulnerability is attacked, the application will often display error messages from the database. We are able to retrieve the data we are trying to retrieve from the database by constructing a query that ensures it ends up in the error message passed back to us. This is the method we used in the previous SQL injection example. This is a very quick and efficient way of mining data through SQL injection vulnerabilities. Sometimes, code is constructed in a way that whilst it is vulnerable to injection, it’s not possible to get the data we want returned by the database. Consider the following code –

        $link = mysql_connect("localhost", "twl", "XXXX");

        $sql = "SELECT * FROM wp_posts WHERE ID='" . $_GET['id'] . "';";
        $res = @mysql_query($sql);
        if (@mysql_numrows($res))
                echo "We have rows!\n";
        } else {
                echo "We have no rows.\n";

In this case, any errors resulting from mysql_query or mysql_numrows are silenced with an @. In addition, the application only displays a “We have rows!” (true) or “We have no rows.” (false) message. We can get the database to execute our queries, but we receive nothing back other than a true or false response. Although this sample code has been set up in this way, in a real world scenario this will often be seen as the page either fully loading and providing the view expected (true) vs a shorter version of the output, specifically a page where execution has stopped part way through and the expected results and succeeding text/footer is missing (false). In this case, we perform a ‘blind’ SQL injection attack.

In pseudo-code, we exploit this code with –

1' AND IF ( GET_SINGLE_CHARACTER(field_we_want, 1) == "A" ) AND '1'=='1

If this returns true, we move on to the next character in the field (increase 1). If it returns false, we move on to the next letter in the same field (increase ‘A’)

In this case, sqlmap finds –

[INFO] GET parameter 'id' is 'AND boolean-based blind - WHERE or HAVING clause (MySQL comment)' injectable 

When specifying –dbs in order to enumerate the list of databases using this method, we receive the following output:

Place: GET
Parameter: id
    Type: boolean-based blind
    Title: AND boolean-based blind - WHERE or HAVING clause (MySQL comment)
    Payload: id=1' AND 6854=6854#
web application technology: Apache
back-end DBMS: MySQL 5.0.11
[23:44:49] [INFO] fetching database names
[23:44:49] [INFO] fetching number of databases
[23:44:49] [WARNING] running in a single-thread mode. Please consider usage of option '--threads' for faster data retrieval
[23:44:49] [INFO] retrieved: 2
[23:44:51] [INFO] retrieved: information_schema
[23:45:36] [INFO] retrieved: twl

Lastly, what happens if our code doesn’t even return a true or false condition?

        $link = mysql_connect("localhost", "twl", "XXXX");

        $sql = "SELECT * FROM wp_posts WHERE ID='" . $_GET['id'] . "';";
        $res = @mysql_query($sql);

In this case, sqlmap will use a time based blind attack.

Blind SQL Injection

Blind SQL Injection

[INFO] GET parameter 'id' is 'MySQL > 5.0.11 AND time-based blind (comment)' injectable 

In pseudo-code –

1' AND IF ( GET_SINGLE_CHARACTER(field_we_want, 1) == "A" ) AND SLEEP(5) AND '1'=='1

If we take 3 samples, one where we evaluate the page load speeds when running “1 == 1 AND SLEEP(5)” which will always be true, and then “1 == 0 AND SLEEP(5) which will always be false”. The average for the true case may be say 210ms load time, while the average for the false case may be 5190ms. Now we are able to enumerate data using the same method as before, however gathering our true/false response from the page load speed rather than the returned text on the page.

This is the slowest method, and also most error prone. If the site response speeds are too unpredictable and vary dramatically or if the local connection is lagging or under stress, the attack becomes far more difficult. That said, this and the above type of blind SQL injection are likely to bypass the outbound filtering of application firewalls or IDSs that are monitoring outbound data for SQL error messages and similar.