Every time a user posts something containing < or > in a page in my web application, I get this exception thrown.

I don't want to go into the discussion about the smartness of throwing an exception or crashing an entire web application because somebody entered a character in a text box, but I am looking for an elegant way to handle this.

Trapping the exception and showing

An error has occurred please go back and re-type your entire form again, but this time please do not use <

doesn't seem professional enough to me.

Disabling post validation (validateRequest="false") will definitely avoid this error, but it will leave the page vulnerable to a number of attacks.

Ideally: When a post back occurs containing HTML restricted characters, that posted value in the Form collection will be automatically HTML encoded.
So the .Text property of my text-box will be something & lt; html & gt;

Note that you can get this error if you have HTML entity names (&amp;) or entity numbers (&#39;) in your input too.
– Drew NoakesOct 14 '10 at 2:50

17

Well, since it's my question I feel I can define what the point actually is: crashing an entire application process and returning a generic error message because somebody typed a '<' is overkill. Especially since you know most people will just 'validateRequest=false' to get rid of it, thus re-opening the vulnerability
– Radu094Sep 18 '14 at 17:23

7

@DrewNoakes: entity names (&amp;) do not seem to be a problem according to my tests (tested in .Net 4.0), although entity numbers (&#39;) do fail validation (as you said). If you disassemble the System.Web.CrossSiteScriptingValidation.IsDangerousString method using .Net Reflector, you'll see that the code looks specifically for html tags (starting with <) and entity numbers (starting with &#)
– Gyum FoxMay 6 '15 at 15:52

5

Create a new site in VS2014 using the default MVC project and run it. Click the register link, add any email, and use "<P455-0r[!" as the password. Same error out of the box, not trying to do anything malicious, the password field won't be displayed so it won't be a XSS attack, but the only way to fix it is to completely remove validation with the ValidateInput(false)? The AllowHtml suggestion doesn't work in this situation, still blew up with the same error. A potentially dangerous Request.Form value was detected from the client (Password="<P455-0r[!").
– stephenbayerMay 26 '15 at 22:34

43 Answers
43

I think you are attacking it from the wrong angle by trying to encode all posted data.

Note that a "<" could also come from other outside sources, like a database field, a configuration, a file, a feed and so on.

Furthermore, "<" is not inherently dangerous. It's only dangerous in a specific context: when writing strings that haven't been encoded to HTML output (because of XSS).

In other contexts different sub-strings are dangerous, for example, if you write an user-provided URL into a link, the sub-string "javascript:" may be dangerous. The single quote character on the other hand is dangerous when interpolating strings in SQL queries, but perfectly safe if it is a part of a name submitted from a form or read from a database field.

The bottom line is: you can't filter random input for dangerous characters, because any character may be dangerous under the right circumstances. You should encode at the point where some specific characters may become dangerous because they cross into a different sub-language where they have special meaning. When you write a string to HTML, you should encode characters that have special meaning in HTML, using Server.HtmlEncode. If you pass a string to a dynamic SQL statement, you should encode different characters (or better, let the framework do it for you by using prepared statements or the like)..

When you are sure you HTML-encode everywhere you pass strings to HTML, then set validateRequest="false" in the <%@ Page ... %> directive in your .aspx file(s).

In .NET 4 you may need to do a little more. Sometimes it's necessary to also add <httpRuntime requestValidationMode="2.0" /> to web.config (reference).

the problem may be come when it's need on one page of whole application
– Steven SpielbergDec 18 '10 at 6:03

3

You can also add the [ValidateInput(false)] attribute at the class level. If you add it to your base controller class, it will apply to all controller method actions.
– Shan PlourdeMay 29 '11 at 13:12

@Zack Thanks for the solution. On the other hand I am wondering if [AllowHtml] is better than ValidateInput(false), because [AllowHtml]is defined at once for a property i.e. Editor field and whenever it is used there is no need to use it for several actions. What do you suggest?
– JackJul 21 '15 at 23:44

Much better to do this declarativly than in the controller!
– AndiihMar 9 '12 at 9:03

25

The only correct answer! disabling validation on controller action is hacky. And for disabling validation on application level, devs must be hanged!
– trailmaxJan 30 '14 at 14:08

6

Beautiful! This is the way it should be done.
– beautifulcoderFeb 20 '15 at 2:59

3

@AnthonyJohnston Can it also be used in MVC 4 and MVC 5? Thanks...
– JackJul 21 '15 at 23:39

1

What is the difference between ValidateInput(false) and AllowHtml? What is the advantage of one over the other? When would i want to use AllowHtml instead of ValidateInput(false)? When would i want to use ValidateInput(false) over AllowHtml? When would i want to use both? Does it make sense to use both?
– Ian BoydJul 29 '16 at 13:55

If you are on .NET 4.0 make sure you add this in your web.config file inside the <system.web> tags:

<httpRuntime requestValidationMode="2.0" />

In .NET 2.0, request validation only applied to aspx requests. In .NET 4.0 this was expanded to include all requests. You can revert to only performing XSS validation when processing .aspx by specifying:

I've put this in the web.config, but still to the error "A potentially dangerous Request.Form value "
– FilipDec 12 '10 at 15:40

19

Looks like <httpRuntime requestValidationMode="2.0" /> works only when 2.0 framework is installed on the machine. What if 2.0 framework is not installed at all but only 4.0 framework is installed?
– SamuelJul 20 '11 at 18:18

This totally worked for me. None of the steps document in the other answers were necessary (including validateRequest="false")!
– tom redfernOct 2 '12 at 10:53

For ASP.NET 4.0, you can allow markup as input for specific pages instead of the whole site by putting it all in a <location> element. This will make sure all your other pages are safe. You do NOT need to put ValidateRequest="false" in your .aspx page.

The previous answers are great, but nobody said how to exclude a single field from being validated for HTML/JavaScript injections. I don't know about previous versions, but in MVC3 Beta you can do this:

This still validates all the fields except for the excluded one. The nice thing about this is that your validation attributes still validate the field, but you just don't get the "A potentially dangerous Request.Form value was detected from the client" exceptions.

I've used this for validating a regular expression. I've made my own ValidationAttribute to see if the regular expression is valid or not. As regular expressions can contain something that looks like a script I applied the above code - the regular expression is still being checked if it's valid or not, but not if it contains scripts or HTML.

Use [AllowHtml] on the model's properties instead of [ValidateInput] on the Action to achieve the same end result.
– MrchiefMar 25 '14 at 17:07

2

@Christof Note that my answer is 5 years old. I haven't come across this problem in a really long while, so there might be a lot better ways of dealing with it. Regarding this two options I think it depends on your situation. Maybe you expose that model in more than one actions and in some places HTML is allowed or not. In such a case [AllowHtml] isn't an options. I recommend checking out this article: weblogs.asp.net/imranbaloch/…, but it too is somewhat old and might be out of date.
– gligoranJul 22 '15 at 16:13

You can HTML encode text box content, but unfortunately that won't stop the exception from happening. In my experience there is no way around, and you have to disable page validation. By doing that you're saying: "I'll be careful, I promise."

This doesn't seem to work in the case that it gets to the controller method via a configured route.
– PandaWoodMar 24 '16 at 0:39

Actually, the technical explanation, is that this only works when the offending character is in the "query string"... if it's in the request path, Validation attribute does not work
– PandaWoodMar 24 '16 at 2:08

Please bear in mind that some .NET controls will automatically HTML encode the output. For instance, setting the .Text property on a TextBox control will automatically encode it. That specifically means converting < into &lt;, > into &gt; and & into &amp;. So be wary of doing this...

However, the .Text property for HyperLink, Literal and Label won't HTML encode things, so wrapping Server.HtmlEncode(); around anything being set on these properties is a must if you want to prevent <script> window.location = "http://www.google.com"; </script> from being output into your page and subsequently executed.

This will still leave the app vulnerable from made-up POST requests. A regular user will have problems entering characters like , : or quotes, but a regular hacker will have no problems POSTing malformed data to the server. I'd vode this waaay down.
– Radu094Oct 26 '09 at 22:21

13

@Radu094: This solution allows you to keep ValidateRequest=true, which means hackers will still hit that wall. Vote UP, since this leaves you less vulnerable than turning ValidateRequest off.
– jbehrenAug 17 '11 at 19:10

Nice! Wasn't aware of the ability to replace the Request Validator. Instead of just saying "ok" like you do I extended this idea to not validate fields that end in "_NoValidation" as their name. Code below.
– Walden LeverichMay 1 '14 at 20:01

Walden Leverich, to do this see [AllowHtml] attribure
– SelJan 28 '15 at 9:10

Sel, yes in an MVC environment that would work. But in a webforms application I don't have a model to do that on. :-)
– Walden LeverichJan 29 '15 at 23:24

In ASP.NET, you can catch the exception and do something about it, such as displaying a friendly message or redirect to another page... Also there is a possibility that you can handle the validation by yourself...

I guess you could do it in a module; but that leaves open some questions; what if you want to save the input to a database? Suddenly because you're saving encoded data to the database you end up trusting input from it which is probably a bad idea. Ideally you store raw unencoded data in the database and the encode every time.

Disabling the protection on a per page level and then encoding each time is a better option.

Rather than using Server.HtmlEncode you should look at the newer, more complete Anti-XSS library from the Microsoft ACE team.

This works great. If a hacker tries to post via bypassing JavaScript, they they will just see the error. You can save all this data encoded in a database as well, then unescape it (on the server side), and parse & check for attacks before displaying elsewhere.

This is a good solution. It's a proper manual way to control it yourself and not invalidate the entire website or page
– Fandango68Mar 18 '15 at 4:16

Make sure to use an HTML markup, not an ASP.Net control (ie no runat="server") for the textarea, then use the ASP.Net hidden control for the hidden. This is the best solution I've seen w/o compromising anything. Naturally, you want to parse your data for XSS, SQL Injection on the server side, but at least you can post HTML
– MC9000Jun 13 '15 at 7:50

escape(...) can take a long time. In my case, the markup was an entire (2MB) XML file. You might ask, "Why don't you just use <input type="file"... and... I agree with you :)
– The Red PeaSep 12 '16 at 18:18

ASP.NET by default validates all input controls for potentially unsafe contents that can lead to cross-site scripting (XSS) and SQL injections. Thus it disallows such content by throwing the above exception. By default it is recommended to allow this check to happen on each postback.

Solution

On many occasions you need to submit HTML content to your page through Rich TextBoxes or Rich Text Editors. In that case you can avoid this exception by setting the ValidateRequest tag in the @Page directive to false.

This will disable the validation of requests for the page you have set the ValidateRequest flag to false. If you want to disable this, check throughout your web application; you’ll need to set it to false in your web.config <system.web> section

<pages validateRequest ="false" />

For .NET 4.0 or higher frameworks you will need to also add the following line in the <system.web> section to make the above work.

The other solutions here are nice, however it's a bit of a royal pain in the rear to have to apply [AllowHtml] to every single Model property, especially if you have over 100 models on a decent sized site.

If like me, you want to turn this (IMHO pretty pointless) feature off site wide you can override the Execute() method in your base controller (if you don't already have a base controller I suggest you make one, they can be pretty useful for applying common functionality).

Just make sure that you are HTML encoding everything that is pumped out to the views that came from user input (it's default behaviour in ASP.NET MVC 3 with Razor anyway, so unless for some bizarre reason you are using Html.Raw() you shouldn't require this feature.

In my case, a user entered an accented character á in a Role Name (regarding the ASP.NET membership provider).

I pass the role name to a method to grant Users to that role and the $.ajax post request was failing miserably...

I did this to solve the problem:

Instead of

data: { roleName: '@Model.RoleName', users: users }

Do this

data: { roleName: '@Html.Raw(@Model.RoleName)', users: users }

@Html.Raw did the trick.

I was getting the Role name as HTML value roleName="Cadastro b&#225;s". This value with HTML entity &#225; was being blocked by ASP.NET MVC. Now I get the roleName parameter value the way it should be: roleName="Cadastro Básico" and ASP.NET MVC engine won't block the request anymore.

As long as these are only "<" and ">" (and not the double quote itself) characters and you're using them in context like <input value="this" />, you're safe (while for <textarea>this one</textarea> you would be vulnerable of course). That may simplify your situation, but for anything more use one of other posted solutions.

If you're just looking to tell your users that < and > are not to be used BUT, you don't want the entire form processed/posted back (and lose all the input) before-hand could you not simply put in a validator around the field to screen for those (and maybe other potentially dangerous) characters?

None of the suggestions worked for me. I did not want to turn off this feature for the whole website anyhow because 99% time I do not want my users placing HTML on web forms. I just created my own work around method since I'm the only one using this particular application. I convert the input to HTML in the code behind and insert it into my database.

Thank you for your interest in this question.
Because it has attracted low-quality or spam answers that had to be removed, posting an answer now requires 10 reputation on this site (the association bonus does not count).