Tag: Input Validation

Let’s talk for a brief moment about some very basic things you can do to help make your web application more secure. If I were to pick three of the most common issues I still see while browsing the web, they would be:

  1. Error messages enabled
  2. Cross-Site Scripting (unescaped input)
  3. And yes, SQL Injection of some sort

The (un)fortunate thing is that most of these issues are easily solvable. A generic error page, as opposed to a stack trace or verbose error message, can usually be implemented with a couple configuration changes. Yet, I still see large websites that spit out stack traces and code when an error occurs.

Cross-Site Scripting is another issue that still plagues us. Testing for it is simple – just enter something like test"> into an input field and if the resulting page displays that in raw HTML, chances are you have a problem. Every language has some form of HTML-escaping function and, if possible, it’s good to turn this on by default. This will be the case in Rails 3.0, thankfully.

Finally, I still see traces of SQL Injection on an all-too regular basis. Identified by the oh-so-dangerous single tick mark – ‘ – and typically resulting in an error page that shouldn’t be showing up anyway if the first issue were address. That said, even if the error is obscured, it’s still possible to retrieve data using a technique called Blind SQL Injection. Any data getting sent to an SQL server should also be properly escaped or sent through stored procedures depending on the backend technology. Think SQL Injection isn’t a problem? Talk to RockYou, whose database of 32 million usernames and passwords was compromised because of it.

Address those three things and (sadly) you’ll be ahead of the game.

Dove-tailing off my previous post about the Basics of Analyzing Web Site Security, there are some very common places in web applications that I come across typical issues. These are the places I will look at first on a web app to get a general idea of the rest of the site security.

  • Search Forms

    Search forms generally re-display the search term entered by the user. These terms are quite frequently not properly encoded, either, leading to Cross-Site Scripting (XSS) attacks.

  • Jobs and Events

    Jobs and Events pages frequently utilize a database behind the scenes to manage job postings and event listings. Further, they’re usually pretty easy to check as they have the job or event id in the URL for page rank, etc. I’ll commonly look for these for easy injection vectors.

  • Cookies

    Utilizing the fantastic Web Dev extension, I’ll take a quick look at the cookies. If I see anything more than a session ID, I’ll start modifying and manipulating the cookies to verify that server-side checks are in place. Cookies can also frequently lead to XSS.

  • Hidden Form Fields

    If there’s a contact page with a form, the first thing I do is look for hidden form fields to see what parameters the web developers might have thought that a user wouldn’t see by putting them in a “hidden” field. I’ve come across everything from spam gateways to arbitrary file access due to simple issues like this.

  • Typical Directory Structures

    Finally, I’ll commonly poke around in typical directory structures to see if I get lucky. Things like /admin/, /logs/, and /config/, among others, often are not intended for public consumption or linked to, but are present on the site.

There you go – those are generally the first places I look if I need to take a quick look at a web site. Beyond that, I start digging into more complex input locations within the application, logic happening behind the scenes, and potential user authorization issues.

A quick note for startups (or anybody) that may be deploying on Google App Engine:

As App Engine does not automatically escape output, you need to do this yourself.

As an example, here’s a very simple snippet:
Welcome, {{ firstname }}!

If “firstname” is not properly sanitized when stored in the database or escaped on output, I could easily make my first name the following:
damon<script>alert('hi!')</script>

And then we would have stored JavaScript code execution, aka Cross-Site Scripting, as the <script> tag would get interpreted by the browser when echoed out.

The solution?

Simple, just |escape your output when coding in Google App Engine:
Welcome, {{ firstname|escape }}!

You can also sanitize data prior to storing it in the database, but as an additional layer it’s good to escape it on output as well.

I’m not sure if this is a derivative of the fact that GAE utilizes Django 0.9.7, but I guess we’ll see when they upgrade to Django 1.0 as it autoescapes all output by default (thank you, Django!).