Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Disabling request validation for HttpContext.Current.Request.Params

Using MVC5 I use [AllowHtml] on specific model properties to allow HTML to be POSTed up to the server.

In some places in code I want to access the Request params like so:

string wlid = HttpContext.Current.Request.Params["wlid"];

But this fails with a HttpRequestValidationException if any HTML is included in the request, even if the model propertiy is decorated with [AllowHtml].

Is there any way to access HttpContext.Current.Request.Params["wlid"] without completly disabling request validation?

Perhaps disabling request validation, accessing the Request.Params and then enabling it again instantly?

like image 892
Mr. Flibble Avatar asked Jan 19 '18 11:01

Mr. Flibble


2 Answers

Request.Unvalidated works as an unvalidated equivalent of Request.Params.

So instead of

string wlid = HttpContext.Current.Request.Params["wlid"];

just use

string wlid = HttpContext.Current.Request.Unvalidated["wlid"];

or better (as suggested in the comments) to avoid coupling with the static member:

string wlid = this.HttpContext.Request.Unvalidated["wlid"];

TL;DR

If you look behind the scenes, Request.Params combines the following data (in this order):

  • QueryString
  • Form
  • Cookies
  • ServerVariables

You can peek its source code here: https://github.com/microsoft/referencesource/blob/master/System.Web/HttpRequest.cs

The key part is:

_params.Add(this.QueryString);
_params.Add(this.Form);
_params.Add(this.Cookies);
_params.Add(this.ServerVariables);

You're right that accessing Request.Params fails with HttpRequestValidationException as it reads the underneath collections which causes the request validation.

Documentation:

When ASP.NET reads the values in HTTP request collections (such as the Form, QueryString, and Cookies collections), it performs request validation. During request validation, ASP.NET examines the posted values and determines whether they contain markup, script, or reserved characters. By default, if ASP.NET detects any of these types of input, it throws an HttpRequestValidationException exception. This helps prevent malicious script injection attacks on your website.

So this works as designed. If you want to bypass ASP.NET request validation, there is a different object for that. It's called Request.Unvalidated and contains query string params, form variables and cookies in the form of its properties:

  • Request.Unvalidated.QueryString
  • Request.Unvalidated.Form
  • Request.Unvalidated.Cookies

Reading these properties does not trigger the request validation so you can use them in your case. If you don't know which of the above properties contains your data, you can just utilize the Request.Unvalidated in the form of Request.Unvalidated["somekey"] as it has an indexer which retrieves data from the Form, Cookies, QueryString, or ServerVariables collections. So it's a pretty close (but not validated!) equivalent of Request.Params.

Be aware that after bypassing the request validation you become vulnerable to cross-site scripting and you must manually validate the data for potential XSS attacks.

like image 92
piter entity Avatar answered Oct 14 '22 15:10

piter entity


Validation was being triggered any time the Params collection was being accessed.

I was able to use this to get the value we needed

Request.Unvalidated.QueryString["key"]

Note: QueryString is not exactly the same as Params, but for our case the data we needed was in the query string so this worked.

See MSDN for HttpRequestBase.Unvalidated for more information.

like image 41
Sen Avatar answered Oct 14 '22 16:10

Sen