Using an HttpModule to Clean Up Form and QueryString Input

"A potentially dangerous Request.Form value was detected from the client"

To avoid XSS attacks, ASP.NET's default behaviour is to throw a lovely yellow screen of death with that message. It's nice to be protected, but sometimes you want to accept potentially dangerous input, or maybe you just don't want to have that error splashed across the screen. The latter was the case for me recently, but I wasn't completely happy with the standard solution.

The first part of the solution is telling ASP.NET not to validate the request. For both web forms and MVC, you add this to system.web in web.config:

<httpRuntime requestValidationMode="2.0"/>

...then with web forms you disable validation by adding validateRequest="false" to the Page directive, and with MVC a [ValidateInput(false)] attribute to the appropriate controller or action.

Being a fan of prevention rather than cure, and liking aspect-oriented solutions to problems, I figured it'd be nicer to screen input before it gets to my MVC application than stick attributes all over the place. My old friend the IHttpModule is perfect for this; it centralises input clean up by plugging into the request pipeline, and can swapped for a different module later if the screening rules change. My application just receives screened input without knowing how, where or why the screening was done.

So this is what my colleague Andrew Beaton and I came up with - an IHttpModule which removes all HTML tags from the form and query string, then HTML-encodes whatever's left. Add it to the httpModules section of the system.web element and the modules section of the system.webServer element in web.config, and voila!

using System;
using System.Collections.Specialized;
using System.Reflection;
using System.Text.RegularExpressions;
using System.Web;

public class InputScreeningModule : IHttpModule
{
    private static readonly Regex _inputCleaner = new Regex("<[^>]+>", RegexOptions.Compiled);

    public void Init(HttpApplication context)
    {
        context.BeginRequest += CleanUpInput;
    }

    public void Dispose()
    {
    }

    private static void CleanUpInput(object sender, EventArgs e)
    {
        HttpRequest request = ((HttpApplication)sender).Request;

        if (request.QueryString.Count > 0)
        {
            CleanUpCollection(request.QueryString);
        }

        if (request.HttpMethod == "POST")
        {
            if (request.Form.Count > 0)
            {
                CleanUpCollection(request.Form);
            }
        }
    }

    private static void CleanUpCollection(NameValueCollection collection)
    {
        // Both the form and query string collections are read-only by 
        // default, so use Reflection to make them writable:
        PropertyInfo readonlyProperty = collection.GetType()
            .GetProperty("IsReadOnly", BindingFlags.Instance | BindingFlags.NonPublic);

        readonlyProperty.SetValue(collection, false, null);

        for (int i = 0; i < collection.Count; i++)
        {
            if (string.IsNullOrWhiteSpace(collection[i]))
            {
                continue;
            }

            collection[collection.Keys[i]] =
                HttpUtility.HtmlEncode(_inputCleaner.Replace(collection[i], string.Empty));
        }

        readonlyProperty.SetValue(collection, true, null);
    }
}

Print | posted @ Friday, April 22, 2011 2:10 PM

Comments on this entry:

Gravatar # re: Using an HttpModule to Clean Up Form and QueryString Input
by Samrat Bhattacharjee at 2/4/2014 4:08 PM

Hi there,
this is a wonderful post. I was wondering if there is something which could be used to trim a parameter value which has been added by a user after the forms values.
Example: For my page Test.aspx, there is a text box. When the form parameter gets posted, it comes like test. If someone injects another value at last for the same text box in the posted request, the value would come like 'Test,MallicousValue'. I want to get rid of this injected value. In short, want to get rid of HTTP Parameter Pollution. Please help.
Gravatar # re: Using an HttpModule to Clean Up Form and QueryString Input
by Steve Wilkes at 2/8/2014 12:24 PM

Hi,
Glad you've found it useful :) If someone decides to post junk to your site, there's not really anything you can do to identify which bits they've sent are junk, and which bits aren't. You could adapt the above HttpModule to add a parameter to requests where HTML tags have been removed or where there are multiple values for the same form key, but you'd have to review flagged requests manually to see if you thought they really were junk.
Gravatar # re: Using an HttpModule to Clean Up Form and QueryString Input
by mahesh vaghasiya at 11/24/2014 12:53 PM

First of all thank your such informative article. Now talking about issue i'm facing. Normally it works fine for me but it don't work as expected when Ajax calls come into the picture. I can read the querystring colletion of ajax request but some how its not upating the collection value. Can you please help me with that ?
Thanks in advance
Mahesh
Gravatar # re: Using an HttpModule to Clean Up Form and QueryString Input
by Steve Wilkes at 11/24/2014 6:25 PM

Hmm, that's odd - the method of making the request shouldn't have any effect on the way you work with the objects on the server side...
Gravatar # re: Using an HttpModule to Clean Up Form and QueryString Input
by bez at 12/12/2016 7:57 PM

this is a great post, thank you.

is there anyway to filter asp.net control types? like textboxes.
Post A Comment
Title:
Name:
Email:
Comment:
Verification: