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

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

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

捕获异常并显示

发生错误,请返回并重新输入整个表格,但是这次请不要使用 <

在我看来还不够专业。

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

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

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

答案

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

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

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

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

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

确定将 HTML 字符串传递给 HTML 的所有地方都经过 HTML 编码后,请在.aspx文件的<%@ Page ... %>指令中设置validateRequest="false"

在. NET 4 中,您可能需要做更多的事情。有时,还必须将<httpRuntime requestValidationMode="2.0" />到 web.config( 参考 )。

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

C#示例:

[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

在 ASP.NET MVC(从版本 3 开始)中,可以将AllowHtml属性添加到模型的属性中。

通过跳过属性的请求验证,它允许请求在模型绑定期间包括 HTML 标记。

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

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

<httpRuntime requestValidationMode="2.0" />

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

requestValidationMode="2.0"

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

validateRequest="false"

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

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

在 web.config 中进行控制比较安全,因为您可以在站点级别看到哪些页面允许标记作为输入。

您仍然需要以编程方式验证禁用请求验证的页面上的输入。

先前的答案很棒,但是没有人说过如何排除单个字段以进行 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) {
    ...
}

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

对于 MVC,请通过添加忽略输入验证

[ValidateInput(false)]

在控制器中每个动作上方。

您可以在 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