我有一个标准的ASP.Net WebForms应用程序,它运行在带有集成管理管道的IIS 7.0上。我们网站上的许多图片都有文件名中的空格(例如'./baseball drawing.gif'
)。当我们将这些图像放入我们的html页面时,我们会对路径进行编码,以便我们的html img标记看起来像这样< img src='./baseball%20drawing.gif' />
现在,当某些搜索引擎和webcrawler尝试索引我们的网站时,会出现问题。当他们刮擦我们的页面时,他们会对我们已经html编码的路径进行html编码,获取像'./baseball%2520drawing.gif'
这样的图像链接,其中%25
是'%'的网址编码。这导致两个问题:
正如你所看到的,这是一种失败的局面。用户会收到断开的链接,我们会在错误日志中收到噪音。
我一直试图找出如何纠正这个问题而没有运气。这是我尝试过的:
<requestFiltering allowDoubleEscaping='true'>
以防止“404.11 URL Double Escaped error”。这修复了第一个错误但引发了一个新错误,“发现了一个潜在危险的Request.Path”。<httpRuntime requestPathInvalidChars>
中删除'%'以防止“潜在危险的Request.Path”错误。这修复了第二个错误,但现在我们有第三个错误,“无法找到资源”。Request.Path
。看起来它的值是'Ball Image.gif'而不是'Ball%2520Image.gif'。在这种情况下,我不确定它为什么不起作用。我觉得我有一个超级黑客,我必须禁用所有内容,而不是真正理解为什么没有任何工作。所以我想我的问题是三折
任何人都可以提供的帮助将不胜感激。
答案 0 :(得分:18)
好的,经过大量的互联网搜索和大量的实验,我想我终于明白了发生了什么。我的主要问题是一个极端确认偏见的情况。我读到的所有内容都说明了我想要听到的内容,而不是它实际上说的内容。为了回答我的问题,我将大大总结一下我需要理解的要点。
首先,我需要了解IIS和ASP.Net是两个不同的应用程序。简而言之,IIS所做的是接收请求,将该请求路由到处理它的应用程序,从处理应用程序获取输出,然后将应用程序的输出发送回请求者。 ASP.Net所做的是从IIS接收请求,处理它,然后将响应传递回IIS。这是对整个过程的过度概括,但就我的目的而言,这已经足够了。1
传入的ASP.Net请求必须通过两个网守。 IIS7 RequestFiltering模块(在system.webserver / requestFiltering 2中配置),然后是ASP.Net HttpRuntime请求过滤器(在system.web / httpRuntime 3中配置)。
IIS RequestFiltering模块是唯一一个规范化传入请求的模块,它只应用一次规范化。我再说一遍它只适用一次。即使<requestFiltering allowDoubleEscaping="true" />
,它仍然只会应用一次规范化。这意味着&#39;%2520&#39;将被标准化为&#39;%20&#39;。此时如果allowDoubleEscaping为false,IIS将不会让请求通过,因为&#39;%20&#39;仍然可以正常化。但是,如果allowDoubleEscaping设置为true,则IIS7将传递请求&#39;%20&#39;到下一个看门人,ASP.Net。这是第一次错误的原因。
Asp.net过滤器是检查requestPathInvalidCharacters的地方。所以现在我们的&#39;%20&#39;是无效的,因为默认情况下&#39;%&#39;是requestPathInvalidCharacters的一部分。如果我们删除了&#39;%&#39;从该列表我们将通过第二个看门人,ASP.Net将尝试处理我们的请求。这是第二次错误的原因。
现在,ASP.net将尝试将我们的虚拟路径转换为服务器上的物理路径。不幸的是,我们仍然有一个&#39;%20&#39;在我们的道路而不是&#39; &#39;我们希望ASP.Net无法找到我们想要的资源,并且无法找到资源错误&#34;。当我打破我的代码时路径看起来正确的原因是因为我在Request.Url属性上放置了一个监视器。这个属性试图通过在其ToString()方法中应用自己的规范化来提供帮助,从而使我们的%20看起来像&#39; &#39;我们想要它,即使它不是。这是最终错误的原因。
为了完成这项工作,我们可以编写自己的自定义模块,在前两个看门人之后接收请求,并在将其交给ASP.Net之前对其进行完全规范化。这样做虽然允许任何角色通过URL编码。例如,我们通常不希望允许&#39;&lt;&#39;或者&#39;&gt;&#39;在我们的路径中,因为这些可用于在我们的代码中插入标签。随着事情的发展,&lt;和&gt;不会超过ASP.Net过滤器,因为它们是requestPathInvalidCharacters的一部分。但是,编码为%253C和%253E,如果我们打开前两个门,然后在我们自己的自定义模块中规范化请求,然后再将其交给ASP.Net。
总之,允许%2520完全标准化不会造成大的安全漏洞。如果可以告诉RequestFiltering模块在针对前两个看门人测试该请求之前完全规范化它接收到的每个请求,那么它将更加安全,但现在功能不可用。
如果我有任何错误让我知道,我希望这有助于某人。
答案 1 :(得分:0)
如果您想允许双重转义,您可以按照说明进行操作 http://www.iis.net/ConfigReference/system.webServer/security/requestFiltering
它在IIS 7.0上对我有用,无需其他配置。双重转义对我实现的网站代码没有影响;我不知道其他网站可能带来的安全隐患。