Manage Learn to apply best practices and optimize your operations.

Time delay SQL injections

Learn about time delays in this excerpt from "The Database Hacker's Handbook: Defending Database Servers" by David Litchfield, Chris Anley, John Heasman and Bill Grindlay.

The following excerpt, courtesy of Wiley Publishing, is from Chapter 22 of the book "The Database Hacker's Handbook: Defending Database Servers" written by David Litchfield, Chris Anley, John Heasman and Bill Grindlay. Click for the complete book excerpt series or purchase the book.

Time delays

The previous examples of SQL injection techniques assumed that the client can view the error messages returned by the backend database server; however, often the Web server is set up so that error messages are not returned. In this case an attacker may suspect that the Web application is vulnerable to SQL injection but be unable to view any useful information because of its configuration. A method used here to extract the data is known as time delay SQL injection, and works on the basis that true or false queries can be answered by the amount of time a request takes to complete. The statement waitfor used with the delay argument causes SQL Server to pause for the specified period of time:

waitfor delay '0:0:5'

This will pause the query for five seconds.

This feature can be leveraged to reveal information, such as whether the Web application's connection to the database is made as a system administrator:

if (is_srvrolemember('sysadmin') > 0) waitfor delay '0:0:5'

This will cause the query to pause if true, or return immediately if false. At the very lowest level, all data stored in the database is just a binary series of ones and zeros. This means that any data in the database can be extracted using a sequence of true/false questions. For example, the query

if (ascii(substring(@string, @byte, 1)) & (power(2, @bit))) > 0 waitfor
delay '0:0:5'
will trigger a delay only if the bit (@bit) of byte (@byte) in the string (@string) is set to 1. To retrieve the current database name from the server, execute
declare @string varchar(8192) select @string = db_name() if
(ascii(substring(@string, 1, 1)) & (power(2, 0))) > 0 waitfor delay

This will delay if the first bit of the first byte of the current database name is set to 1. The second bit of the first byte can then be queried:

declare @string varchar(8192) select @string = db_name() if
(ascii(substring(@string, 1, 1)) & (power(2, 1))) > 0 waitfor delay

and so on, building up the entire string. Obviously using this method, this would be a time-consuming process, mainly because of the five-second delay per set bit. It is not necessary, however, to run these queries sequentially or in any particular order. A small program, known as a harness, can be used to form the URLs to request with the necessary injected SQL to build the required string. Multiple requests can then be made to the server in multiple threads, and the harness program can then wait for the requests to return and build the string as they do.

Example C code for a generic harness program is included in Appendix A.

Click for the next excerpt in this series: Stored procedures

Click for the complete book excerpt series.

Dig Deeper on SQL Server Security