从客户端检测到有潜在危险的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属性将自动对其进行编码。 这特别意味着将<
转换成<
, >
进入>
和&
。 所以要小心这样做…
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ás"
。 这个值与HTML实体á
被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(){targetText = 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。
更多信息在这里
- Rails国际化(I18n)模型validation:可能与否?
- 如何将我的DDD模型中的“用户”与validation用户进行集成?
- 如何在java中检查date
- 是否可以添加到Visual Studio的HTML5validation?
- ASP.NET .NET MVC禁用每个字段级别的客户端validation
- 如何获得一个<input type =“number”>字段的原始值?
- 使用Hibernate Validator进行交叉字段validation(JSR 303)
- validationRuby on Rails中has_many项目的数量
- 在表中为dynamic文本框设置类validation