从客户端检测到潜在危险的 Request.Path 值 (&)

Posted

技术标签:

【中文标题】从客户端检测到潜在危险的 Request.Path 值 (&)【英文标题】:A potentially dangerous Request.Path value was detected from the client (&) 【发布时间】:2011-08-06 15:10:24 【问题描述】:

我明白为什么会发生这种情况,但我需要解决方法。我在 *** 上查看了其他一些问题,但没有一个有帮助。我不想禁用整个网站的输入验证,因为这绝对是危险的。我只有一个(至少现在)需要禁用输入验证的地方。

我使用 [ValidateInput(false)] 属性修饰了 Action Method,并且使用 html.Encode 对字符串进行了编码。但是,我仍然遇到同样的错误。这是我的看法:

<div id="sharwe-categories">
    <ul class="menu menu-vertical menu-accordion">
        @foreach(var topLevel in Model)
        
            var topLevelName = Html.Encode(topLevel.Name);
             <li class="topLevel">
                <h3>  
                    @Html.ActionLink(topLevel.Name, "Index", "Item", new  category = topLevelName , new @class = "main" )
                    <a href="#" class="drop-down"></a>
                </h3>
                <ul>
                    @foreach (var childCategory in topLevel.Children)
                    
                        var childcategoryName = Html.Encode(childCategory.Name);
                        <li>@Html.ActionLink(childCategory.Name, "Index", "Item", new RouteValueDictionary   "category", topLevelName ,  "subcategory", childcategoryName  , null)</li>
                    
                </ul>
            </li>
        

    </ul>

</div>

如您所见,没有用户输入。但是有些类别名称中有一些“危险”字符...有什么解决办法吗?

【问题讨论】:

你能提供导致问题的值吗? @Robert Koritnik:包含“&”或“,”或任何危险字符的值... 【参考方案1】:

您可能会发现following blog post 对于在 url 中使用特殊字符很有用。但一般来说,最好的做法是 replace those titles with slugs 与 *** 一样,在 url 中使用问题标题以获得更好的 SEO 并使用 id 来识别它们。

【讨论】:

但是使用 requestValidationMode v2 并使用 [ValidateInput(false)] 装饰 Action 方法是否安全?在我的应用程序中,安全性是重中之重,所以我不能冒任何风险...... @Kassem,ValidateInput(false) 属性用于将 HTML 发布到控制器操作。在 ASP.NET MVC 3 中,您可以使用 [AllowHtml] 属性来装饰视图模型属性,该属性将仅对更安全的该属性禁用请求验证。如果您使用AllowHtml 属性,则无需设置requestValidationMode="2.0"。如果您想将特殊字符作为 url 的一部分和您没有选择的路由参数发布,则需要遵循我链接到的博客文章中的建议。 除非他以某种方式更改类别命名...通常或仅在 URL 中使用时... @Robert Koritnik,是的,这正是我建议的两种解决方案之一:使用蛞蝓。 是的,你做到了。我同意。但是添加了 ID,我认为这在他的情况下是不可行的,因为它有多个类别。但是,是的。你做到了。【参考方案2】:

尽管 Darin 的答案完全可行,但我不建议使用 Scott Hanselman 逐步关闭所有这些验证的技术。你迟早会陷入深渊……

使用 ID 和虚拟字符串(这对 SEO 和人们非常有用)的第二个建议是一种可行的方法,但有时它们也不可行。想象一下这个请求 URL:

/111/Electronics/222/Computers/333/Apple

虽然我们有这些我们可以依赖的 ID 和人类/SEO 友好的类别名称,但这绝对不是我们想要的。当我们需要表示单个项目时,ID + Dummy string 是可行的。在其他情况下不是。而且由于您必须显示类别和子类别,这是一个问题。

那你能做什么?

两种可能的解决方案:

    将类别名称清理为仅包含有效字符 - 可以这样做,但如果这些不是静态的并且特权用户无法编辑,那么您在这里就不走运了,因为即使您现在已经清理了它们,稍后有人会输入无效的内容

    随时随地清理您的字符串 - 当您使用类别名称时,将其清理并在读取和使用它(以获取实际的类别 ID)时,您可以将提供的(先前清理的)类别名称与您在 DB 中的值进行比较随时清理:

      现在在过滤类别时 在生成类别名称之前

我建议您采用 2.2 方法。扩展您的数据库表以包含两列:

类别显示名称 类别 URL 友好名称

您还可以在第二列上设置唯一约束,这样就不会发生您的两个类别(即使它们具有不同的显示名称)具有相同的 URL 友好名称。

如何清洁

首先想到的是去除无效字符,但这非常繁琐,而且您很可能会遗漏一些内容。从您的类别显示名称中获取有效字符更加容易和明智。我在生成 dummy URL 类别名称时也做了同样的事情。只需取出有效的并将其余的放入垃圾箱。它通常工作得很好。此类正则表达式的两个示例:

    (\w2,) - 只使用字母、数字和下划线,并且至少使用其中两个(因此我们省略了 a 或单个数字和类似的东西,它们不会增加任何意义,并且会不必要地延长我们的 URL ([a-zA-Z0-9]2,) - 只有字母和数字(也是 2+)

获取您的类别显示名称中的所有匹配项,并用空格/破折号将它们连接起来,并与原始显示名称一起保存。一个不同的question of mine 正是与此有关。

为什么要增加一列?因为您无法在 SQL Server 中运行正则表达式。如果您使用的是 mysql,您可以使用一列并在 DB 上使用正则表达式。

【讨论】:

效果非常好!感谢您的建议,不胜感激:)【参考方案3】:

即使您不应该这样做……有时也没有一种简单的方法可以绕过它。 web.Config 中 httpRuntime 标记上的 requestPathInvalidCharacters 是您所寻求的。只需在 部分输入以下内容:

&lt;httpRuntime requestPathInvalidCharacters="&amp;lt;,&amp;gt;,*,%,:,\" /&gt;

我强烈建议使用以下方法锁定它:

<location path="the/path/you/need/to/lock/down">
    <system.web>
        <httpRuntime requestPathInvalidCharacters="&lt;,&gt;,*,%,:,\"/>
    </system.web>
</location>

只需将其放入根 标记中即可。这样...您不会打开整个站点以允许路径中出现 & 符号...并可能使整个站点遭受无法预料的攻击。

【讨论】:

以上是关于从客户端检测到潜在危险的 Request.Path 值 (&)的主要内容,如果未能解决你的问题,请参考以下文章

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

从客户端中检测到有潜在危险值的解决办法

从客户端中检测到有潜在危险的 request.form值[解决方法]

从客户端中检测到有潜在危险的 request.form值[解决方法]

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

如何处理“从客户端检测到潜在危险的 Request.Form 值”?