Mark Needham

Thoughts on Software Development

ASP.NET MVC: Preventing XSS attacks

with 12 comments

XSS(Cross site scripting) attacks on websites seem to be quite popular these days but luckily if you’re working with the ASP.NET MVC framework Steve Sanderson has written a great post on how to protect yourself from this.

The solution Steve details works the opposite way to other solutions I have heard for this problem – we assume that everything that goes to the browser needs to be HTML encoded unless otherwise stated.

The benefit of this approach is that when we add new things to our page in the future we don’t need to worry that we might have inadvertently reintroduced a security problem.

Excluding aspx code from being encoded

After setting up the encoding we came up against the problem of how to exclude HTML that we are generating from our aspx templates that we don’t want HTML encoded.

This was a particular problem with our use of the HtmlHelper and UrlHelper provided with the framework.

Since the majority of the methods we use are extension methods on these classes we didn’t find it that easy to work out how to proxy those calls (we couldn’t just override the methods since they aren’t actually on HtmlHelper!) to our own RawHtmlHelper which could cast the result to RawHtml and therefore allow it to be rendered by the page.

The aim was to minimise the amount of things that we had to change. The worst case solution would be to have to go through all our aspx files and change every call to a Helper method to a new encoded version of the same method.

Luckily the new keyword comes to the rescue and allows us to hack around the problem.

We hooked into the page lifecycle to create a new version of the Html property which returned our RawHtmlHelper.

public class BaseViewPage<TModel> : ViewPage<TModel> where TModel = class
{
	public override void InitHelpers() 
	{
		base.Html = new RawHtmlHelper(..);
		base.Url = new RawUrlHelper(...);
	}
 
	public new RawHtmlHelper Html 
	{
		get { return (RawHtmlHelper) base.Html; }
	}
}
public class RawHtmlHelper : HtmlHelper 
{
	public RawHtml TextBox(string name, object value)
	{
		return (RawHtml) ((HtmlHelper)this).TextBox(name, value);
	}
}

In our aspx page we don’t need to make any changes to our code in order for it to now use the RawHtmlHelper method instead of the HtmlHelper method.

<%= Html.TextBox("name", "value") %>

The only other change was to make each of our aspx code behind classes inherit from BaseViewPage so that they receive the new Html property.

Overall

There is way too much casting for my liking in this solution but I’m not sure if a better solution exists other than creating our own version of the helper methods named ‘RawTextBox’, ‘RawRadioButton’ and so on.

The amount of work with that approach would be almost the same except if we have used the original HtmlHelper anywhere then we need to go and change all those too – exactly the problem we were trying to solve with the above solution.

Written by Mark Needham

February 12th, 2009 at 10:47 pm

Posted in .NET

Tagged with ,

  • http://blog.codeville.net Steve Sanderson

    Hi Mark

    The other way to intercept all the Html.* calls is to create your own set of wrapper methods in another namespace/assembly, and then to edit your web.config file. Under pages/namespaces, remove the reference to System.Web.Mvc.Html, and reference your wrapper methods’ namespace instead. That will change which methods all your views call without having to touch any of the views.

    You would still have to create wrappers for all the Html.* helpers, which is a long and boring job. I was thinking of making a little tool that reflects over System.Web.Mvc.dll and generates C# code that wraps any string-emitting extension method on HtmlHelper. Then we get the benefits without the work, and can easily update the wrappers if Microsoft changes their code.

    What do you think?

  • http://www.markhneedham.com Mark Needham

    Ah neat, didn’t realise we had the ability to do that from the web.config – sounds like a pretty cool approach.

    I like the idea of the code-gen – not only is it long and boring to manually write them but it’s quite difficult to tell whether or not you’ve covered everything since they’re all extension methods rather than being overridable methods on a class for example.

  • Pingback: Dew Drop - February 12, 2009 | Alvin Ashcraft's Morning Dew

  • http://falkayn.blogspot.com Angus McDonald

    Mark,

    I keep wondering if there is some way to use the new XElement object from System.XML.Linq (currently only in VB.NET) to give us helpers that create strongly typed XHTML.

    We are doing something at the moment with our CMS templates in ASP.NET webforms that will use this approach, I’m pretty sure we could come up with something for ASP.NET MVC too – but that still leaves the problem of how to reference them. My gut feel is the HtmlHelper methods will end up being left behind as ASP.NET MVC matures anyway …

    Angus/Falkayn

  • Pingback: Encoding user entered data at Mark Needham

  • Pingback: Mark Needham: Encoding user entered data | Enterprise Java

  • Pingback: Mark Needham: Encoding user entered data | Enterprise Java

  • Pingback: ASP.NET MVC Archived Blog Posts, Page 1

  • Pingback: C#: Extensions methods != Open classes at Mark Needham

  • Pingback: ASP.NET MVC: Pre-compiling views when using SafeEncodingCSharpCodeProvider at Mark Needham

  • Pingback: HTML encoding/escaping with StringTemplate and Spring MVC at Mark Needham

  • Sda

    document.cookies = null