Sunday 24 March 2013

Exam 70-486 Deferred Validation and Validation Requests in MVC 4

The Problem

Currently out of the box in MVC 3 using ASP.NET 4.0, if a user tries to submit a form that contains fields with HTML markup or even tries to pass HTML markup to query string parameters you will receive a Request Validation error similar to below.

ASP.NET will automatically kick your posted request to the curb and won't even attempt to execute your controller's action methods. The ValidateInput attribute placed on top of controller or action methods was also ignored and no longer became a factor as it once was in ASP.NET 2.0. The reason for this is that the validation of all request input is now evaluated before the application's Begin_Request method is actually called.

To better demonstrate the problem think about the following web request being made to the server.

http://localhost/Home/Index?name=<script>alert('hello world');</script>

As you can see this is a very safe scripting attack but still one in any case. But just assume for the moment that you wanted this to get through to the web server. In ASP.NET 2.0 you could have simply written MVC code like below including the ValidateInput attribute and forcing the action method to never validate.

  1. [ValidateInput(false)]
  2. [HttpGet]
  3. public ActionResult Index(string name)
  4. {
  5. ViewBag.Name = name;
  6. return View();
  7. }

But if you try to run the same code in an MVC application running under the ASP.NET 4.0 runtime, you will receive the error above. Believe it or not Microsoft did this by design because they felt it was important to catch any validation errors early rather than not at all. In ASP.NET 2.0 if you created a custom HTTP Handler or were using a ASMX Web Service, this validation was never being performed at all. So the unexpected functionality change was kinda necessary, (but destroyed the purpose of the ValidateInput attribute in the process, damn you Microsoft!!!). But now all ASP.NET applications are better protected against Cross Site Scripting (XSS) attacks. However there are still times where using HTML markup is actually appropriate for best user experience, such as submitting comments or even blogs as I am right now.

The Fix

So how do we get around this? What is the best approach to take in MVC 3/4? Well there are a number of different ways to address this. The old way to fix this issue in MVC 3 was to revert the requestValidationMode attribute of the httpRuntime element in the web.config file back to using "2.0".

  1. <httpRuntime requestValidationMode="2.0" />

However what this meant you relapsed back to the security vulnerabilities that ASP.NET 2.0 had. Luckily .NET 4.5 has provided 2 new features to fix such a problem. Deferred ("lazy") request validation and the ability to access unvalidated request data. So now you just need to set the runtime attribute to "4.5".

  1. <httpRuntime requestValidationMode="4.5" />

So what is Deferred ("lazy") request validation?

The purpose of Deferred request validation was to delay the validation of any posted information until it was actually attempted to be retrieved from the request object itself. Another words if some posts some malicious code as a query string parameter or as some form data it will be ignored until you try to do something like this.

  1. var comment = Request.Form["comment"];

Or
  1. var comment = Request.QueryString["comment"];

At this point in time the value of comment is then validated and will return a Request Validation Error if the value is deemed malicious.

But wait a minute, why bother letting in malicious information in if you are just going to run into the same problem anyway when you try to access it. Well this is where the ability to access unvalidated data comes into play.

Accessing Unvalidated Data

To retrieve data that has malicious code but without receiving the Request Validation error you can access the data using the Unvalidated extension method included in the System.Web.Helpers namespace located inside of the System.Web.WebPages assembly. You then just simply access it using the code below.

  1. var comment = Request.Unvalidated["comment"];

MVC and Model Binding issues

But now you are probably asking the question, "Does this actually solve issues with Model Binding?". Unfortunately no it does not as Model Binding still continues to look inside of the Forms and Query string collections in order to try and perform the binding. So how do we fix this? Does ValidateInput actually work now?

The answer to the second question is yes, however I strongly recommend to never use it. The problem with ValidateInput is that it allowed all posted data to have validation ignored, even when only one parameter required HTML. Instead in MVC 3 a newly defined AllowHtmlAttribute was created to get around such a problem. You include it on top of model's property so that only that on is ignored.

  1. public class Comment
  2. {
  3. [AllowHtml]
  4. public string Description { get; set; }
  5. public string Title{ get; set; }
  6. }

Doing this means that Description will allow HTML to pass through, however Title will not.

Summary

I guess to take out of all this you just need to remember the following.

  • Ensure that the requestValidationMode on the httpRuntime element in the web.config file is set to 4.5 to ensure you have the maximum XSS support.
  • If fetching unvalidated values from the Request object directly use the Unvalidated extension method from the System.Web.Helpers namespace.
  • To address a property on your model use the AllowHtmlAttribute in replace of the ValidateInput on a controller or action method.

Thanks for reading...

2 comments:

  1. While you are planning to get Developing ASP.NET MVC 4 Web Applications Cerification. You also plan ahead getting study material for exam preparation like pdf files and pratice test software. I would suggest you get 100% real Developing ASP.NET MVC 4 Web Applications certification exam 70-486 questions and practice test software from CertificationGenie they are best exam material provider. The holiday deals are awesome and might end up saving a lot of money.

    ReplyDelete
  2. This article is very helpful on 70 486 Asp.net no doubt this is very important certification to learn but before directly attempt it is very important to do some practice before many sites provide PSM Certification Dumps

    ReplyDelete