Jan
20
2012

Selective request validation using custom request validator in .Net 4.0

Introduction

Cross site scripting attacks are very common and easy way of trying to break into any website. To secure web page from this common security threat, Asp.net always had request validation mechanism in place.

What is cross site scripting(XSS) attacks

In any simple asp.net web page, go to textbox and type <test>. Unless the request validation has been disabled, you will get either ugly yellow page exception message indicating "A potentially dangerous Request.Form value was detected from the client blah.." or if you have exception handling in place for all exceptions then more generic custom exception message.

If you have disabled request validation explicitly then you are running the risk of being under XSS attacks.

Article Body

Although, we know that letting user enter script characters like less than (<) is not good practice and can cause serious issue in terms of XSS attacks, Sometime it becomes part of requirement.

Before .Net 4.0 the option was to disable request validation for the page by setting attribute in <@Page> tag

<%@ Page validateRequest="false" %>

After which it becomes developers responsibility to check every input to make sure it does not contain mallicious script.

Custom request validation in .Net 4.0

From .Net 4.0, we now have a option of extending default request validation.

The RequestValidator class of System.Web.Util namespace is the base class for standard request validation. We can override the to add our own implmentation.

To understand its use, consider this scenario which I faced recently.

Note: Please note that, the custom request validation logic which I used here is for demonstration purpose only. The logic may have some faults. But the intentions is to show how we can implement custom logic in RequestValidator class.

There is a small Asp.net application which has user module and admin module. I want default request validation to do its work for all pages of user module. In admin section, there are many pages and it contains some textboxes where admin user can enter some raw HTML code.

The requirement is, Admin user should be allowed to enter only raw html links like this

<a href="somename.html" ...> blah.. </a>

at the same time, any attempt by admin user to enter any other html tag or script tag should be validated (not allowed)

that means, <Img src="blah.jpg"> should not be allowed.

The standard request validation mechanism cannot provide us the option of such selective validation but, custom request validation does. To see custom request validation in action for above scenario, let us create sample application in .Net 4.0 (and Visual Studio 2010).

In the test application, create App_Code folder and add a new class. Name the new class as CustomRequestValidation.cs and add below code in the class

using System;
using System.Web;
using System.Web.Util;

public class CustomRequestValidation : RequestValidator
{
    public CustomRequestValidation() { }

    protected override bool IsValidRequestString(HttpContext context, string value,
        RequestValidationSource requestValidationSource, string collectionKey,
        out int validationFailureIndex)
    {
        validationFailureIndex = -1;  //Set a default value for the out parameter.        
        
        if (requestValidationSource == RequestValidationSource.Form && context.Request.Path.Contains("Admin.aspx")) 
        {

            //If the form data contains less thand and greater than characters then use logic to identify the tag name 
            if (value.Contains("<") && value.Contains(">"))
            {
                //split string with less than character
                string[] strValues = value.Split('<');
                //loop through all splitted strings
                for (int i=1;i<strValues.Length;i++)
                {
                    //after trim, check if the string starts with a or /a. i.e. string contains <a href or </a> 
                    if ((!strValues[i].Trim().ToUpper().StartsWith("A ")) && (!strValues[i].Trim().ToUpper().StartsWith("/A")))
                        return false;
                    //if yes, then continue and set validationfailureindex to -1 so as to avoid error.
                }
                validationFailureIndex = -1;
                return true;
            }
            else
                //Leave any further checks to ASP.NET.
                return base.IsValidRequestString(context, value,requestValidationSource,
                collectionKey, out validationFailureIndex);
        }
        else
        {
            return base.IsValidRequestString(context, value, requestValidationSource,
                                             collectionKey, out validationFailureIndex);
        }
    }
}

As it is clear from the code, below are important points to note in the code

  • The class should use namespace System.Web.Util
  • The class should inherit from RequestValidator class
  • Override IsValidRequestString function to add your own logic for request validation
  • Return true from IsValidRequestString function to indicate request string is valid else return false

To check request string, above code first checks that custom validation code is used only for validating form data (i.e. for querystring type of data, standard request validation logic will be used) this make it cleaner implementation wherein we are not breaking validation logic for other request types.

The code then splits incoming string with less than character and checks each part of splitted string to check if it either starts with "a " or "/a". That means string contains <a xxx> </a> which is fine. The validation logic will not allowed string like <Img blah... >

Note: In this demo code, I have considered only Form data as request validation source. However, you can validate reuquest data coming from URL, Cookies, form, files etc. For complete lise of request source types and definition of individual function parameter, please visit here

 

See custom request validation in action

We have simply created a class which overrides RequestValidator class. To make our application to use this class instead of standard request validation, we need to add following lines of code in web.config file of web site

<system.web>

        <httpRuntime requestValidationType="CustomRequestValidation" />

</system.web>

The name of requestValidationType in above config setting is nothing but the name of request validation class we have used above.

In the request validation class, we have added a check that the request url contains file name as Admin.aspx. This is rather straightforward test assuming that only authenticated admin user would have access to admin.aspx. In real world scenario you might have to use more complex logic like the request url should contain "admin" in the path and that all admin pages be present inside admin directory which can be accessed by only admin user etc.

For test purpose, add a new web page in the project and name it as Admin.aspx. Add a textbox in the page and a button control. Run the page and type "<test>" in the textbox and hit enter.

Now,run the page again and enter value as "<a href="somename.html" > Click Here </a>"

and click on the button. Since it contain <a and </a,  This will pass custom request validation and display html output in a label like this

Conclusion

By allowing extension for request validation mechanism in .Net 4.0 It becomes really easy to deal different request validation scenarios. At the same time we can continue relying upon standard request validation for rest of the request data.

Thanks for visiting my site and reading this article. I hope to see your comments :)

About Me

You are visiting personal website of Kedar (KK)

Please go here to know more about me

Disclaimer

The opinions expressed here represent my own and not those of my past or present employers.

The concept/code provided on this site may not work as described. If you are using any code provided on this site. Then, please test it thoroughly. I shall not be responsible for any issues arising in the code. 

Month List