This talk by Chema Alonso and Jose Parada at the Defcon 16 security conference in Las Vegas introduced a method, and a tool, for performing time based blind SQL injection without the need to use delay functions of the database server.
Blind SQL injection allows data to be retrieved form a database through an SQL injection vulnerability even when that data is not directly output by the vulnerable application. The techniques used to accomplish this require repeated queries selecting a small piece of data, such as a single character or the a string length or a field name, and testing its value. Using conditionals, different behaviour is induced depending on whether the condition has guessed correctly about the data. Gradually then, information can be extracted.
For the technique to work however, a visible difference in the result of a true or false condition must be produced. If the application checks the result of the query more strictly, a generic error message may be given in all cases, removing the ability to differentiate between a true or a false condition. In these situations, timing attacks can be used. These traditionally take advantage of timing functions contained in certain SQL servers to cause the query to pause for a measurable length of time, say 10 seconds. The truth of the condition can then be inferred according to whether the query pauses for at least that length of time, or returns quickly.
If the underlying database does not support, or has disabled delay functions, and the only viable attack vector is timing based, SQL injection to extract information may seem futile. Alonso and Parada demonstrated a method for making this possible, inducing the database to pause longer for one condition by causing it to execute a heavy query.
A heavy query is a query which forces the database to do a lot of work. Such queries take the database server a length of time to process such that the difference between a true and a false condition, executing a light or a heavy query, can be measured reliably. Heavy queries take advantage of a problem common to large database design. Applications can grind to a halt processing poorly constructed queries which are usually hunted down by programmers and altered to be more efficient. There should then be many ways to construct a deliberately slow query.
To make the technique work, it is important to understand how the target database processes queries. Databases without optimisation evaluate conditions and clauses in a fixed order, left-to-right or right-to-left. Databases with optimisation however, estimate which part of a nested query or clause will be more expensive and executes the lighter one first. This allows the database to skip the heavy query if it is not needed to fully evaluate the condition. It is important to know how a given database operates to ensure that the outcome of the query returning quickly or slowly can accurately determine the truth of the condition given.
The following is a generic example of a query designed to perform heavy query based SQL injection attack:
http://server/script.aspx?vuln_param=1 and ()>0 and 300>(select top 1 ascii(substring(name,1,1)) from sysusers)
The heavy query is not filled in here, and more details on how heavy queries can be constructed are discussed later. The thing to note at this point is the structure of the query as a whole. The heavy query will only be performed by MSSQL if the last condition is true. This last condition also makes up the query which extracts the information we are interested in, comparing the value of the first letter of data we are interested in the usual manner of blind SQL injection.
As the light query is optimally executed first, the database server evaluates this side of the condition first. If it is false, it does not need to execute the heavy query to know the overall “and” condition is false, so it skips it, and the query returns quickly. If however, the last condition is true, the database must execute the heavy query to fully evaluate the query, and it returns slowly. In this way, it can be determined if the last condition is true or false, and data can gradually be inferred.
As well as providing a viable attack vector to otherwise unpractical SQL injection vulnerabilities, this kind of attack has an advantage in overcoming IDS detection. As there is usually no need for an application to use delay functions, signatures could be written to detect queries containing such functions. Using heavy queries however, no unusual query statements need to be present and the query looks a lot more like a legitimate query. The ability to create heavy queries in a variety of subtly different ways also makes evading signatures easier. Of course the presence of any generic SQL injection string could still potentially be caught by IDS systems, but the ability to leave out other identifying elements of a timing based attack does increase the chances of letting the query slip by.
By default, the marathon tool designed to automate this kind of attack uses default tables from the database it supports (Microsoft SQL Server, MySQL and Oracle) to reliably construct heavy queries independent of schema. For Oracle, the user_details, user_tables or all_objects tables will be used by default; for MySQL, information_schema.columns is used by default; and for Microsoft SQL Server, the default tables used are sys.databases and sysusers. These tables can be changed in the configuration if desired, and if a table name is already known or guessed, using it instead may aid in attempts to bypass IDS, as only tables legitimately used by the application will be included in the query.
To produce the slow processing effect required by this approach, Marathon uses multiple cross-joins on the tables selected for use. Cross-joins instruct the database to combine every record of the table with every other record. Marathon then tunes the query, varying the number of joins until an efficient delay time is found that is long enough to be accurately measured, but not too long so the attack is slowed down more than necessary. Parameters can be set to constrain this tuning both in terms of the minimum and maximum joins to use, and the minimum length of time a heavy query should take.
Marathon also supports useful features like setting cookies or authorisation data, and routing through proxies, to allow it to be used in a variety of circumstances.
The marathon tool is still being developed, and according to the authors is still in an alphas stage. It is functional, but it currently only supports extracting the schema from a database and not the actual data. Still it acts as a good proof-of-concept for this method of heavy query time based SQL injection.
While the Defcon presentation was given by only Chema Alonso and Jose Parada, the work behind it had many more contributors who should also be acknowledged, They include Daniel Kachakil, Rodolfo Bordón and Antonio Guzmán y Marta Beltrán. Further information can also be found at http://technet.microsoft.com/en-us/library/cc512676.aspx.