views:

648

answers:

4

Recently one of our client's websites fell prey to a SQL Injection attack due to a failure to sanitize query string parameters provided to the page. The vulnerable code has since been identified and is being corrected, but it got me wondering about some of the differences between how MySQL and SQL Server process multi-query strings.

The vulnerable code is used on several dozen websites, two of which are are running on SQL server while the rest are on MySQL. With this code we have never before suffered an injection attack (by the grace of God), but once we released the two websites that are running on SQL server (with the same code base) the website was quickly exploited. The method of injection was quite simple:

page.asp?param=1;delete from [some_table];

Like I said, the vulnerable code is shared across many websites, but if I try to execute the same type of injection on our MySQL sites ASP throws up a nice Server Error letting us know that there was an error in the query:

SELECT * FROM Table1 WHERE ID = 1;DELETE FROM TABLE1;

Testing this further I was able to verify that the MySQL ODBC 3.51 Driver will not allow two SQL queries to be executed in the same statement when an ADODB.Connection object calls Execute(""), while SQL Server Native Client (10.1) doesn't have any problem running two side-by-side queries. Is this in fact just a configuration of the provider that makes SQL server vulnerable in this fashion while MySQL is not, or does this stem from somewhere else?

+1  A: 

I think this happened because SQL Server supports MARS. As far as I understand MySQL does not support this. Mars is a good feature to speed up database queires so there are fewer round trips. you can put more then one query in a sql statement.

+4  A: 

The MySQL client API does not permit multi-queries by default. You have to enable this explicitly, or else you'll get errors when trying to execute a query like you saw. This is a good thing for reducing risk of SQL injection attacks.

The MySQL ODBC driver 3.51.18 (August 2007) added support for a connect option FLAG_MULTI_STATEMENTS to enable multi-statements. See http://dev.mysql.com/doc/refman/5.1/en/connector-odbc-configuration-connection-parameters.html.

See also http://bugs.mysql.com/bug.php?id=7445 for the history of this option.

Also see my answer to "Mysql change delimiter for better SQL INJECTION handling?" Note that multi-statements is only one way to get an SQL injection vulnerability. Disabling multi-statements is not a 100% proof against these flaws.

Bill Karwin
+1  A: 

It's a feature of SQL server that it supports multiple statements on a line. The solution is not so much to sanitize the input, as to use parameterized queries or stored procedures. If the query had been

SELECT * FROM Table1 WHERE ID = @id

Then passing "1;DELETE FROM TABLE1;" would have produced an error, since that's not a valid integer value.

John Saunders
Or casting it with cInt() or cLng()
AnonJr
+1  A: 

It is possible to exploit SQL injection without stacking queries. A very common method is to use a "Union Select" Here is a mysql injection exploit that I have written which uses a union select: http://milw0rm.com/exploits/3002 A union select allows you make a select statement within other statement: select 1 union select Password from mysql.user

You can also do a sub-select: insert into sometable (some,col,id) values ((select Password from mysql.user),1,1)-- )

Blind sql injection works on all platforms, however depending on the database the exploit will be different. This is a blind SQL Injection exploit for mysql:" milw0rm.com/exploits/4547

This is a very good paper on the topic of SQL Injection for MySQL: www.ngssoftware.com/papers/HackproofingMySQL.pdf

Rook