Entries in SQL Injection (5)


Exploiting Integer Based SQL Injection in Nested SQL Queries

In this post I’ll be talking you through exploiting what turned out to be an interesting SQL Injection variation - SQL injection involving nested queries and arithmetic evaluation.

Consider the following example application requests and responses:


your account balance is: 16230


your account balance is: 56963

The underlying SQL query in this case is equivalent to the following:
SELECT balance from balances where account_number=(SELECT account_number from accounts where id=?);

This parameter is vulnerable to integer based SQL Injection, which we can verify by using the following “id=1” parameter value equivalents:


your account balance is: 16230


your account balance is: 16230


your account balance is: 16230


your account balance is: 16230

This is pretty conclusive proof that our “id” values are being evaluated as part of a dynamic SQL query. Still it’s always worth proving the negative case, so we can go ahead and test a few other numerical values and see if they return other balance values.

Let’s see what happens if we try to return the MySQL version:



No luck. Still we can leverage the fact that we can manipulate integers to infer the result of the above version request. We can do this by using the MySQL “ASCII” native function. The ASCII function will take a string and return to us the leftmost character as a decimal value.


your account balance is: 990

Great! It looks like the expression evaluated and returned a response based on the first character of the version string.

By spidering all possible id values we discover that the balance value 990 belongs to the account with id value “53”:


your account balance is: 990

So we now know that the decimal ASCII value of the first character is the MySQL version string is “53”. If we use an ascii lookup table we can map this value to the “5” character. The first character in the MySQL version string is “5”.

To get the other characters in the version string, we can use the MySQL “SUBSTRING” native function. Let’s use it in our example to return the second character of the version string:

id=ASCII(SUBSTRING(@@version,2,1)) Response:
your account balance is: 96146

The response is equivalent to a request to “id” value “46” which indicates that the second character in the version string is a “.” character.

Using this technique we can step through each character and enumerate the whole response string. To aid us in the process we can get the total length of the version string by using the MySQL “CHAR_LENGTH” native function.


With the response being equivalent to “23”.

I think we’ve proved a point here in what is a fairly contrived scenario. In this example we can actually bypass this whole process as there is no actual filtering involved (just implicit type-casting in the SQL query). The following request will return the whole version string:

id=53) union select @@version — -

your account balance is: 5.5.28-0ubuntu0.12.04.3

This teaches us a lot about the power of close brackets in evaluating potential SQL injection (you don’t always need a quote!) but it doesn’t teach us a lot about real world exploitation where filtering is enabled.

For my next trick we’ll look at an example where this technique was used to identify and exploit an 0day SQL Injection issue in the McAfee ePolicy Orchestrator product.

Disclosure Details:

McAfee ePolicy Orchestrator (ePO) 4.6.5 Blind SQL Injection Via SQL Arithmetic

Vulnerability Type: Blind SQL Injection

Company: Gotham Digital Science

Affected Software: McAfee ePolicy Orchestrator (ePO) 4.6.5 (Build 168)

McAfee Security Bulletin:

Vulnerability Description:

The ‘uid’ parameter passed to the ‘’ page allows for the passing of SQL arithmetic that is evaluated as a dynamic SQL statement. The database backend evaluates these values and then returns the associated record.


The following request and response pairs demonstrate the use of the SQL integer evaluation injection:





(The response value ‘GDSSECURITY’ is related to the host name of a machine being referenced by the ‘uid’ value and is returned as part of the response data).

Since we know that making a request with the ‘uid’ parameter value set to 1 returns the value host-name value ‘GDSSECURITY’ we can use any query that evaluates to 1 and confirm that it evaluates to 1 by getting the expected response back.

For example consider the following Request:
/EPOAGENTMETA/ * ASCII(SUBSTRING(@@version,1,1)) / 77

If the value of the first character of the database version is equal to ‘M’ then the arithmetic will be equivalent to “1 * 77 / 77” (i.e the value “1”).

We run into a practical challenge in certain situations in that SQL Server will, in some cases, round off equations evaluating to non-whole number results.

For example the following queries will both be rounded down to the same result (the value “1”):

select 1 * ASCII(SUBSTRING(@@version,1,1)) / 77 = 1 select 1 * ASCII(SUBSTRING(@@version,1,1)) / 76 = 1

To compensate for this we can explicitly cast the return value as a float by first dividing by the decimal value ‘0.5’ as per the following example:

SELECT 1 * 0.5 * ASCII(SUBSTRING(@@version,1,1)) / 0.5 / 77

In these conditions SQL Server will handle the casting of return values according to its own internal rules. With the return value cast as a float integer we can perform the arithmetic we need without the danger of rounding down and getting inaccurate responses.

The following proof of concept will use these techniques to validate the first character of the server version as the ASCII value 77 or ‘M’:

/EPOAGENTMETA/ * 0.5 * ASCII(SUBSTRING(@@version,1,1)) / 0.5 / 77

The application returns the expected record “GDSSECURITY” validating that the first character of the database version string is ‘M’ and therefore most probably a Micosoft SQL Server instance.

Extending the Attack:

It is possible to step out of the restrictions of injecting into a ‘SELECT’ query through the use of stacked queries. The following proof of concept demonstrates the addition of a second, arbitrary query after a completed initial parameter:


This request will result in a 5 second delay before a response is returned by the database and the application.


So there you have it. Nested SQL queries and type-cast values can be dangerous. If you haven’t already, add “)” and “ASCII(@@version)” to your attack dictionaries.


SQL Injection used in Heartland, 7-Eleven and Hannaford Breaches

Having recently seen our book SQL Injection Attacks and Defense come out, it is very timely indeed to see in the news of the recent indictment of Albert Gonzalez that SQL Injection played a key part in the Heartland Payment Systems, 7-Eleven, and Hannaford Brothers breaches, as well as for two other unnamed victim companies.

So how can SQL Injection, which is an application level problem, be used as a vector for attacking an organization? In a number of ways. SQL Injection gives an attacker the ability to interact with the database, and therefore if something is possible on the database server it may well be possible through SQL Injection. Modern database systems such as Oracle, SQL Server and others provide a rich variety of functionality for their users - all too often though, some of this functionality can be abused by malicious individuals.

Making some assumptions, its likely that something like the following occurred:

  1. It was possible to interact with the underlying operating system in some way using SQL Injection. This could have been through the ability to execute operating system commands (such as through the well known xp cmdshell stored procedure on Microsoft SQL Server), or through the ability to stage content to the database server (or filesystem) and then have it compiled to executable content.
  2. With the ability to execute content at the operating system layer, access was consolidated by providing some form of alternative control channel or remote access to the database server.
  3. With consolidated access to the database server, the attacker uses the database server as a foothold to go further into the organization.

These types of hybrid attacks where one type of attack is dovetailed or launched over another are becoming increasingly common. Another SQL Injection hybrid attack of recent note was the SQL Injection mass attacks that started in early 2008. These used SQL Injection in another way - to inject links to JavaScript malware into thousands of unsuspecting vulnerable sites. It just goes to prove that even if a vulnerability is over 10 years old, it still has some new tricks to be seen.


Using SPF to Protect Against SQL Injection Worms

When SPF was first released last month, I knew it was a great protection mechanism to thwart attacks against applications running on IIS. What I didn't realize was that the most urgent gap that it fills is that of thwarting SQL injection worms.

Microsoft has pitched UrlScan v3 as a band-aid solution to protect against SQL injection worm attacks on classic ASP and ASP.NET applications. The reality is that UrlScan's capabilities to protect applications-level attacks are quite limited. Specifically, UrlScan is not able analyze POST data and lacks support for regular expressions. This combined with the inability to include or exclude specific URLs leaves many users unable to adequately protect their vulnerable applications. Unfortunately with UrlScan it's an all or nothing approach.

SPF overcomes both of these shortcomings. Unlike UrlScan, SPF is specifically designed to thwart application-level attacks. UrlScan is not. UrlScan was originally designed to protect IIS web servers from the onslaught of web server attacks that surfaced shortly after the turn of the millennium (i.e. Code Red, Nimda, etc). UrlScan is very effective as a server-level protection mechanism; however the reality is that it simply was not designed to be an application-level protection mechanism.

Last week, an updated beta of SPF was released which has been significantly optimized for performance in Black-List only configuration mode. I have come up with the following sample configuration which can be used to protect IIS6 applications from SQL injection attacks (applications hosted on IIS7 can also use this configuration). Keep in mind that these patterns are designed to prevent false positive hits while still allowing most sites to function; using blanket deny rules against strings like "exec", for example, won't work in most real-world situations (strings like this occur way too often in most free-text submissions). I experienced this first-hand when attempting to implement UrlScan on a customer website using the sample SQL Injection rules published on the IIS.NET Security Blog.

The Black-List only sample configuration for SPF is shown below:

<spfConfig logDirectory="c:\\temp\\logs" protectForm="false" protectUri="false"
protectQueryString="false" protectCookie="false" protectMode="Active"

<add extension=".asp" />
<add extension=".aspx" />

<add patternRegex="(select|grant|delete|insert|drop|alter|replace|
database|index|view|set)" applyTo="all" />
<add patternRegex="'?\\s+OR\\s.+=" applyTo="all" />
<add patternRegex="(--|;|*|@@|0x|DECLARE|..|.dbo.)" applyTo="all" />
<add patternRegex="(CAST|EXEC|CHAR)(%|()" applyTo="all" />
<add patternRegex="(s|x)p_" applyTo="all" />

If anyone has any additional ideas on good SQL attack patterns to look for, feel free to share your thoughts. Keep in mind SPF BlackListPatterns are not case sensitive and are applied to decoded request data. As always, this is not intended to be permanent solution for SQL injection (as opposed to fixing your code); however it certainly raises the bar for bad guys and will buy you some time to implement the optimal fix.


Overview of "SQL Injection Worms for Fun and Profit" 

For those of you who didn't catch my turbo talk at Black Hat in Las Vegas, and especially those of you who looked at the slides and demo in my previous blog post and had no idea what the talk was about, I thought I'd put together a short summary of what was covered, and what I demonstrated.

I began my presentation by discussing the mass SQL Injection attacks that started earlier this year (see Internet Storm Center coverage from the start of the year), originally out of China, but now out of Eastern Europe as well. The profit motivation for these attacks is fairly obvious - inject JavaScript malware into a site's HTML. The attacks exploit SQL Injection vulnerabilities to insert JavaScript into the database that is then rendered back into web pages. Botnets are often used to randomly attack website pages on the Internet (chosen using Google, for example) with a generic SQL Injection attack. The attacks have one shot at success - it either works or it doesn't. The major upside of using a botnet is that even a low success rate can be devastating as they can still compromise hundreds of thousands of pages. Even worse, the indiscriminate nature of botnet attacks make it so potential victims no longer have to wander off to the deep dark corners of the Internet to face the possibility of some malicious content being installed on their machines, because any site could potentially be infected.

There are some other profit motivations that to date we haven't seen exploited. Namely, unlike the more common botnet attacks that seem to largely target home users for their personal information and details, the mass SQL Injection attacks have a different target - websites developed by organizations and businesses, large and small. Some of which may have some very interesting information, such as customer data and (regardless of whether it is supposed to be there according to the PCI DSS) credit card information. Another target are websites that are on DMZ's behind outer perimeter controls (e.g. firewalls), and therefore may provide a useful pathway into an organization's network, and all of the interesting information and data residing there.

Building on these attack scenarios, I then speculated on aspects of the current mass SQL Injection attacks that could lead to more serious exploitation. What I came up with was a self replicating SQL Injection worm, and this is what was demonstrated on stage at Black Hat.

How does the Proof of Concept SQL Injection Worm Work?

For the moment it is Microsoft SQL Server specific, largely because the functionality leveraging the underlying operating system is straight forward to access in SQL Server. The worm looks at the IP address it is on, and if it is an RFC 1918 private IP range it will scan the subnet looking for other web servers on port 80. When it finds a website, it does a fairly simple crawl of the entire site, and then parses through the HTML code to identify query strings with parameters, as well as forms in the HTML. The worm then tests each parameter in succession for trivially identified SQL Injection vulnerabilities. If a parameter is vulnerable, the worm will then run through the following tests:

  • is the back end Microsoft SQL Server?
  • are stored procedures executable?
  • is the xp_cmdshell extended stored procedure executable?

If those tests succeed, the worm uses the xp_cmdshell functionality to upload a copy of itself (i.e. the payload) onto the database server. It does this by encoding the payload as a text file, echoing it up line by line, and unpacking it on the destination server using the debugger that ships with every Windows installation by default - debug.exe. Then, presuming it all worked, the reassembled worm is executed, and the spread continues. And that is all this proof of concept worm does - spread. All of this worked quite well live on stage, with the exploit to upload process taking about 2-3 minutes for my test network, enabling me to show a number of the worms executing in memory (as the worm doesn't have any facility to detect whether a machine is already infected). 

Yes, this particular worm does rely on an insecure configuration being present - namely that xp_cmdshell is executable. By default this is not available on SQL Server 2005, and won't be executable unless the website has been explicitly granted privileged access to the database server, so not all vulnerable sites will be exploited by the worm. However, there are plenty of sites that are configured insecurely, running previous versions of SQL Server (that are much easier to misconfigure), and let's not forget xp_cmdshell is also available and potentially exploitable on sites running a Sybase backend. After all, even if only one in ten sites are in this configuration, we will still have tens of thousands of vulnerable sites.

To wrap it all up, my Black Hat presentation demonstrated one particular way that things could get much worse with SQL Injection worms. Leveraging operating system access (if present) is only one potential way to wreak havoc on the Internet. There are lots of others - I for one will be very interested to see where those clever folks in China and Eastern Europe take the mass SQL Injection attacks in the near future.


SQL Injection Worms for Fun and Profit - slides and demo

Well, I'm offstage now having just presented my talk on "SQL Injection for Fun & Profit" at Blackhat in Las Vegas. One of the main aims of the talk was to provide more coverage on the mass SQL injection attacks that started earlier this year (and are still going on). The Internet Storm Center has some good discussion and coverage on this topic from earlier this year. The other aim was to point out some of the ways it could have, and probably will be in the near future, much much worse.

You can find a copy of the slides that were presented here, as well as a flash video of the demo that was done of the self replicating SQL Injection worm I wrote for this talk.