Contact   •   Products   •   Search

Rick Strahl's Web Log

Wind, waves, code and everything in between...
ASP.NET • C# • HTML5 • JavaScript • AngularJs

RequestValidation Changes in ASP.NET 4.0


There’s been a change in the way the ValidateRequest attribute on WebForms works in ASP.NET 4.0. I noticed this today while updating a post on my WebLog all of which contain raw HTML and so all pretty much trigger request validation. I recently upgraded this app from ASP.NET 2.0 to 4.0 and it’s now failing to update posts. At first this was difficult to track down because of custom error handling in my app – the custom error handler traps the exception and logs it with only basic error information so the full detail of the error was initially hidden.

After some more experimentation in development mode the error that occurs is the typical ASP.NET validate request error (‘A potentially dangerous Request.Form value was detetected…’) which looks like this in ASP.NET 4.0:

RequestValidationErrorScreen

At first when I got this I was real perplexed as I didn’t read the entire error message and because my page does have:

<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="NewEntry.aspx.cs" Inherits="Westwind.WebLog.NewEntry" 
         MasterPageFile="~/App_Templates/Standard/AdminMaster.master"  
         ValidateRequest="false"         
         EnableEventValidation="false"
         EnableViewState="false" 
%>

WTF? ValidateRequest would seem like it should be enough, but alas in ASP.NET 4.0 apparently that setting alone is no longer enough. Reading the fine print in the error explains that you need to explicitly set the requestValidationMode for the application back to V2.0 in web.config:

<httpRuntime executionTimeout="300" requestValidationMode="2.0" />

Kudos for the ASP.NET team for putting up a nice error message that tells me how to fix this problem, but excuse me why the heck would you change this behavior to require an explicit override to an optional and by default disabled page level switch? You’ve just made a relatively simple fix to a solution a nasty morass of hard to discover configuration settings??? The original way this worked was perfectly discoverable via attributes in the page. Now you can set this setting in the page and get completely unexpected behavior and you are required to set what effectively amounts to a backwards compatibility flag in the configuration file.

It turns out the real reason for the .config flag is that the request validation behavior has moved from WebForms pipeline down into the entire ASP.NET/IIS request pipeline and is now applied against all requests. Here’s what the breaking changes page from Microsoft says about it:

The request validation feature in ASP.NET provides a certain level of default protection against cross-site scripting (XSS) attacks. In previous versions of ASP.NET, request validation was enabled by default. However, it applied only to ASP.NET pages (.aspx files and their class files) and only when those pages were executing.

In ASP.NET 4, by default, request validation is enabled for all requests, because it is enabled before the BeginRequest phase of an HTTP request. As a result, request validation applies to requests for all ASP.NET resources, not just .aspx page requests. This includes requests such as Web service calls and custom HTTP handlers. Request validation is also active when custom HTTP modules are reading the contents of an HTTP request.

As a result, request validation errors might now occur for requests that previously did not trigger errors. To revert to the behavior of the ASP.NET 2.0 request validation feature, add the following setting in the Web.config file:

<httpRuntime requestValidationMode="2.0" />

However, we recommend that you analyze any request validation errors to determine whether existing handlers, modules, or other custom code accesses potentially unsafe HTTP inputs that could be XSS attack vectors.

Ok, so ValidateRequest of the form still works as it always has but it’s actually the ASP.NET Event Pipeline, not WebForms that’s throwing the above exception as request validation is applied to every request that hits the pipeline. Creating the runtime override removes the HttpRuntime checking and restores the WebForms only behavior. That fixes my immediate problem but still leaves me wondering especially given the vague wording of the above explanation.

One thing that’s missing in the description is above is one important detail: The request validation is applied only to application/x-www-form-urlencoded POST content not to all inbound POST data.

When I first read this this freaked me out because it sounds like literally ANY request hitting the pipeline is affected. To make sure this is not really so I created a quick handler:

public class Handler1 : IHttpHandler
{

    public void ProcessRequest(HttpContext context)
    {
        context.Response.ContentType = "text/plain";
        context.Response.Write("Hello World <hr>" + context.Request.Form.ToString());
    }

    public bool IsReusable
    {
        get
        {
            return false;
        }
    }
}

and called it with Fiddler by posting some XML to the handler using a default form-urlencoded POST content type:

FiddlerRequest

and sure enough – hitting the handler also causes the request validation error and 500 server response.

Changing the content type to text/xml effectively fixes the problem however, bypassing the request validation filter so Web Services/AJAX handlers and custom modules/handlers that implement custom protocols aren’t affected as long as they work with special input content types. It also looks that multipart encoding does not trigger event validation of the runtime either so this request also works fine:

POST http://rasnote/weblog/handler1.ashx HTTP/1.1
Content-Type: multipart/form-data; boundary=------7cf2a327f01ae
User-Agent: West Wind Internet Protocols 5.53
Host: rasnote
Content-Length: 40
Pragma: no-cache

<xml>asdasd</xml>--------7cf2a327f01ae

*That* probably should trigger event validation – since it is a potential HTML form submission, but it doesn’t.

New Runtime Feature, Global Scope Only?

Ok, so request validation is now a runtime feature but sadly it’s a feature that’s scoped to the ASP.NET Runtime – effective scope to the entire running application/app domain. You can still manually force validation using Request.ValidateInput() which gives you the option to do this in code, but that realistically will only work with the requestValidationMode set to V2.0 as well since the 4.0 mode auto-fires before code ever gets a chance to intercept the call. Given all that, the new setting in ASP.NET 4.0 seems to limit options and makes things more difficult and less flexible. Of course Microsoft gets to say ASP.NET is more secure by default because of it but what good is that if you have to turn off this flag the very first time you need to allow one single request that bypasses request validation??? This is really shortsighted design… <sigh>

Make Donation
Posted in ASP.NET  


Feedback for this Post

 
# re: RequestValidation Changes in ASP.NET 4.0
by Martin Aatmaa August 21, 2010 @ 4:11pm
Rick,

Thanks for the detailed post and information.

Regarding the part about this functionality being restricted to "application/x-www-form-urlencoded POST" requests: are you sure about this?

I seem to remember that I ran into this on a simple GET request which had illegal characters in the URL. I don't have time to verify this right now, but was wondering whether you would know anything about it.

When I do revisit this I'll be sure to post back here.

Thanks,
# re: RequestValidation Changes in ASP.NET 4.0
by Richard August 24, 2010 @ 6:24am
I agree with Martin - I've just tested a very simple ASP.NET 4.0 page passing HTML in the query-string, and got: "A potentially dangerous Request.QueryString value was detected from the client". This happens even if I set the ValidateRequest attribute to false.

I think the problem with your multipart/form-data example is that the body isn't properly formatted. To trigger the error, change your POST body to:

--------7cf2a327f01ae
Content-Disposition: form-data; name="user"
 
<xml>asdasd</xml>
--------7cf2a327f01ae


(Note the two extra "-" characters on the boundary markers.)
# re: RequestValidation Changes in ASP.NET 4.0
by PilotBob August 25, 2010 @ 1:22pm
Rick... thanks for posting the same thoughts I had. When we ran into this and investigated it I was surprised the only way I could disable request validation for a specific page was to downgrade to ASP.Net 2.0 request validation.

How is this MORE secure again? Jees...

BOb
# re: RequestValidation Changes in ASP.NET 4.0
by Jarrett Vance August 30, 2010 @ 7:41am
Rick, this is a great post, keep it up!
# re: RequestValidation Changes in ASP.NET 4.0
by Chris Halcrow August 30, 2010 @ 4:39pm
Thanks for the post Rick - this clarifies things some more.

I'm trying the fix that allow validation to be switched off, i.e. adding <httpRuntime requestValidationMode="2.0" /> to our root web.config. It works fine on my local development machine, however I still get the validation errors on our test web server. Both machines have .NET 4.0 installed, and the application I'm testing is configured as .NET 4.0 on my local machine and the test server. The only difference in these environments is that my local machine is running IIS 5.1, and the test server is running IIS 6.0. Has anyone come across this issue?

Thanks for any help, Chris
# re: RequestValidation Changes in ASP.NET 4.0
by Chris Halcrow September 05, 2010 @ 9:35pm
Hi Rick

If you're looking for more flexibility in the way that the automatic validation works, you can define a custom validation type (i.e. a custom class for performing the validation). See details here:

http://jefferytay.wordpress.com/2010/04/15/creating-your-own-custom-request-validation/
# re: RequestValidation Changes in ASP.NET 4.0
by David September 10, 2010 @ 8:57am
What happens if you the AJAX HTML Editor is used to dress up text that is then saved in a DB? I had played with it a while back and discovered that it saves the text using typical HTML-related tags.
# re: RequestValidation Changes in ASP.NET 4.0
by duquanyong September 10, 2010 @ 8:19pm
Thanks! this is a great post, keep it up!
# re: RequestValidation Changes in ASP.NET 4.0
by Holyeagle September 11, 2010 @ 2:43pm
Rick - I love this article and your final conclusion. I must say that the best statement in your article is "WTF?". I do not know how many times I have uttered this same statement when trying to code in asp.net.
# re: RequestValidation Changes in ASP.NET 4.0
by Sheo Narayan September 13, 2010 @ 7:19am
Hey Rick,

I had come across this situation while designing a webpage few months back that had Rich Text Editor box and I fixed it the way you shown in by modifying the web.config file. However I didin't digged more into why it was happening. Your post clarified it now. Wondering if that would downgraded all aspx pages of my website to 2.0 as it is being specified in the web.config file thats really not good.

I tried to set a page level requestValidationMode but I think it is not doable, if any body knows please suggest. Anyways as always great post, keep it up!

Regards
# re: RequestValidation Changes in ASP.NET 4.0
by Seena September 19, 2010 @ 10:19am
Thanks man, u really saved me a lot of troubles today ! ;)
# re: RequestValidation Changes in ASP.NET 4.0
by Jeremy February 04, 2011 @ 12:45am
Hi Sheo,
To do it by page use location sections in your web.config;

<location path="[PageRequiring].aspx">
        <system.web>
            <httpRuntime requestValidationMode="2.0" />
        </system.web>
    </location>
# re: RequestValidation Changes in ASP.NET 4.0
by Steve January 26, 2012 @ 11:53am
hmm..nearly a year later i see... but thanks Jeremy. That was the answer I was looking for! Cheers
# re: RequestValidation Changes in ASP.NET 4.0
by Kevin October 29, 2013 @ 8:42am
just encode the html string with javascript and decode it on the server side. no need to turn off validation.
 


West Wind  © Rick Strahl, West Wind Technologies, 2005 - 2014