Anatomy of a SQL Injection Incident

A number of people are reporting that 10K+ websites have been hacked via a SQL injection attack that injected a link to a malicious .js file into text fields in their database.  For example, here's Avert Labs report.

The reports that I've seen talk about how the .js file tries to compromise clients that connect to the defaced web servers; however, they don't discuss the really interesting part.  How did the servers get hacked in the first place? 

Whenever I see a large number of hosts compromised in the same way, my initial assumption is that they all share a piece of vulnerable code.  If this was the case, I thought that it would be in everybody's interest to figure out what that shared code was and take appropriate action.

Since the CSS Security team here at Microsoft worked with several of these incidents, I was able to look at multiple sets of data and the work that my colleagues had already done.  The first thing I noticed was that the attacks looked, with a few exceptions, identical.  They shared several things in common:

  • Two initial query strings that do some basic injection, apparently as a test.
  • One or more additional queries, specifically to do IS_SRVROLEMEMBER() happen in some cases.
  • Two final queries that DECLARE a variable that CASTs a large hex value into NVARCHAR and then EXEC()'s that string.  The string contains a script to append the link to the .js file onto every string-type column in every table in the database.
  • All of these happen within a very short period of time.  The only lag seems to be the time it takes the final two queries to execute.  (In the case with the largest database, the last query actually failed with a timeout.  I guess that's not surprising since it's essentially doing a find-and-replace on the entire database table.)

The last item makes me think that this is an automated process of some sort, particularly since the user-agent string for the last two queries is different from the user-agent string for the preceding ones.

This is where it gets interesting, though.  In comparing the pages that were compromised in different incidents, I realized that, while they're all vulnerable to SQL injection, they don't appear to share any common code. 

My next question, then, was how did the attacker select these sites?  Given that the whole attack took a very short period of time and the attacker only touched a single ASP page on the server, it was pretty clear that they had some reason to believe that page was vulnerable prior to connecting to the site.  It's possible that they had previously scanned the site but I didn't find any indication that this was true.

The other possibility that occurred to me was that the attacker was using a generalized approach to search Google for vulnerable sites.  As I was thinking this through, I found that I wasn't the first person to have thought about it:

How Prevalent Are SQL Injection Vulnerabilities 

Guard Against SQL Injection Attacks 

SQL Injection Is Surprisingly Easy

So, there you have it -- automated SQL injection attacks in a nutshell.  Next week, I'll try to find some time to go into some of the details and brainstorm on how incident responders can get to the root of SQL injection attacks.

(I should note that many brilliant people on my team provided information and analysis into how the incidents happened.)

(Part 2 is here.)