Monday, April 4, 2011

MVC3 XSS Protection

I am focusing quite a bit on security in my current project, and so I decided to spend a little time working with the default xss projection in MVC3.

On the surface, it seems as if the default protection against XSS is quite robust in MVC3.  I started off by creating a simple form that took a message input.  This message was added to the ViewData and passed back to another view where it was displayed.  I tried the most basic of XSS attacks at got a nice little error message saying

Server Error in '/' Application.

A potentially dangerous Request.Form value was detected from the client (message="<script>alert("hello...")



Pretty good eh?  Now of course you would want to have a custom error page all set up, but this is quite nice protection to have right out of the box.  MVC3 includes a ValidatinInputAttribute which you can set to false to disable the input validation.  You can set this attribute only on the method or class level, so make sure you know what you are doing.


[ValidateInput(false)]
        public ActionResult Display(string message)
        {
            .....
        }

Adding this attribute on to my method got rid of the nasty error message received before.  I proceeded to add this message directly to the ViewData and outputted it directly on the screen.  To my amazement, it printed the input with the proper escaping!  WOW!  Microsoft finally got something right.  I started to ask myself the question, what if I actually wanted to display HTML on the screen, say for example, rich text input.  It turns out that you have to do a combination of the following.

In you model input, you have to use the AllowHtmlAttribute.  This attribute will ensure that you won't get a nasty message when input validation occurs without having to disable all field validation for that method or class.  This also allows you to still do some sanity checks on the data you are receiving.  In order to get this html to display properly, you have to use the Html.Raw method to output the data.


public class DisplayModel
    {
        [AllowHtml]
        public string Message { get; set; }
    }

Hello, @Html.Raw(Model.Message)

It is good to see that it MVC3 is trying to do protection by default.

Sunday, April 3, 2011

Book Review: Don't Make Me Think 2nd Edition

On my current project, I have been forced to wear many hats. One of those hats is that of lead designer. Sure, putting divs on the page is easy. But how do you actually make something look good? How do you make it usable? How do you design a user experience?

I would call this book a good intro to the world of design. The author sets the expectations of this book at the beginning. It is not an all inclusive book (I don't think one is in existence in the world of design). It is a short primer to get the reader up to speed on some of the biggest design flaws. As the author quotes in his first few pages,
"You don't need to know everything. As with any field, there is a lot that you could learn about usability. But unless you are a usability professional, there is a limit to how much is useful to learn."

I would say that this book is a good intro.  It will give you the skills necessary to take a critical look at your websites design.  It will give you ideas to tweak the design.  It will give you the skills (say if you are a hireing manager) to take a good look at work being present to you.  Most of all, it will force you to think objectively about web usability and design so that you can make better decisions.

I recommend this book to anyone wanting to get a start in web usability.

Friday, April 1, 2011

Validation in MVC3: An Example

[[Update]]
I had to add a null check to my custom validator. You can find out more information in this post.


Validation is a big aspect of security in web applications.  I can't count how many times I have seen blatant ignorance of this simple fact.  Just recently I was browsing an application built by a 3rd party (who probably charged an arm and a leg for their product).  It took about 1 minute to find a huge sql injection flaw in their application.  One of the get parameters that was being passed into their application was being put directly into a database call.  Worse than this, I got an error message telling me that my sql statement had not worked.  This error message told me the following pieces of information.

1)  It returned the actual sql call
2)  It told me the database that it was using along with the version
3)  It told me the web framework that was being used.

The security industry has spent a lot of time trying to educate developers on best practices for building secure applications.  It is unfortunate to see people still do this kinda of sloppy work.  I guess there is a reason why injection attacks are still on the OWASP top 10 list.

In this article I am going to go over making a custom user name validation attribute.

User names are part of most web applications these days.  I want you to note that there are other perfectly valid ways to do what I am doing here.  I have chosen to make a custom attribute because I assume that I will be using this user name validation in other parts of my application.  Following the DRY principals, it is best to create a custom attribute and go from there.


using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using System.ComponentModel.DataAnnotations;
using System.Text.RegularExpressions;

namespace MvcApplication2.Attributes
{
    public class UserNameAttribute : ValidationAttribute 
    {
        private const string WHITE_LIST_REGEX = @"^[a-zA-Z0-9]*$";
        private const int MIN_LENGTH = 5;
        private const int MAX_LENGTH = 25;

        public UserNameAttribute()
        {
            // Set a default error message that does not give any information away
            // We don't want an attacker to gain information as to how we build our user names
            // This is a good security measure in cases when the site is not open to the public
            // registration.
            ErrorMessage = "Please enter a valid user name.";
        }

        public override bool IsValid(object value)
        {
            if (value == null)
            {
               return false;
            }
            // Sanity check 1:  Is it a string?
            if (!(value is string))
            {
                return false;
            }

            var userName = value as string;

            // Sanity check 2:  Is it within acceptible norms?
            if (userName.Length < MIN_LENGTH ||
                userName.Length > MAX_LENGTH)
            {
                return false;
            }

            // White List Check
            if (Regex.IsMatch(userName, WHITE_LIST_REGEX))
            {
                return true;
            }

            return false;
        }
    }
}

In order to do proper input validation you have to follow the following rules.

1)  Input is always invalid by default
2)  Input should conform to a known whitelist
3)  Sanity checks should be done to ensure that you only operate on plausible values
4)  Information leakage should be avoided on unauthorized pages

As you can see from the above code, I return false by default.  I use a generic, standard error message to combat (4).  Building white lists are easy with the use of regular expressions.  You can validate almost any type of input.  In the case above, I use a business rule defined in my application to build my white list.  I know that my user names only have letters and numbers.  I can thus enforce this in a white list as shown in the code.  The last check is the one that tests for min and max length.  Although I should enforce this on the form, we all know that the any client side checking can be disabled very easily.  It is easy to build in a check here to make sure that the length of the user name provided meets known business rules.  I could have just as easily incorporated this into the same regular expression that did the character white list.  It would look something like

string fullRegex = @"^[a-zA-Z0-9]{5,15}$";

In this case, my LoginController contains a Login action that takes a LoginModel model.  It is easy to add the above attribute in the LoginModel to provide the necessary protection.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.ComponentModel.DataAnnotations;
using MvcApplication2.Attributes;

namespace MvcApplication2.Models
{
    public class LoginModel
    {
        [Required]
        [UserName]
        public string UserName { get; set; }
    }
}

Of course, security in layers is the best protection to use.  This example above is just one of the layers that you can use to protect your application.  Now that the input has passed some validation, you can use the user name supplied and check against your database to see if the user actually exists.

Happy validating!