MSSQL Tips

This article is nothing new, but it focalizes on giving all information needed to do a sql injection on a SQL SERVER (mssql). All queries will not modify or add anything to the database.

1 – Standard SQL injection (not blind)

1.1 – Information gathering

Get server version:

Get server name:

Get current username:

Get current database name:

1.2 – Database structure

MSSQL is a very friendly database… you can get all db structures via normal select. Fist of all you can take the list of databases on the server.

Using an sql injection like:

will show you only the first result. To get all records we need to implement something in sql like the limit keyword on mysql ($XX$ is the row number):

or you can use this way (I know, someone will think 2 top should be enough, but sometimes it gives trouble, with 3 top no… don’t ask me why… hey Lame! it’s your query!):

You can test this syntax with (“or 1 in” on the first query will return always the same result, so we will use “or 1 =”):

To get numeric data we need to convert them to strings and append a non numeric char, otherwise the sql server will do an automatic cast.

and we can append data to get results faster

Ok, now we have to get the tables name, columns etc. We will work on the current database, but you can access to the others with a double dot syntax, like “master..sysdatabases”.

This query will return you all the primary keys of all tables names, column names and column type (string, boolean, int).

and this one will return all non primary keys.

So you can build the database structures using this query:

or using this (simple) one:

Now we can download the primary keys columns ($XX$ is the number of the row) the $ will be the deliminator

and the other columns

Ok… now you have all the database structure of the current database.

1.3 – Dumping the data

If you have the database structure, it is simple to get the data. For example if we have a table named “users” with primary key “userid” (numeric) and with columns username,userpass,usermail you can get single data with:

or you can get it on a single query with:

If you wouldn’t use a where condition (if you don’t know how many record there will be, or if you don’t know the primary keys) you can always use the top method as:

Happy dumping 😉

1.4 – Privilege escalation with OPENROWSET

A query can be done with normal users privileges, but sometimes you need administrator privileges (for example to use xp_cmdshell) or get access to others databases. On SQL SERVER 2000 you can use the OPENROWSET to bruteforce the admin password (on SQL SERVER 2005 it has been disabled by default) with a query like thisone

If “Login failed for user ‘sa'” appears the login is incorrect, otherwise you found the password. With a query like thisone you can get data of other databases:

Remember the escape character in MSSQL is ” so, if you need some ‘ on the query in the openrowset you need to use them double like:

 

2 – Blind sql injection

Ok, we have seen how simple is to get data on standard sql injection with display error on, now we will try to work on blind sql injection. The sample code of a simple application can be found here. The example does a simple query on the master database table and shows the results. In this application as you can see there is a error catching, so you will never see an error.

First of all you have to identify a way to get different results with injecting your data, for example:

Another interesing way can be use sql optimizations to get an error if the last part of the query is correct.

Having this kind of difference between the results gives you a way to work with a blind sql injection. Another way can be using WAIT and similar instructions of the db, but to get the results you will spend a lot of time.

To get the data using this response differences we can use the keyword like:

If the page will return a non blank result the table sysdatabases columns names contains a record that starts with the letter M. Now you can implement a little brute force tool to get all the names.

The choice of the charset for the bruteforce attack can cause a lot of problems. You will not be sure to get all the data because you don’t know what type the data is. By using the stored procedure fn_varbintohexstr you can convert the data in a hex value, so you will know the charset is “abcdef01234567890”.

As described with the standard sql injection you can get table structures and data. So build your own sql blind bruteforce script.

 

3 – Compatibility issues

During some pentest I got some strange error on the syntax of the injections, I discovered that there was some compatibilty issues on the software set with sp_dbcmptlevel. To avoid these limits you just need to change the database and work as with blind sql injections.

4 – Escape errors

Some very skilled programmers use some routines to escape the user input to avoid sql injection problems. Some of them escape the ‘ char with a \ (for example who uses php with a sql server db). He does not know that on mssql the escape is not \ but ”. So you can inject as normal, but you can not use the ‘ on the query. This can sometimes be a problem. To bypass this limitation you can use SET QUOTED_IDENTIFIER OFF and use ” instead of ‘. Here is an example: