Mass SQL Injection attack

I’ve been reading up on the mass SQL injection attack launched against servers running IIS and MS SQL Server last week. That article is a bit out of date, as the problem turned out not to be a security hole in IIS but rather security holes in the Web applications themselves. The script that compromised the sites was clever enough to probe for forms that didn’t prevent SQL injection, and injected SQL specifically designed to work with MS SQL.

The article linked to also says that the attacks were first reported on April 17, but I found an incident report from April 13 describing the attack.

The end goal of these attacks is to infect client PCs with malware. The attacks appends database fields with markup that includes JavaScript from a third party domain, and then when any page that displays the field is viewed by a user, the JavaScript is downloaded and executed, any unpatched client PCs will be infected by the malware.

IIS.net has a post that explains exactly how the attack works. The script finds a form on the site that does not properly escape user input and injects SQL that finds all of the text columns in the database and appends the HTML that loads the malware to each of them. You can read more about it here. The main innovation in this attack is the cleverly written SQL injected that’s ejected. A similar attack could be launched against any application that does not protect against SQL injection. MySQL is somewhat protected in that most sites are running MySQL 4.x, which doesn’t provide support for stored procedures.

There are several takeaways from these attacks:

  • The only common vector in these attacks is MS SQL Server. Any application that does not prevent SQL injection could be the vector. So a Java application running on Solaris or a PHP application running on Linux could also be affected if they store their data in MS SQL.
  • You should minimize the privileges granted to the database user that the Web application uses. If your application uses the “root” or “sa” account, give up now. Just using grant all is the wrong idea for a production account. Figure out which privileges the account must have for your application to work properly, and grant only those.
  • If you’re writing Web applications and you’re not sanitizing user input, you need to go back to the drawing board. I’m beginning to think that languages like PHP and libraries like J2EE should sanitize all input by default and force programmers to go out of their way to access the original input. In other words, in PHP, $_REQUEST should contain escaped data by default. Many programmers don’t know what they’re doing, and in the case of attacks like this one, it’s end users who get hurt, not just the people who wrote the compromised application.
  • Just visiting Web sites you trust isn’t enough to keep you safe. Keeping your PC patched up and running security software is essential to preventing your PC from being compromised. It just keeps getting more dangerous.
  • Replication and backup are two different things. When this attack was run, all of the bad information inserted by the attack was almost certainly copied to the replication server immediately. Taking a snapshot of your data frequently is perhaps more important than replication. (Those of us who have run an errant update or delete statement and wiped out a ton of data, only to see the results replicated immediately already know about the dangers of relying on replication.)

4 thoughts on “Mass SQL Injection attack

  1. Sanitizing user input, while essential, is the incorrect way to avoid SQL injection in my opinion. SQL injection is caused by gluing strings together to create SQL queries. In this day and age there is absolutely no excuse for doing this – you should be using a database library that takes a SQL statement with placeholders and the values for those placeholders separately (some environments call these prepared statements, but you can simulate them with anything just by writing a simple function).

    PHP originally escaped input by default, and it took YEARS for the community to recover from the mess that it caused!

  2. Simon: I agree completely about using placeholders but I think the problem with PHP was that it wasn’t consistent and a lot of code was written which made dangerous assumptions about the magic quotes behavior. It wouldn’t have been perfect but the web would be safer if PHP had default escaping for input and output.

    If I could wave a magic wand for PHP6 I’d make a few backwards-incompatible changes:

    • Input data would be tainted and functions which aren’t marked as taint-safe would throw exceptions.
    • Output data would be HTML-escaped by default and the raw-output function would be have a discomforting name like insecure_output.
    • PDO and all other database classes would have their syntax improved to make parameters available without prepared statement overhead: it’s pretty easy to subclass PDO for this but it should be standard.
  3. should sanitize all input by default and force programmers to go out of their way to access the original input

    sanitize it for what? For output to the web? for usage in sql queries? If the latter, for which databases, and which charactersets should be assumed? My point is there is too many variables to make it automatic.

    @Simon:

    (some environments call these prepared statements, but you can simulate them with anything just by writing a simple function).

    and please, please, people who do that make sure that the function does more than simply glue string togethers without any further checks or escaping, otherwise you’ve only obfuscated the problem in the code, but exploiting is as easy as it was before. (Yes, I’ve seen it often enough…)

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>