Life often presents us with common problems or challenges that require solving. Many problems have many solutions. Some solutions are good; most solutions are bad.

A specific problem developers commonly experience when working with ASP.NET technologies is the age old HttpRequestValidationException problem. Like so many other problems in life, there are many solutions to this one, most of them bad.

A quick Google search will yield many posts that proclaim (many times with a feeling of authority) that the solution here is to disable this pesky security feature. Some tell you to disable it in your web.config, while others indicate that it can be done on the page-level as well by setting validateRequest to false in either place. This security feature exists for a reason, and it is to protect you and your web application from injection (and other kinds of) attacks.

You should embrace this free security feature and make use of it; it is unwise to simply disable it because it is annoying. You can either change your code so that you never enter into a situation where such an exception is raised, or you can keep your code the way it is and take more sensible action.

I. Why Does This Happen?

Referring to the MSDN page on HttpRequestValidationException, we can clearly see that this exception gets raised when a client submits a request containing potentially malicious data. Humorously enough, the first suggestion on the MSDN page is to disable the feature! I wonder where the frequent bad behavior of recommending to disable this feature originates from….

What does “malicious data” entail? It can mean a whole lot of things, I’m sure; most commonly, however when discussing ASP.NET applications, it means HTML elements supplied outside of the original markup. Probably the most common reason as to why this exceptions happens in the wild is due to HTML that isn’t recognized by the server.

How simple the solution on depends on the situation. At times, we might find ourselves working with externally defined HTML that we have no intention of rendering. Other times, however, we may actually WANT to render the externally supplied HTML.

Encoding the HTML before displaying it is a good start. Actually, I believe that used to be all you needed to do (not sure). Starting with .NET 4.0, however, any HTML supplied by the code-behind is going to throw this exception, at least in my experience. Let’s look at a typical example.

Let’s say you have a column of cells that represent the status of an entity. The statuses that are available to use are defined by users or an administrator, and employ HTML in order to style their appearance. So, in order to get that stuff on the page, you load the preference setting (from a database or whatever) and set the cell’s InnerHTML to the user defined HTML.

Now, let’s say the user submits the form. Even though they didn’t directly enter the HTML that makes up the status cells, a request validation exception will occur because the user is submitting a form containing HTML which did not originate from the page’s original markup.

This feature is essentially impossible to provide with request validation turned on.

II. What a Pain, So How Do I Disable This?

No, no, we don’t want to disable it! The fact that you are getting these exceptions means there’s a very real chance that a wide open attack vector exists in your application. You have two options:

  1. Disable the functionality that is allowing for users to direct or indirectly supply some custom HTML completely
  2. Sanitize the input You should first think very hard if such functionality is required. Many times, you may find that there is no good reason as to why you should allow for such a feature. If possible, this will always be the best solution.

Sometimes though, that doesn’t matter one bit. For example, it may be a business requirement. No question there then, you need to make some magic happen.

That leads us to #2, which is the proper thing to do in this case. Sanitize the input. Ok. Let’s say we have a method named “Sanitize”, which takes a string. You run the custom HTML through it, scrub it of all its badness, and then use the result. Submit the form.

You’re still going to get the exception. ASP.NET has no idea if input has been sanitized or not; potentially malicious data is potentially malicious data.

So, is this when you should disable validation for the specific page? Nope, instead, write your own request validator.

III. Custom Validator

And this is the main point of the article.

If you deem a feature where the user can input potentially malicious data is vital, then the proper way of proceeding is to implement your own request validator. This is done by creating a new class that inherits from RequestValidator and registering that class in the web.config so it is used.

So, what’s supposed to go in this validator? I suppose it’s a bit much to assume one can just wave their hand around in a “validator-like” fashion and expect results without knowing what it is they’re supposed to do.

There are many things one can do, and there are many levels of robustness to be had here. I’m going to present you with an example custom validator; I’ll leave it up to you to decide how it can be improved, as it is quite minimal.

The custom validator I’ll be showing here consists of a single method, IsValidRequestString. This is the heart of the show here — this is where all the validation goes down. There’s plenty you can do here, however I’m only doing one thing, I’m looking for known HTML tags that are dangerous, and throwing an error only if one is encountered. I’m not an avowed expect in the ways of typical web application exploitation, therefore do not assume this code will provide you with ironclad security.

The potentially dangerous HTML tags we search for in the code below were compiled by myself from various Microsoft security-related documents.

    protected override bool IsValidRequestString(
        HttpContext context,
        string value,
        RequestValidationSource requestValidationSource,
        string collectionKey,
        out int validationFailureIndex)
    {
        Match dangerousMatch
          = Regex.Match(value,
                         "</?(?i:script|body|applet|html|layer|ilayer|embed|object|frameset|frame|iframe|meta|link|style)(.|\n)*?>",
                         RegexOptions.IgnoreCase | RegexOptions.Compiled);

        // Set this to the location of a match, if one was found.
        validationFailureIndex = 0;

        // Everything is fine here if we failed to find any matches, otherwise ASP.NET will throw an exception.
        return !dangerousMatch.Success;
    }

Basically, all I’m doing is a RegEx match, returning true if there wasn’t a match, false if there was. Returning false from this method will result in the lovely “dangerous request” exception message to appear.

The “validationFailureIndex” set to 0 is an uninitialized integer that must be set before leaving the function. A more correct implementation of this handler would handle this parameter properly, which means that it would be set to the starting point of the text deemed to be malicious in the supplied string.

This will allow for users to use safe HTML, like simple styling elements, while blocking out the nastier elements.

The collection of malicious elements displayed above is a good starting point for knowing what to look for, but I cannot guarantee that these are the only malicious tags out there.

Checking if the HTML in the request was encoded would also be a nice improvement, but that should really be something taken of by the developer, by ensuring everything going out is encoded.

Matt Weber

I'm the founder of Bad Echo LLC, which offers consulting services to clients who need an expert in C#, WPF, Outlook, and other advanced .NET related areas. I enjoy well-designed code, independent thought, and the application of rationality in general. You can reach me at matt@badecho.com.

  One Response to “Properly Handling “A potentially dangerous Request.Form value was detected…””

  1. Hi, thanks for this article…

    I would like to have the validateRequest=”true” but at the same time instead of displaying the default “Server Error in ‘*’ Application. A potentially dangerous Request.Form value was detected” page to the user, i would like to display some other page/message to the user. Something like customErrors pages…
    Is it possible to do something like this? using customErrors.. How?
    I need to do this for the whole application without editing every single page in the application (which is not at all practical) :(

    Thanks :)

Leave a Reply to Tx36 Cancel reply

(required)

(required)

You may use these HTML tags and attributes: <a href="" title="" rel=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>

 
   
© 2012-2013 Matt Weber. All Rights Reserved. Terms of Use.