Two Steps Forward to More Secure Applications

Comments 0

Share to social media

Introduction

The web has woven itself into nearly every aspect of your life.  You do your banking online, you track your investments online, and you keep in touch with friends and family online.  Every day you trust your most important financial information and most intimate personal communications to millions of lines of code written by programmers just like you.

If you’re like most programmers that last sentence is enough to make you leap out of your seat, your hair stand on end, and seriously question ever buying anything online again.  Why?  Well, because despite the fact that some of the most important parts of our society have moved completely online, only a handful of programmers have even a passing familiarity with basic security.

Earlier this year the SANS Institute released its 2010 edition of the Top 25 Most Dangerous Software Errors…sort of a ‘Greatest Hits’ of epic failures in software security.  What’s so disturbing about this list is that even though it’s updated every year, the vast majority of errors can easily be avoided with just a bit of forethought.  Many developers, including myself, often view software security as a highly advanced black art that is understood only by those few security professionals who have dedicated their career to demystifying its muddy waters.  While I am sure that there are only a handful of professionals on this earth who can truly understand the arcane differences between AES encryption and DES encryption, would it surprise you to know that the #11 programming error of 2010 was “Use of Hard-Coded Credentials“? 

What was that?  People are still hard-coding unencrypted usernames and passwords directly in their code, or even worse, in configuration files?  That’s right, and enough people are doing it that it was the 11th highest ranking programming error by the SANS Institute in 2010.  Do you still think that security is a black art reserved for an elite few?

In addition to the fact that many of the most common security exploits can be easily avoided, many highly dangerous exploits from days gone by have been greatly reduced if not prevented completely by the advent of managed runtimes such as .NET.  For example, Buffer Overflows and Integer Wraparounds, once the bane of security experts everywhere, are either prevented by the .NET runtime or their effects are strongly reduced.

In this article, we’ll discuss two simple steps that you can take to significantly improve the security of your software.  We’ll learn about a few common exploits in the wild today, and how we can defend against them using some basic coding techniques.

SQL Injection Attack

Whether you write applications fo­­r the web, desktop, or mobile devices…if your application talks to a database then you’re at risk for this attack.

A SQL Injection Attack consists of a user passing SQL code into your application, which it naively processes, resulting in the user gaining unauthorized access to pieces of your data or completely destroying the data in your database.

Most often this occurs when a developer constructs a SQL query by simply concatenating unchecked user input with strings of pre-written SQL, like in the example below…

Assuming your user is searching for ‘Joseph Wilson’then web entry form might look like this…

1133-Farrel1.jpg

 …and the resulting SQL would look as follows…

As long as your users are trustworthy people, which we all hope they are, the code above can exist happily for a quite some time with no concerns.  However, what happens when you can encounter a user with less than altruistic intentions?  Imagine that your user has passed in the text “Fake’ OR ‘1’=’1”.  The resulting SQL would be….

1133-Farrel2.jpg

What’s with the Quotes?

There’s another interesting point about the SQL above.  Note that the user has added uneven quotes around the ‘1’=1.  This allows the attacker to smoothly insert his own SQL directly into the string concatenation without causing a syntax error.  As we’ll see later, a clever attacker can also use this technique to append entire SQL statements on the end of your query.

In this case the fact that there is no user in your user’s table with the last name of ‘Fake’ is irrelevant, the fact that the attacker has OR’d ‘Fake’ with the expression of ‘1=1–an expression which will always be true–has ensured that the WHERE clause will return true for each row in the table, resulting in every row in the table being returned.  Hope you’re hashing your passwords!

What’s that you say?  You never store your passwords in clear text and even if you did you wouldn’t bind the results directly to a grid?  Don’t get too comfortable yet, maybe our attacker will just decide to add himself to the database then.

By inserting ; the attacker can cause their own SQL statement to be executed immediately after yours.  Also, note the – – appended to the end.  This comment disables the trailing quote that would normally be inserted after the attacker’s input and prevents a syntax error.

Or, maybe your user isn’t even interested in gaining access to your system.  Maybe, instead, all he’s interested in is taking it down.

The statement above will definitely take your application offline for a few hours and will give you a great chance to test out that backup strategy you’re always thinking about implementing.

So how do you defend against this threat?  Actually, it’s quite simple.  By parameterizing your SQL queries or by using Stored Procedures, you can eliminate the possibility of an attacker passing malicious SQL into your application.

Let’s consider the SQL query from above.

What makes this query dangerous it that we allow the user to pass any value for LastName without first checking its validity.  However, by forcing this value into a parameter, we can trust our database engine to do a large amount of validation for us.

Here is the ADO.NET code responsible for executing the query above.

We can also achieve the same effect by using parameterized stored procedures.

And here is the ADO.NET code responsible for executing the stored procedure above.

Both of these solutions allow us to leverage the power of the platform to prevent malicious code from being passed along to our database. The advantage of the solution that uses stored procedures is that you can then deny access to the base tables to the login used by the website whist allowing access to the stored procedure, so that, even if the attacker somehow gained access, there would be nothing further they could do. They would be unable to bypass the defined interface.  Another solution worth mentioning is the use of an OR/M such as NHibernate or Linq to SQL.  Since an OR/M generates most SQL automatically for the developer using parameterized SQL the opportunity for developer error is greatly reduced.

Cross-Site Scripting Attack

If you’ve done anything with the web in the past few years, the odds are that you’ve come up against this attack.  In fact, as of this year it has been elevated to the coveted Number 1 spot of the Top 25 Most Dangerous Software Errors report listed above.  Well…coveted if you’re a security bug, that is.

Cross-Site Scripting, abbreviated as XSS, is similar to the SQL Injection attack listed above in the sense that it often occurs by blindly trusting malicious input from your users.  However, unlike SQL Injection which is often used to gain access to, or possibly damage, the data in your database XSS is used to trick your website into serving harmful script data to your users.

An attacker can mount an XSS attack on your website when you allow users to input un-sanitized text directly into your web page that you later display.  For example, imagine that you have created a site that allows users to post comments about recent updates.  This type of freeform text entry is the perfect opportunity for an attacker to enter an attack script instead of a review.  The issue arises the next time an unsuspecting visitor browses that particular product on your site.  As your application retrieves all associated comments for a given product it will encounter the malicious scripting code and serve it to your user’s browser just as it would the other text in the database.  The browser, which doesn’t understand the context of a comment versus regular script code, will execute the script code as soon as it encounters it.

Let’s take a look at an example.

In the web page below, users are invited leave a review for the website in a free form text box.  This is the perfect opportunity for some of your less scrupulous users to mount a XSS attack against your site!

If you’re simply accepting your users’ reviews as trusted data then you could be leaving yourself open to just such an attack.

The next time a user visits your site they’ll be the victim of the unscrupulous users attack.

How do you prevent such an atrocity from occurring?  By simply encoding your user’s input using the Microsoft AntiXSS Library.  The Microsoft AntiXSS Library compares your user’s input to a whitelist of known safe characters encoding anything that doesn’t appear on that whitelist.  This encoding neutralizes any harmful input that a user may throw at you.

It’s also worth mentioning that the ASP.NET platform also includes more out-of-the-box protection to deal with XSS attacks.  Every ASP.NET page contains a page-level directive called ValidateRequest which scans user input for known attack characters and rejects any post which contains them.  In fact, the examples above will only work if ValidateRequest has been turned off on the page (it’s on by default).  So why are additional libraries necessary if this page directive is in place?  Primarily it’s because the Anti-XSS library, and even HtmlEncode(), provide a much more in-depth defense than the ValidateRequest page directive does.  In addition, since ValidateRequest prevents a post of any data containing blacklisted input it’s not unheard of for ValidateRequest to be turned off for certain pages where blacklisted characters are expected.  In these cases it is imperative to allow field-level validation using one of the techniques that I’ve mentioned..

Conclusion

SQL Injection and XSS are the two of the most common attacks threatening Internet-based applications today.  However, by following the simple steps mentioned above, you can dramatically reduce your application’s exposure to malicious intent; This way you’ll  make it safer for both your users and your stakeholders.

Article tags

Load comments

About the author

Jeremy Jarrell

See Profile

Jeremy Jarrell is a software developer specializing in desktop application development with the .NET platform. He is heavily involved in the .NET developer community both as a regular contributor to open source and as a frequent presenter at user groups throughout both the Pittsburgh and Philadelphia areas. His interests include client application technologies, developer productivity, and leading edge developer techniques such as test-driven development. He can be reached through his website at www.JeremyJarrell.org.

Jeremy Jarrell's contributions