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


每次用户发布包含的内容 < 要么 > 在我的Web应用程序的页面中,我抛出了这个异常。

我不想进入关于抛出异常或崩溃整个Web应用程序的聪明性的讨论,因为有人在文本框中输入了一个字符,但我正在寻找一种优雅的方法来处理这个问题。

捕获异常并显示

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

对我来说似乎不够专业。

禁用后验证(validateRequest="false")肯定会避免这个错误,但它会使页面容易受到一些攻击。

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

有没有办法可以从处理程序中执行此操作?


1326
2017-09-17 10:58


起源


请注意,如果输入中也包含HTML实体名称(&amp;)或实体编号('),则可能会出现此错误。 - Drew Noakes
好吧,因为这是我的问题,我觉得我可以定义实际的重点:崩溃整个应用程序进程并返回一般错误消息,因为有人输入'<'是过度的。特别是因为你知道大多数人只是'validateRequest = false'来摆脱它,从而重新打开漏洞 - Radu094
@DrewNoakes:根据我的测试(在.Net 4.0中测试),实体名称(&amp;)似乎不是问题,尽管实体编号(')确实未通过验证(正如您所说)。如果使用.Net Reflector反汇编System.Web.CrossSiteScriptingValidation.IsDangerousString方法,您将看到代码专门针对html标记(以<开头)和实体编号(以&#开头) - Gyum Fox
使用默认MVC项目在VS2014中创建一个新站点并运行它。单击注册链接,添加任何电子邮件,然后使用“<P455-0r [!”作为密码。开箱即用的相同错误,没有尝试做任何恶意的事情,密码字段将不会显示,因此它不会是XSS攻击,但修复它的唯一方法是使用ValidateInput完全删除验证(false) ? AllowHtml建议在这种情况下不起作用,仍然会出现同样的错误。从客户端检测到潜在危险的Request.Form值(Password =“<P455-0r [!”)。 - stephenbayer
TL; DR put <httpRuntime requestValidationMode="2.0" /> 在web.config中


答案:


我认为你是通过尝试编码所有发布的数据从错误的角度攻击它。

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

此外,“<“本质上并不危险。在特定的上下文中它只是危险的:当编写未编码为HTML输出的字符串时(因为XSS)。

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

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

什么时候 您确定在将字符串传递给HTML的任何地方进行HTML编码,然后进行设置 validateRequest="false" 在里面 <%@ Page ... %> 你的指令 .aspx 文件(S)。

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


996
2017-09-17 11:26



对于那些迟到的人:validateRequest =“false”进入Page指令(.aspx文件的第一行) - MGOwen
提示:放 <httpRuntime requestValidationMode="2.0" /> 在位置标记中,以避免从您的网站的其余部分中删除验证提供的有用保护。 - Brian
在MVC3中,这是 [AllowHtml] 在模型属性上。 - Jeremy Holovacs
@MGOwen你也可以通过提交页面指令到web.config <pages validateRequest="false" /> 在 <system.web />。这样做会将属性应用于所有页面。 - oliver-clare
在MVC4中, [ValidateInput(false)] 作品。 - Adam K Dean


如果您使用的是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

467
2017-10-08 22:56



当需要在整个应用程序的一个页面上时,可能会出现问题
您还可以在类级别添加[ValidateInput(false)]属性。如果将其添加到基本控制器类,它将应用于所有控制器方法操作。 - Shan Plourde
@Zack感谢您的解决方案。另一方面,我想知道是否 [AllowHtml] 比...更好 ValidateInput(false)因为 [AllowHtml]对于属性(即编辑器字段)立即定义,无论何时使用它,都不需要将其用于多个操作。你有什么建议? - Clint Eastwood
@Zack Peterson使用安全吗?没有安全问题? - shrey Pav


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

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

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

361
2017-09-05 09:33



声明性地比在控制器中做得更好! - Andiih
唯一正确的答案!禁用控制器操作的验证是hacky。并且要在应用程序级别禁用验证,必须挂起开发人员! - trailmax
美丽!这是它的方式 应该 做完了。 - beautifulcoder
@AnthonyJohnston它还能用于MVC 4和MVC 5吗?谢谢... - Clint Eastwood
有什么区别 ValidateInput(false) 和 AllowHtml?一个优于另一个的优势是什么?我什么时候想用 AllowHtml 代替 ValidateInput(false)?我什么时候想用 ValidateInput(false) 过度 AllowHtml?我什么时候想要同时使用?使用两者都有意义吗? - Ian Boyd


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

<httpRuntime requestValidationMode="2.0" />

在.NET 2.0中,请求验证仅适用于 aspx 要求。在.NET 4.0中,这扩展到包括 所有 要求。你可以恢复 只要 在处理时执行XSS验证 .aspx 通过指定:

requestValidationMode="2.0"

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

validateRequest="false"

203
2017-07-30 04:51



在 - 的里面 <system.web> 标签。 - Hosam Aly
我把它放在web.config中,但仍然是错误“一个有潜在危险的Request.Form值” - Filip
看起来<httpRuntime requestValidationMode =“2.0”/>仅在计算机上安装2.0框架时才有效。如果没有安装2.0框架但只安装了4.0框架怎么办? - Samuel
这完全适合我。其他答案中的步骤文档都不是必需的(包括validateRequest =“false”)! - tom redfern
这解决了我当前的问题。谢谢! - Dyrborg


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

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

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

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


102
2017-11-27 17:22



有关requestValidationMode = 2 | 4的更多信息: msdn.microsoft.com/en-us/library/... - GlennG
遗憾的是,这不适用于ASP.net 2.0。删除httpRuntime行,它将工作。 - Fandango68
你还有validateRequest =“false” - 非常糟糕! - MC9000
我添加了一个警告,提醒人们在禁用验证时手动验证输入。 - Carter Medlin
这个解决方案非常适合我。谢谢。 - aspnetdeveloper


之前的答案很棒,但没有人说过如何排除单个字段的HTML / JavaScript注入验证。我不知道以前的版本,但在MVC3 Beta中你可以这样做:

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

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

我用它来验证正则表达式。我已经创建了自己的ValidationAttribute来查看正则表达式是否有效。由于正则表达式可以包含看起来像脚本的东西,我应用了上面的代码 - 如果正则表达式有效,它仍然被检查,但如果它包含脚本或HTML则不会被检查。


68
2017-11-06 14:58



可悲的是,它似乎从MVC 3 RTW中删除了排除功能:( - Matt Greer
它也不包含在MVC 4中 - wilsjd
使用 [AllowHtml] 在模型的属性而不是 [ValidateInput] 在Action上实现相同的最终结果。 - Mrchief
@gligoran是 [AllowHtml] 比...更好 ValidateInput(false) 对于编辑器字段?因为 [AllowHtml]对于属性(即编辑器字段)立即定义,无论何时使用它,都不需要将其用于多个操作。你有什么建议? - Clint Eastwood
@Christof请注意,我的答案是5岁。我很久没有遇到过这个问题了,所以可能有更好的方法来处理它。关于这两个选项我认为这取决于你的情况。也许您在多个动作中公开该模型,在某些地方允许HTML或不允许HTML。在这种情况下 [AllowHtml] 不是一个选择。我建议看一下这篇文章: weblogs.asp.net/imranbaloch/...,但它也有些陈旧,可能已经过时了。 - gligoran


在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) {
    ...
}

46
2017-11-30 12:56



为了我, validateRequest="false" 只是没有必要 requestValidationMode="2.0" - tom redfern
requestValidationMode =“2.0”仍然使用HTMLencoded数据生成错误。没有解决方案除了base64编码所有内容,然后发送它。 - MC9000


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


45
2017-09-17 11:20





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

[ValidateInput(假)]

在控制器中的每个动作之上。


42
2018-01-29 09:40



在通过配置的路由到达控制器方法的情况下,这似乎不起作用。 - PandaWood
实际上,技术解释是,这仅在违规字符在“查询字符串”中时才有效...如果它在请求路径中,则验证属性 才不是 工作 - PandaWood
谢谢。有效。 - Baqer Naqvi