允许双URL编码的请求路径有效

Mar*_*ker 8 asp.net validation iis-7 urlencode

我有一个标准的ASP.Net WebForms应用程序在IIS 7.0上运行,带有集成管理管道.我们网站上的许多图像都有文件名中的空格(例如'./baseball drawing.gif').当我们将这些图像放入我们的html页面时,我们会对路径进行编码,以便我们的html img标签看起来像这样<img src='./baseball%20drawing.gif' />

现在,当某些搜索引擎和webcrawler尝试索引我们的网站时,问题就出现了.当他们刮擦我们的页面时,他们将html编码我们已经html编码的路径获取像这样的图像链接'./baseball%2520drawing.gif',其中%25是'%'的url编码.这会导致两个问题:

  1. 当用户从这些搜索引擎获得结果时,他们会收到断开的链接
  2. 当用户尝试导航到这些损坏的链接时,它会在我们的系统中引发错误.

你可以看到这是一个失败的局面.用户得到断开的链接,我们的错误日志中会出现噪音.

我一直试图找出如何纠正这个问题没有运气.这是我尝试过的:

  1. <requestFiltering allowDoubleEscaping='true'>在web.config中设置以防止"404.11 URL Double Escaped error".这修复了第一个错误但导致了一个新错误,"发现了一个潜在危险的Request.Path".
  2. 从中删除'%' <httpRuntime requestPathInvalidChars>以防止"潜在危险的Request.Path"错误.这修复了第二个错误,但现在我们有第三个错误,"无法找到资源".
  3. 我在我的代码中休息了一下Request.Path.看起来它的值是'Ball Image.gif'而不是'Ball%2520Image.gif'.在这种情况下,我不确定它为什么不起作用.

我觉得我有一个超级黑客,我必须禁用一切,而不是真正理解为什么没有任何工作.所以我想我的问题是三折

  1. 为什么解决方案尝试1不解决问题?
  2. 为什么解决方案2没有解决问题?
  3. 为什么我的Request.Path在步骤3中看起来正确但它仍然不起作用?

任何人都可以提供任何帮助将不胜感激.

Mar*_*ker 18

好的,经过大量的互联网搜索和大量的实验,我想我终于明白了发生了什么.我的主要问题是一个极端确认偏见的情况.我读到的所有内容都说明了我想要听到的内容,而不是它实际上说的内容.为了回答我的问题,我将大大总结一下我需要理解的关键点.

  1. 首先,我需要了解IIS和ASP.Net是两个不同的应用程序.简而言之,IIS所做的是接收请求,将该请求路由到处理它的应用程序,从处理应用程序获取输出,然后将应用程序的输出发送回请求者.ASP.Net所做的是从IIS接收请求,处理它,然后将响应传递回IIS.这是整个过程的一个巨大的过度概括,但对于我的目的,它已经足够好了.1

  2. 传入的ASP.Net请求必须通过两个网守.IIS7 RequestFiltering模块(在system.webserver/requestFiltering 2中配置),然后是ASP.Net HttpRuntime请求过滤器(在system.web/httpRuntime 3中配置).

  3. IIS RequestFiltering模块是唯一一个规范化传入请求的模块,它只应用一次规范化.我再说一遍它只适用一次.即使<requestFiltering allowDoubleEscaping="true" />它仍然只应用一次归一化.这意味着'%2520'将被标准化为'%20'.此时,如果allowDoubleEscaping为false,IIS将不会让请求通过,因为'%20'仍然可以规范化.但是,如果allowDoubleEscaping设置为true,则IIS7会将请求'%20'传递给下一个网守ASP.Net.这是第一个错误的原因.

  4. Asp.net过滤器是检查requestPathInvalidCharacters的位置.所以现在我们的'%20'无效,因为默认情况下'%'是requestPathInvalidCharacters的一部分.如果我们从该列表中删除'%',我们将通过第二个网守,ASP.Net将尝试处理我们的请求.这是第二个错误的原因.

  5. 现在ASP.net将尝试将我们的虚拟路径转换为服务器上的物理路径.不幸的是,我们的路径中仍然有'%20'而不是''我们想要的,所以ASP.Net无法找到我们想要的资源并抛出"资源无法找到错误".当我打破我的代码时路径看起来正确的原因是因为我在Request.Url属性上放置了一个监视器.这个属性试图通过在其ToString()方法中应用自己的规范化来提供帮助,从而使我们的%20看起来像''我们想要的,即使它不是.这是最终错误的原因.

为了完成这项工作,我们可以编写自己的自定义模块,在前两个看门人之后接收请求,并在将其交给ASP.Net之前对其进行完全规范化.这样做虽然允许任何角色通过URL编码.例如,我们通常不希望在路径中允许"<"或">",因为这些可用于在我们的代码中插入标记.由于现在工作正常,<和>不会通过ASP.Net过滤器,因为它们是requestPathInvalidCharacters的一部分.但是,编码为%253C和%253E,如果我们打开前两个门然后在我们自己的自定义模块中规范化请求,然后将其交给ASP.Net.

总之,如果不创建大型安全漏洞,则无法完成允许%2520完全规范化.如果可以告诉RequestFiltering模块在针对前两个网守测试该请求之前完全规范化它接收的每个请求,那么它将更加安全,但现在功能不可用.

如果我有任何错误让我知道,我希望这有助于某人.