Blind MySQL injection and database stressing

Complete with the rest of Mysql blind injection papers in the web.

Currently tools are being used to get SQL data from a blind (Microsoft) sql injection, like datathief of absinthe. The problem in Mysql is the dificulty to get the database structure. In Mysql there are no Objects database or alike, so it's not possible to create an stored procedure to walktrough a database catalog as these programs do with other database managers.

The approach explained here is from a web service viewpoint. It's, from a web service vulnerable to sql injection.

Current Blind SQL injection methods

Despite the title, this article doesn't cover the whole mysql injection world, but just some notes!

Most of the tools in use now to extract data from a sql injection make use of the stored procedures. The configuration of the tool incorporates some variables to create the stored procedures in the remote server and to tool itself interactuates later with them.

The Microsoft SQL database mantains a catalog (as many others do) about the composition of the databases, their tables and their fields. The stored procedures make extensive use of this catalog to quickly present the database structure to the user, so it can interact later with the database.

The last feature not found in Mysql is the availability to execute more than one sentence in a database query from the web service. It's, ';' separated sentences will be executed, while Mysql only allows one sentence to be executed (note: some TODOs, like php's, showed to allow more than one sentence to be executed, but it's not developed yet.). At this point, Mysql is the lowest developed (or the most secure) interface, as Mysql V3 doesn't allow UNION in the sentence.

Data types

One of the features Mysql offers to blind Sql injection are the variable datatype. Almost every value can be handled as variable, so there's no need to exactly match the field data type in the guess, what is a really usefull.
Forget the VARCHAR, DATE and all the other formats of fields, they are defaulted to "variant" value by the web service or by the mysql engine, so the sentence "SELECT 1 FROM users WHERE 1=1" will be as acepted as "SELECT '1' FROM users WHERE 1=1". And with this I mean the database manager will react the same way with both sentences, but if the web service is expecting a concrete data type the application may fail.

Exploiting blind SQL injection in MySQL

I will assume the reader knows what's SQL Injection and understands why and when it's called "blind". Let's start from a web script allowing us to inject MySQL code but not informing the errors. We can get two expected responses with a correct injection inserted, one is when the sentence is returning the same result withouth injection, and other with blank results, error page or redirection, or defaulted. The results will be diferent if we use AND or OR sintax in the injected sentence. Let me explain:

- OR sintax: could be used to display multiple results from an abused injection.
- AND sintax: could be used to guess values, as deterministic operator.

It would be usefull to determinate different attack vectors in MySQL injection to stress the database and get it's structure:

- The use of INTO OUTFILE, or LOADFILE. The use of files will help a lot in several attack vectors.
The posibility to create a database interface using dumps to file will allow to create a simple version of an export.php or export.xxx to connect to the database. This will allow to execute commands like "SHOW DATABASES" or "SHOW TABLES" with the following code: $result = mysql_query("SHOW tables", $db); . Later the use of the command "DESCRIBE tablename" with each one of the tables to show more information, in order to fully automate the export feature like the export function in applications like PhpMyAdmin. It's a little intrusive to use filesystem to get database control, but, after all, it's the same as using stored procedures.

- The use of UNION to expand the attack field to other tables and objects per request.
When the union sentence is avaiable, selects to other databases and tables are allowed with the format *** UNION SELECT * FROM mysql.user WHERE ****, so this will help a lot to extract data from the database.

- Error reporting, It's important to notice, that an injection may be blind even if error reporting is activated. The topic here is that we will see an error reported from following code instead that from the inserted one. The error showed will not help a lot in the extraction process, but may help determining how to explode the injection, it's, when the injection is well conformed.

Getting mysql structure

The first task IMHO is to get the database structure, but it will rely in the priviledges of the user being connected to the database in the injected-vulnerable script. This situation could sandbox us in the selected database or the databases where the user has read permissions.

NOTE: from now on the expression "expected result" correspond to the returned page from the server as if no injection was inserted in the request, it's, the page as it was.


the mysql.db table

There's a table in the mysql database named db. This one holds the permissions relation in the database manager, and can be used to force a select and extract the database names. But, there's a but, only those databases with permissions assigned (it's, a "GRANT PRIVILEGES" for a user was executed) are saved here.

Selectable blind objects

In sqlbftools project readme are documented some of the objects available from a blind sql injection. This POC use some kind of bruteforce explained in this paper: adaptive dictionaries for bruteforce cracking

Selectable blind objects are those who export important information about database manager, like functions or important values:

* version(): current mysql version
* database(): current database where user is connected
* user(): connected to the database
* system_user(): obvious
* session_user()
* current_user()
* last_insert_id()
* connection_id()
* .....
* and off course, all data available in the query

Alltough it's not possible to execute more than one select in a request, several functions like previous may be executed within the select.

Bruteforcing objects

When there's no other way to get the database structure, a bruteforce may allow to guess some values. One of the main problems here is the user privileges. If user has no right no read the database, an error will be returned. If the injection is blind, it's no information (neither errors) were displayed, then we couldn't know when the database doesn't exists or the user has no permissions to read it. The first problem is to get the number of arguments in the SELECT sentence.


Number of arguments in the SELECT

The number of arguments (1 to n) is unknown initially, but it's an easy guess by an incremental injection of the type: "UNION SELECT 1", "UNION SELECT 1,2" and so on untill we get the expected results.


Database and Table objects

Once we know the number of arguments the injection could be like this:
UNION SELECT 1,2,...,n FROM database.table WHERE 1=0


The "WHERE 1=0" will not add any result from the union, so this way we will not modify the correct select, but if the returned page is what expected than the database and the table are valid names. Almost 90% of databases have users or other possible table names (it's context dependant) so "a.users" "a.categories" or "a.articles" are good choices bruteforcing the dabatase.

When the database is known, a bruteforce against the table name will help us finding the tables of the database.

Later, once the database and the table are OK, then we can start to guess field values, changing 1 or 2 or n with guessing field name. Do it one by one, or you won't know when both are bad or one is ok, remember, it's blind sql injection.

Bruteforcing database names

When the UNION is not avaiable (MySQL v3) than guessing the databases name is not so easy as it's for table names (within the same database) or fields.

Bruteforcing table names

The use of simple sql injection like "AND table.field = 2" is not a valid sentence if the table was not used in the SELECT. The only way to guess more table names of the current database is if they were used in the SELECT sentence. Anyway, in a blind injection is not possible to determinate when the table or the field are wrong if the expected result is not returned: It may fail if the table or the field and not correct, and execute correctly only if both, table, and field in the table exists.

Bruteforcing field names

The use of simple sql injection like "AND field_name = 2" will complain the select with a valid field name. The problem here is the deterministic AND or OR selector for the query, because even if the field name is correct, no valid selection could be expected from the database, so no results will be returned. After several testing the sentence "OR field_name = 0" is a good aproximation, as the result will return at least the same record as withouth injection, but it may return tons of records (all those whose field_name field should be 0). For this to ensure it's a valid match, some results are expected as good. If the page support more than one match in the query and a lot of result are displayed the field has been guessed. It may happend that no results are displayed, by two factors: the field name was never guessed, or an error ocurred when more than one result is displayed by the OR selector. Then an AND selector may be used to ensure that the valid field name was not skipped due to errors displaying the page.

Bruteforcing values

The last to do with a blind sql injection is to bruteforce some values of the select (or getable mysql objects described before).

The injection to do that is something like:
AND MID($$$VAL$$$,1,1) LIKE CHAR(37)

This will test if the first character of $$$VAL$$$ is 37. Substring could be as long as whished, and other strings can be used:
AND MID($$$VAL$$$,1,4) LIKE 'root'

To test if the value of the variable is root. This should return the expected resulting page as if no injection was requested when the LIKE comparation is correct, it's, when there's a correct guess

Using a bruteforce against a charset it's possible to go guessing each character of the value. $$$VAL$$$, it's the value, could be any of the getable objects like VERSION() and so, or any of the values in the select sentence when the injection was done.

Some cares:

Not everything is as easy as it seems..

Mysql version cares

Diferent Mysql versions will have diferent features. Where there's no way in MySQL to know the databases structure other than using SHOW in mysql 3 and 4, in Mysql 5.x there's a new table, INFORMATION_SCHEMA, holding everything about databases, tables, columns and so. Some recursive selects requests to this table will give all the information about the database.
http://dev.mysql.com/doc/refman/4.1/en/
http://dev.mysql.com/doc/refman/5.0/en/

So, it's not only that diferent functions will be available, also diferent tables are version dependant. It's important then to notice that version of exploited MySQL is the first task to guess no matter how. MySQL 3 doesn't support UNION sentences, MySQL5 incorporates the INFORMATION_SCHEMA table.. Not every operation can be executed in every MySQL version.

Operating system cares

In the manual of MySQL you could find a link like this: http://dev.mysql.com/doc/refman/4.1/en/operating-system-specific-notes.html . Please read carefully to understand the diferences of Mysql in each one of the operating systems. This will dificult the automation of tools. Path conventions accessing the filesystem, data type and storage size, forbidden operations and so are examples about operating system casuals.

Some functions may not be available in all operating systems, as other may answer different values. In the process of automate a tool to grab the information cross-system should be granted, or at least system dependant operations performed.

web service cares

Application server connection to web server may perform diferent operations with the data upon request performing in the database manager. Canonicalization of paths, strings or format conversions, charset and character adaptation.. There's a lot of considerations to handle with the application service.

Most of the times the Web service will be Apache and the application service will be PHP, but not always is this way. If we automate this environment (LAMP) then the tool will only stress LAM environments.

Security applications

Most of the time a layer of security is added to each one of the previous. PHP security configuration options, mod_security or any uri parser, a layer7 firewall, operating system acces control list and so. Any attack may be detected and stoped at each, so not always the automation will be able to detect when the result is good or where was the attack detected.
Not always a security circunvention can be applied but you can try to find some of them reading carefully the data interpretation in mysql.. http://dev.mysql.com/doc/refman/5.0/en/string-functions.html

Put all them together..

..and you will have several problems extracting data from a MySQL server due to the diferent options/configuration/environments you could find. Anyway, the lowest version you get to exploit, the more operations you can perform in posterior versions, even if there's an easier way to do with the last version.

Well, with this resume of things lets down the lower level of posible activity, to a MySQL v3 server, with a PHP with magic_quotes enabled in a windows Box (harder to get some paths working) and a complete Blind injection where no error is reported. Try to figure out where is the limit.. then as an example you can find some videos about MySQL stressing here:

beyond mysql injection video


TOOLS OF THE TRADE

To test all this and play with, we developed some stupid tools to stress the database in the worst case: it's, BLIND mysql injection in mysql3 (no unions are accepted) with php's magic_quotes and safe_mode enabled..

The tools are included in the project sqlbftools. Download it here

sqlbf

This tools bruteforces mysql values. The video at http://www.unsec.net/ shows how to use the tool and how to extract information of the database. Information functions are the best choice to bruteforce!:
http://dev.mysql.com/doc/refman/5.0/en/information-functions.html

This tools is now mantained at http://www.unsec.net as msqlbf.pl.

sqlget

Allow you to donwload files from a web site with a blind mysql injection.. including binary files!

sqlst

sqlst is parser for MYD, FRM and MYI files.. this tools was designed to read and parse tables formats, and field contents, so withouth the need to download all the database file, be able to read any database value. It's very difficult to parse a mysql files due to the version changes of the MyISAM format, but still you can reach a good point if you develop a little.. This tools needs more testing before publishing.. sorry!!! (actually, private tools are so expensive.. jeje)


Last Notes

The value bruteforce was implemented in the sqlbftools project to stress some of the getables values from a blind MySQL injection. Some videos will be uploaded to the web so you can see it working. Anyway the program is really easy to use, and is as well documented to get it compiled and running by yourself. A readme is included with a using example.