Request Validation in ASP.NET

Request validation is a feature in ASP.NET that examines an HTTP request and determines whether it contains potentially dangerous content. In this context, potentially dangerous content is any HTML markup or JavaScript code in the body, header, query string, or cookies of the request. ASP.NET performs this check because markup or code in the URL query string, cookies, or posted form values might have been added for malicious purposes.

For example, if your site has a form where users enter comments, a malicious user could enter JavaScript code in a script element. When you display the comments page to other users, the browser executes the JavaScript code as if the code had been generated by your website. This exploit is typically referred to as a cross-site scripting (XSS) attack.

Request validation helps prevent this kind of attack. If ASP.NET detects any markup or code in a request, it throws a "potentially dangerous value was detected" error and stops page processing.

Request validation throws this exception when any HTML markup is detected, including harmless markup like <b> (bold) elements. Throwing an error under this circumstance can be a problem if you want your application to accept HTML markup. For example, if your site lets users add comments, you might want to let users add basic formatting by using HTML tags that put text in bold or italics. In cases like these, you can disable request validation and check for malicious content manually. Or you can customize request validation so that certain kinds of markup or script are accepted. For information about how to customize request validation, see the whitepaper Security Extensibility in ASP.NET 4 (PDF). For information about how to specify a custom error page instead of the default error, page, see How to: Handle Application-Level Errors.

Security noteSecurity Note

Even if you're using request validation, you should HTML-encode text that you get from users before you display it on a page. (Unless you've manually checked it for potentially malicious markup, as explained later.) For information about how to HTML-encode text, see the blog entry New <%: %> Syntax for HTML Encoding Output in ASP.NET 4 (and ASP.NET MVC 2) by Scott Guthrie.

Disabling Request Validation

Security noteSecurity Note

If you disable request validation, you must check the user input yourself for dangerous HTML or JavaScript. For more information, see Manually Checking Requests later in this topic.

The method that you use to disable request validation depends on what type of ASP.NET web application you are working with:

  • ASP.NET Web Forms

  • ASP.NET MVC

  • ASP.NET Web Pages

Disabling Request Validation in ASP.NET Web Forms (ASP.NET 4 or later)

You can disable request validation for an entire application, but doing so is not recommended. The recommendation is to selectively disable request validation only for the virtual paths or specific pages where you want to allow markup.

In either case, you must make two changes in the Web.config file. The first change is to set the requestValidationMode attribute of the httpRuntime element to "2.0". This setting makes request validation occur later in the sequence of request processing events. The setting is required for applications that use ASP.NET 4 and later, because as of ASP.NET 4, request validation takes place earlier in the request life cycle than it did in previous versions of ASP.NET.

<system.web>
  <httpRuntime requestValidationMode="2.0" />
</system.web>

The following example shows how to make request validation occur later for a single page, in this case the Test.aspx page:

<location path="test.aspx">
  <system.web>
    <httpRuntime requestValidationMode="2.0" />
  </system.web>
</location>

The second change is to set validationRequest to false. For the application as a whole, you do this using the pages element in the Web.config file as shown in the following example. (This setting is effective only if you also set requestValidationMode="2.0".)

<configuration>
  <system.web>
    <pages validateRequest="false" />
  </system.web>
</configuration>

For an individual page, you can set validationRequest to false in the @ Page directive of the page, as in the following example:

<@ Page validateRequest="false" %>

Disabling Request Validation in ASP.NET MVC

To disable request validation in an ASP.NET MVC application, you must change request validation to occur earlier in the sequence of request processing, as explained earlier for ASP.NET Web Forms. In the Web.config file, make the following setting:

<system.web>
  <httpRuntime requestValidationMode="2.0" />
</system.web>

In ASP.NET MVC, you can disable request validation for an action method, for a property, or for a field (input element) in a request. If you disable validation for an action method, you disable it for any requests that invoke that method—that is, all user input is allowed for any request that calls the action method. This approach is therefore the least secure way to disable request validation.

If you disable validation for a property, you allow user input for any reference to that property. If you disable validation for specific fields, you can control which request element (field) allows arbitrary user input.

To disable request validation for an action method, mark the method with the attribute ValidateInput(false), as shown in the following example:

[HttpPost]
[ValidateInput(false)]
public ActionResult Edit(string comment) 
{
    if (ModelState.IsValid) 
    {
        //  Etc.
    }
    return View(comment);
}

To disable request validation for a specific property, mark the property definition with the AllowHtml attribute:

[AllowHtml]
public string Prop1 { get;  set; }

To disable request validation for a specific field in a request (for example, for an input element or query string value), call the Request.Unvalidated method when you get the item, as shown in the following example:

var rawComment = Request.Unvalidated().Form["comment"];

Disabling Request Validation in ASP.NET Web Pages

To disable request validation for ASP.NET Web Pages, in code, call the Request.Unvalidated method and pass it the name of the field or other object that you want to bypass request validation for. The comments in the following code snippet indicate which lines of code trigger request validation and which ones do not.

Note

In ASP.NET Web Pages applications that do not also include Web Forms pages or MVC controllers, you do not have to change any settings in the Web.config file.

var userComment = Request.Form["userInput"]; // Validated, throws error if input includes markup

Request.Unvalidated("userInput"); // Validation bypassed
Request.Unvalidated().Form["userInput"]; // Validation bypassed

Request.QueryString["userPreference"]; // Validated
Request.Unvalidated().QueryString["userPreference"]; // Validation bypassed;

Manually Checking Requests

If you disable request validation, you must manually check the unvalidated user input for potentially dangerous input. Checking for dangerous input is critical for the security of your application. However, it is not necessarily an easy task. If your code is flawed or if you forget to protect one page or one field, malicious users might eventually find and exploit that weakness.

In general, you should restrict as narrowly as possible the list of HTML tags that you will accept, and reject everything else. (This approach is sometimes referred as using a safe terms list or a whitelist.)

If you are working with Web Forms pages, you can often use a third-party "rich text" control that lets users format text. These controls often have validation routines built in that permit only safe HTML. (If you use a control, make sure that it offers HTML safety.)

If you are not using a control, a simple approach is to HTML-encode the user input, and then to selectively unencode just the HTML tags that you want to allow. This approach is practical if the tags you want to allow do not include attributes, such as <b>, <strong>, <i>, and <em>. The following example shows a way to encode and then selectively decode just the <b> and <i> tags.

// Encode the string input
StringBuilder sb = new StringBuilder(
    HttpUtility.HtmlEncode(htmlInputTxt.Text));
// Selectively allow <b> and <i>
sb.Replace("&lt;b&gt;", "<b>");
sb.Replace("&lt;/b&gt;", "</b>");
sb.Replace("&lt;i&gt;", "<i>");
sb.Replace("&lt;/i&gt;", "</i>");

To allow more flexible HTML markup in the user input, you can use third-party libraries. Examples include the HTML Agility Pack that you can download from the CodePlex website and the open-source OWASP Anti-Samy utility. For more information, see the example on the OWASP site of disabling request validation for ASP.NET.

Another approach is to use an alternative form of markup, like MarkDown, and then convert the user's text to valid and safe HTML. Many wikis use this approach. For more information about Markdown, see the Daring Fireball site.

Additional Information