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

时间:2020-03-05 18:58:33  来源:igfitidea点击:

每次用户在Web应用程序的页面中发布包含<或者>的内容时,都会引发此异常。

我不想讨论引发异常或者崩溃整个Web应用程序的明智性,因为有人在文本框中输入了字符,但是我正在寻找一种优雅的方式来解决这个问题。

捕获异常并显示

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

在我看来还不够专业。

禁用后验证(validateRequest =" false")绝对可以避免此错误,但是会使页面容易受到多种攻击。

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

有没有办法可以从处理程序做到这一点?

解决方案

回答

我们可以对文本框内容进行HTML编码,但是不幸的是,这不会阻止异常的发生。以我的经验,这是没有办法的,我们必须禁用页面验证。这样做是在说:"我会小心的,我保证。"

回答

我们应该使用Server.HtmlEncode方法来保护站点免受危险的输入。

更多信息在这里

回答

我认为我们尝试对所有发布的数据进行编码,从而从错误的角度对它进行了攻击。

请注意,"`<"也可能来自其他外部来源,例如数据库字段,配置,文件,提要等。

此外," <<"并不是天生的危险。这仅在特定情况下是危险的:在编写尚未编码为HTML输出的字符串时(由于XSS)。

在其他情况下,不同的子字符串很危险,例如,如果我们将用户提供的URL写入链接,则子字符串" javascript:"可能很危险。另一方面,单引号字符在SQL查询中插入字符串时很危险,但如果它是从表单提交的名称或者从数据库字段读取的名称的一部分,则绝对安全。

最重要的是:我们不能过滤随机输入的危险字符,因为在适当的情况下任何字符都可能是危险的。我们应该在某些特定字符可能会变得危险的地方进行编码,因为它们会跨入具有特殊含义的其他子语言。在将字符串写入HTML时,应使用Server.HtmlEncode对在HTML中具有特殊含义的字符进行编码。如果将字符串传递给动态SQL语句,则应该对不同的字符进行编码(或者更好的方法是,让框架通过使用准备好的语句等为我们完成此操作)。

当我们确定到处都进行HTML编码时,我们会将字符串传递给HTML,然后在.aspx文件中的<%@ Page ...%>指令中设置validateRequest =" false"

在.NET 4中,我们可能需要做更多一点。有时,还必须在Web.config(参考)中添加<httpRuntime requestValidationMode =" 2.0" />`。

回答

我想你可以在一个模块中做到;但这留下了一些问题;如果要将输入保存到数据库怎么办?突然因为将编码数据保存到数据库中,我们最终信任了来自数据库的输入,这可能不是一个好主意。理想情况下,我们将未编码的原始数据存储在数据库中,并且每次都进行编码。

更好的选择是在每页级别禁用保护,然后每次编码。

而不是使用Server.HtmlEncode,我们应该查看Microsoft ACE团队提供的更新,更完整的Anti-XSS库。

回答

只要这些只是" <"和">"(而不是双引号本身)字符,并且我们在诸如<input value =" this" />之类的上下文中使用它们,就可以安全使用(而对于<textarea >这一个</ textarea>,我们当然会很脆弱)。这可能会简化情况,但对于其他任何用途,请使用其他已发布的解决方案之一。

回答

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

页面验证存在一个安全漏洞,因此可以绕过该漏洞。同样,页面验证不应仅依赖于页面验证。

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

回答

如果我们只是想告诉用户<和>不会被使用,但是我们不希望整个表单事先处理/发回(并丢失所有输入),我们是否不能简单地将验证程序来筛选那些(可能还有其他潜在危险)字符?

回答

请记住,某些.NET控件将自动对输出进行HTML编码。例如,在TextBox控件上设置.Text属性将自动对其进行编码。这特别意味着将<<转换为<<,将>转换为>,将'&转换为'&`。所以要小心做...

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

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

做一些实验,看看什么被编码,什么没被编码。

回答

如果我们不想禁用ValidateRequest,则需要实现JavaScript函数,以避免发生异常。这不是最佳选择,但它可以工作。

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);")

回答

如果我们使用的是ASP.NET MVC,则有针对此错误的另一种解决方案:

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

样本:

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

Visual Basic示例:

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

回答

我们可以在Global.asax中捕获该错误。我仍然想验证,但显示适当的消息。在下面列出的博客上,可以找到类似的示例。

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();
        }
    }

重定向到另一个页面似乎也是对异常的合理响应。

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

回答

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

<httpRuntime requestValidationMode="2.0" />

在.NET 2.0中,请求验证仅适用于" aspx"请求。在.NET 4.0中,它已扩展为包括所有请求。我们可以通过指定以下内容恢复为仅在处理.aspx时执行XSS验证:

requestValidationMode="2.0"

我们可以通过指定完全禁用请求验证:

validateRequest="false"

回答

先前的答案很好,但是没有人说过如何排除单个字段以进行HTML / JavaScript注入验证。我不知道以前的版本,但是在MVC3 Beta中,我们可以执行以下操作:

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

这仍然会验证除排除字段以外的所有字段。这样做的好处是,验证属性仍然可以验证该字段,但是我们不会获得"从客户端检测到潜在的Request.Form值危险"异常。

我已经使用它来验证正则表达式。我已经创建了自己的ValidationAttribute来查看正则表达式是否有效。由于正则表达式可以包含类似于脚本的内容,因此我在上面的代码中应用了正则表达式,因此仍会检查正则表达式是否有效,但是如果正则表达式包含脚本或者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) {
    ...
}