Rick Strahl's Weblog  

Wind, waves, code and everything in between...
.NET • C# • Markdown • WPF • All Things Web
Contact   •   Articles   •   Products   •   Support   •   Advertise
Sponsored by:
West Wind WebSurge - Rest Client and Http Load Testing for Windows

RequestValidation Changes in ASP.NET 4.0


:P
On this page:

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.

What Microsoft Says

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…

Posted in ASP.NET  

The Voices of Reason


 

Martin Aatmaa
August 21, 2010

# re: RequestValidation Changes in ASP.NET 4.0

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,

Richard
August 24, 2010

# re: RequestValidation Changes in ASP.NET 4.0

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.)

PilotBob
August 25, 2010

# re: RequestValidation Changes in ASP.NET 4.0

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

Jarrett Vance
August 30, 2010

# re: RequestValidation Changes in ASP.NET 4.0

Rick, this is a great post, keep it up!

Chris Halcrow
August 30, 2010

# re: RequestValidation Changes in ASP.NET 4.0

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

Chris Halcrow
September 05, 2010

# re: RequestValidation Changes in ASP.NET 4.0

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/

David
September 10, 2010

# re: RequestValidation Changes in ASP.NET 4.0

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.

duquanyong
September 10, 2010

# re: RequestValidation Changes in ASP.NET 4.0

Thanks! this is a great post, keep it up!

Holyeagle
September 11, 2010

# re: RequestValidation Changes in ASP.NET 4.0

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.

Sheo Narayan
September 13, 2010

# re: RequestValidation Changes in ASP.NET 4.0

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

Seena
September 19, 2010

# re: RequestValidation Changes in ASP.NET 4.0

Thanks man, u really saved me a lot of troubles today ! ;)

Jeremy
February 04, 2011

# re: RequestValidation Changes in ASP.NET 4.0

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>

Steve
January 26, 2012

# re: RequestValidation Changes in ASP.NET 4.0

hmm..nearly a year later i see... but thanks Jeremy. That was the answer I was looking for! Cheers

Kevin
October 29, 2013

# re: RequestValidation Changes in ASP.NET 4.0

just encode the html string with javascript and decode it on the server side. no need to turn off validation.

fib(Littul)
March 11, 2015

# re: RequestValidation Changes in ASP.NET 4.0

just encode with javascript ?! - amounts to writing a massive encoder/decoder that will be broken each time W3 changes things, just about. Just try this ... examples:
xmlhttp.open("POST", "page.aspx?val1=abc&val2=<d", false(or true));
or anything "<(letter)"...
or anything that has '&' in it...
The above is with RequestValidation in force.
Examples: if you encode '<d' ... no go!
if you swap '<' or & with certain 3 character sequences and of course, decoding code galore on the server side... wow... things can be made to work... but the code is horrendous. Don't know, show me what I am missing.
so, hypothetically <div would become xxx, <p...zzz, ... etc... ...xxx may fail in a porno context! lol

Björn Kullberg
July 06, 2017

# re: RequestValidation Changes in ASP.NET 4.0

Solved it with a location tag, like this:

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

Archie Marler
May 01, 2020

# re: RequestValidation Changes in ASP.NET 4.0

Hi Chris Halcrow (or anyone)

I'm having exactly the same issue, albeit 11 years later!, where this works on my development machine but not on the live server. I have 2.0 (and 3,3.5,4.x) frameworks installed on both machines. The WebConfig contains both entries and they're not accidently in a location tag but still get the "potentially dangerous request" error warning.

Did you find a solution?

Thanks


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