从客户端检测到有潜在危险的Request.Form值

每当用户在我的Web应用程序的一个页面中发布一个包含<>东西时,我就会抛出这个exception。

我不想讨论抛出exception或者崩溃整个Web应用程序的聪明之处,因为有人在文本框中input了一个字符,但是我正在寻找一个优雅的方式来处理这个问题。

捕获exception并显示

发生错误请返回并重新input整个表单,但这次请不要使用<

对我来说似乎不够专业。

禁用后validation( validateRequest="false" )肯定会避免这个错误,但会使页面容易受到多次攻击。

理想情况下:当发布包含HTML限制字符的回发时,表单集合中的发布值将自动进行HTML编码。 所以我的文本框的.Text属性将是something & lt; html & gt; something & lt; html & gt;

有一种方法,我可以从处理程序做到这一点?

我认为你是从错误的angular度来攻击它,试图编码所有发布的数据。

请注意,“ < ”也可能来自其他外部来源,如数据库字段,configuration,文件,提要等等。

此外,“ < ”不是固有的危险。 在特定的上下文中,这只是一个危险的事情:编写未被编码为HTML输出的string(由于XSS)。

在其他上下文中,不同的子string是危险的,例如,如果您将用户提供的URL写入链接,则子string“ javascript: ”可能是危险的。 另一方面,在SQL查询中插入string时,单引号字符是危险的,但如果它是从表单提交的名称或从数据库字段读取的名称的一部分,则是完全安全的。

底线是:你不能过滤危险字符的随机input,因为任何字符在正确的情况下可能是危险的。 你应该对某些特定字符进行编码,因为这些字符会跨越不同的子语言,并具有特殊的含义。 在向HTML写入string时,应使用Server.HtmlEncode对HTML中具有特殊含义的字符进行编码。 如果你传递一个string到一个dynamic的SQL语句,你应该编码不同的字符(或者更好的,让框架为你做准备语句等)。

如果您确信HTML编码是将string传递给HTML,则在.aspx文件的<%@ Page ... %>指令中设置validateRequest="false"

在.NET 4中,你可能需要做更多的事情。 有时还需要在web.config( reference )中添加<httpRuntime requestValidationMode="2.0" />

如果您使用ASP.NET MVC,则会出现此错误的不同解决scheme:

  • ASP.NET MVC – 页面validateRequest = false不起作用?
  • 为什么是ValidateInput(False)不工作?
  • ASP.NET MVC RC1,VALIDATEINPUT,潜在的危险请求和PITFALL

Visual Basic示例:

 <AcceptVerbs(HttpVerbs.Post), ValidateInput(False)> _ Function Edit(ByVal collection As FormCollection) As ActionResult ... End Function 

C#示例:

 [HttpPost, ValidateInput(false)] public ActionResult Edit(FormCollection collection) { // ... } 

在ASP.NET MVC 3中,您可以将AllowHtml属性添加到模型的属性中。

它允许请求在模型绑定期间通过跳过属性的请求validation来包含HTML标记。

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

如果您使用的是.NET 4.0,请确保将其添加到<system.web>标记中的web.config文件中:

 <httpRuntime requestValidationMode="2.0" /> 

在.NET 2.0中,请求validation仅适用于aspx请求。 在.NET 4.0中,这个扩展包含了所有的请求。 在处理.aspx时,您可以恢复为执行XSSvalidation,方法是指定:

 requestValidationMode="2.0" 

您可以通过指定完全禁用请求validation:

 validateRequest="false" 

对于ASP.NET 4.0,您可以将标记全部放在<location>元素中,以允许标记作为特定页面的input,而不是整个站点。 这将确保您的其他网页都是安全的。 您不需要将.aspx页面中的ValidateRequest="false"

 <configuration> ... <location path="MyFolder/.aspx"> <system.web> <pages validateRequest="false" /> <httpRuntime requestValidationMode="2.0" /> </system.web> </location> ... </configuration> 

在web.config中控制这个是比较安全的,因为你可以在站点级别看到哪些页面允许标记作为input。

您仍然需要以编程方式validation禁用请求validation的页面上的input。

以前的答案是伟大的,但没有人说如何排除一个单一的字段validation的HTML / JavaScript注入。 我不知道以前的版本,但在MVC3testing版中,你可以这样做:

 [HttpPost, ValidateInput(true, Exclude = "YourFieldName")] public virtual ActionResult Edit(int id, FormCollection collection) { ... } 

这仍然validation除了排除的一个之外的所有字段。 关于这一点的好处是您的validation属性仍然validation字段,但是您只是没有得到“从客户端检测到有潜在危险的Request.Form值”exception。

我用这个来validation一个正则expression式。 我做了我自己的ValidationAttribute,看看正则expression式是否有效。 由于正则expression式可以包含看起来像脚本的东西,所以我应用了上面的代码 – 如果正则expression式是有效的,它仍然被检查,但是如果它包含脚本或HTML,则不会被检查。

在ASP.NET MVC中,您需要在web.config中设置requestValidationMode =“2.0”和validateRequest =“false”,并将ValidateInput属性应用于您的控制器操作:

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

 [Post, ValidateInput(false)] public ActionResult Edit(string message) { ... } 

你可以用HTML编码文本框的内容,但不幸的是,这不会阻止发生的exception。 根据我的经验,没有办法,你必须禁用页面validation。 通过这样做,你说:“我会小心,我保证。”

对于MVC,通过添加忽略inputvalidation

[ValidateInput(假)]

在Controller的每个Action之上。

你可以在Global.asax中捕获这个错误。 我仍然想validation,但显示一个适当的消息。 在下面列出的博客中,可以使用这样的示例。

  void Application_Error(object sender, EventArgs e) { Exception ex = Server.GetLastError(); if (ex is HttpRequestValidationException) { Response.Clear(); Response.StatusCode = 200; Response.Write(@"[html]"); Response.End(); } } 

redirect到另一个页面似乎也是对exception的合理回应。

http://www.romsteady.net/blog/2007/06/how-to-catch-httprequestvalidationexcep.html

请记住,一些.NET控件会自动对输出进行HTML编码。 例如,在TextBox控件上设置.Text属性将自动对其进行编码。 这特别意味着将<转换成&lt;>进入&gt;&amp; 。 所以要小心这样做…

 myTextBox.Text = Server.HtmlEncode(myStringFromDatabase); // Pseudo code 

但是,HyperLink,Literal和Label的.Text属性不会对HTML进行编码,所以要包装Server.HtmlEncode(); 如果要防止<script> window.location = "http://www.google.com"; </script>则必须在这些属性上设置任何内容<script> window.location = "http://www.google.com"; </script> <script> window.location = "http://www.google.com"; </script>从输出到你的页面,然后执行。

做一点实验,看看什么是编码,什么不是。

这个问题的答案很简单:

 var varname = Request.Unvalidated["parameter_name"]; 

这将禁用特定请求的validation。

在web.config文件的标签中,插入带有requestValidationMode =“2.0”属性的httpRuntime元素。 还要在pages元素中添加validateRequest =“false”属性。

例:

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

如果你不想禁用ValidateRequest,你需要实现一个JavaScript函数来避免这个exception。 这不是最好的select,但它的工作。

 function AlphanumericValidation(evt) { var charCode = (evt.charCode) ? evt.charCode : ((evt.keyCode) ? evt.keyCode : ((evt.which) ? evt.which : 0)); // User type Enter key if (charCode == 13) { // Do something, set controls focus or do anything return false; } // User can not type non alphanumeric characters if ( (charCode < 48) || (charCode > 122) || ((charCode > 57) && (charCode < 65)) || ((charCode > 90) && (charCode < 97)) ) { // Show a message or do something return false; } } 

然后在后面的代码中,在PageLoad事件中,使用下一个代码将该属性添加到您的控件中:

 Me.TextBox1.Attributes.Add("OnKeyPress", "return AlphanumericValidation(event);") 

现在似乎还没有人提到,但它解决了我的问题。 而之前有人说是的,这是Visual Basic …糟糕。

 <%@ Page Language="vb" AutoEventWireup="false" CodeBehind="Example.aspx.vb" Inherits="Example.Example" **ValidateRequest="false"** %> 

我不知道是否有任何缺点,但对我来说这是惊人的。

另一个解决scheme是

 protected void Application_Start() { ... RequestValidator.Current = new MyRequestValidator(); } public class MyRequestValidator: RequestValidator { protected override bool IsValidRequestString(HttpContext context, string value, RequestValidationSource requestValidationSource, string collectionKey, out int validationFailureIndex) { bool result = base.IsValidRequestString(context, value, requestValidationSource, collectionKey, out validationFailureIndex); if (!result) { // Write your validation here if (requestValidationSource == RequestValidationSource.Form || requestValidationSource == RequestValidationSource.QueryString) return true; // Suppress error message } return result; } } 

在ASP.NET中,你可以捕获exception并做一些事情,比如显示一个友好的消息或者redirect到另一个页面…另外你也可以自己处理validation。

显示友好的信息:

 protected override void OnError(EventArgs e) { base.OnError(e); var ex = Server.GetLastError().GetBaseException(); if (ex is System.Web.HttpRequestValidationException) { Response.Clear(); Response.Write("Invalid characters."); // Response.Write(HttpUtility.HtmlEncode(ex.Message)); Response.StatusCode = 200; Response.End(); } } 

我想你可以在一个模块中做到这一点。 但是这留下了一些问题; 如果你想保存input到数据库呢? 突然之间,因为你将编码的数据保存到数据库,你最终信任它的input,这可能是一个坏主意。 理想情况下,您每次都将原始的未编码数据存储在数据库和编码中。

禁用每页级别的保护,然后每次编码是一个更好的select。

而不是使用Server.HtmlEncode,您应该查看来自Microsoft ACE团队的更新,更完整的Anti-XSS库 。

这里的其他解决scheme是很好的,但是对于不得不将每个模型属性应用[AllowHtml]的情况来说,这是一种皇室般的痛苦,特别是如果你在一个相当规模的站点上有100多个模型。

如果像我一样,你想把这个(恕我直言,毫无意义的)functionclosures现场,你可以覆盖你的基本控制器中的Execute()方法(如果你还没有一个基础控制器,我build议你做一个,他们可以对于应用通用function非常有用)。

  protected override void Execute(RequestContext requestContext) { // Disable requestion validation (security) across the whole site ValidateRequest = false; base.Execute(requestContext); } 

只要确保你是HTML编码的东西是从用户input的意见(这是在ASP.NET MVC 3的默认行为与剃刀无论如何,所以除非有一些奇怪的原因,你使用Html.Raw()你不应该要求这个function。

如果您使用的是框架4.0,那么web.config(<pages validateRequest =“false”/>)

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

如果你使用的是框架4.5,那么web.config(requestValidationMode =“2.0”)中的条目

 <system.web> <compilation debug="true" targetFramework="4.5" /> <httpRuntime targetFramework="4.5" requestValidationMode="2.0"/> </system.web> 

我也得到这个错误。

就我而言,用户在“angular色名称”(关于ASP.NET成员资格提供者)中input了重音符号á

我把angular色名称传递给一个方法来授予用户这个angular色, $.ajax post请求失败了…

我这样做是为了解决这个问题:

代替

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

做这个

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

@Html.Raw做的伎俩。

我将angular色名称作为HTML值roleName="Cadastro b&#225;s" 。 这个值与HTML实体&#225; 被ASP.NET MVC阻止。 现在我得到的roleName参数值应该是这样的: roleName="Cadastro Básico"和ASP.NET MVC引擎不会阻止该请求了。

原因

ASP.NET默认validation所有input控件是否可能导致跨站点脚本 (XSS)和SQL注入的不安全内容。 因此通过抛出上述exception来禁止这样的内容。 默认情况下,build议在每次回发时进行检查。

在很多情况下,您需要通过Rich TextBox或Rich Text Editors将HTML内容提交到您的页面。 在这种情况下,您可以通过将@Page指令中的ValidateRequest标记设置为false来避免此exception。

 <%@ Page Language="C#" AutoEventWireup="true" ValidateRequest = "false" %> 

这将禁止validation你设置ValidateRequest标志为false的页面的请求。 如果你想禁用这个,请检查整个Web应用程序; 您需要在您的web.config <system.web>部分将其设置为false

 <pages validateRequest ="false" /> 

对于.NET 4.0或更高版本的框架,您还需要在<system.web>部分中添加以下行来完成上述工作。

 <httpRuntime requestValidationMode = "2.0" /> 

而已。 我希望这可以帮助你摆脱上述问题。

引用方式: ASP.Net错误:从客户端检测到有潜在危险的Request.Form值

如果您确实需要特殊字符(如>< ,等),请禁用页面validation。然后确保显示用户input时,数据是HTML编码的。

页面validation存在安全漏洞,因此可以绕过。 此外,页面validation不应该完全依赖。

请参阅: http : //www.procheckup.com/PDFs/bypassing-dot-NET-ValidateRequest.pdf

您也可以使用JavaScript的转义(string)函数来replace特殊字符。 然后服务器端使用Server。 URLDecode(string)切换回来。

这样你就不必closuresinputvalidation,而且其他程序员可以更清楚地知道string可能含有HTML内容。

我find了一个解决scheme,使用JavaScript来编码数据,这是在.NET解码(并不需要jQuery)。

  • 使文本框的HTML元素(如textarea),而不是一个ASP。
  • 添加一个隐藏的字段。
  • 将以下JavaScript函数添加到您的标题。

    函数boo(){ta​​rgetText = document.getElementById(“HiddenField1”); sourceText = document.getElementById(“userbox”); targetText.value = escape(sourceText.innerText); }

在你的textarea中,join一个叫做boo()的onchange:

 <textarea id="userbox" onchange="boo();"></textarea> 

最后在.NET中使用

 string val = Server.UrlDecode(HiddenField1.Value); 

我知道这是单向的 – 如果你需要双向的,你必须有创意,但是如果你不能编辑web.config,这将提供一个解决scheme

以下是我(MC9000)通过jQuery提出并使用的示例:

 $(document).ready(function () { $("#txtHTML").change(function () { var currentText = $("#txtHTML").text(); currentText = escape(currentText); // Escapes the HTML including quotations, etc $("#hidHTML").val(currentText); // Set the hidden field }); // Intercept the postback $("#btnMyPostbackButton").click(function () { $("#txtHTML").val(""); // Clear the textarea before POSTing // If you don't clear it, it will give you // the error due to the HTML in the textarea. return true; // Post back }); }); 

和标记:

 <asp:HiddenField ID="hidHTML" runat="server" /> <textarea id="txtHTML"></textarea> <asp:Button ID="btnMyPostbackButton" runat="server" Text="Post Form" /> 

这很好。 如果黑客试图绕过JavaScript,他们只会看到错误。 您可以将所有这些数据保存在数据库中,然后在服务器端对其进行parsing,并在显示其他地方之前parsing并检查攻击。

我最终在每次回发之前使用JavaScript来检查您不想要的字符,例如:

 <asp:Button runat="server" ID="saveButton" Text="Save" CssClass="saveButton" OnClientClick="return checkFields()" /> function checkFields() { var tbs = new Array(); tbs = document.getElementsByTagName("input"); var isValid = true; for (i=0; i<tbs.length; i++) { if (tbs(i).type == 'text') { if (tbs(i).value.indexOf('<') != -1 || tbs(i).value.indexOf('>') != -1) { alert('<> symbols not allowed.'); isValid = false; } } } return isValid; } 

授予我的网页主要是数据录入,并且回传的元素很less,但是至less保留了他们的数据。

如果你只是想告诉你的用户,<和>不能被使用,但是你不希望整个表单被处理/返回(并且丢失所有的input)validation器周围的字段来筛选这些(也可能是其他潜在的危险)字符?

没有任何build议为我工作。 我不想为整个网站closures这个function,因为99%的时间我不希望我的用户把HTML放在网页上。 我只是创build了自己的工作方法,因为我是唯一使用这个特定的应用程序。 我在后面的代码中将input转换为HTML,并将其插入到我的数据库中。

你可以使用像这样的东西:

 var nvc = Request.Unvalidated().Form; 

后来, nvc["yourKey"]应该工作。

您应该使用Server.HtmlEncode方法来保护您的网站免受危险的input。

更多信息在这里