Разрешить допустимые пути запроса с двойным URL - PullRequest
8 голосов
/ 07 января 2012

У меня есть стандартное приложение ASP.Net WebForms, работающее на IIS 7.0 с интегрированным управляемым конвейером. Многие изображения на нашем сайте имеют пробелы в именах файлов (например, './baseball drawing.gif'). Когда мы помещаем эти изображения в наши html-страницы, мы url кодируем пути так, чтобы наши html img-теги выглядели так <<code>img src='./baseball%20drawing.gif' />

Теперь проблема возникает, когда некоторые поисковые системы и веб-сканеры пытаются проиндексировать наш сайт. Когда они очищают наши страницы, они будут html-кодировать наши уже html-закодированные пути, получая ссылки на изображения, подобные './baseball%2520drawing.gif', где %25 - это кодировка URL для «%». Это вызывает две проблемы:

  1. Когда пользователи получают результаты из этих поисковых систем, они получают неработающие ссылки.
  2. Когда пользователи пытаются перейти к этим неработающим ссылкам, это вызывает ошибки в нашей системе.

Как видите, ситуация проигрышная. Пользователи получают неработающие ссылки, и мы слышим шум в наших журналах ошибок.

Я безуспешно пытался выяснить, как исправить эту проблему. Вот что я попробовал:

  1. Установите <requestFiltering allowDoubleEscaping='true'> в файле web.config, чтобы предотвратить ошибку 404.11 URL Double Escaped. Это исправило первую ошибку, но вызвало новую, «потенциально опасный Request.Path найден».
  2. Удалил '%' из <httpRuntime requestPathInvalidChars>, чтобы предотвратить ошибку "потенциально опасный Request.Path". Это исправило вторую ошибку, но теперь у нас есть третья, «Ресурс не найден».
  3. Я поставил перерыв в своем коде, чтобы посмотреть Request.Path. Похоже, что это правильно со значением «Ball Image.gif» вместо «Ball% 2520Image.gif». Учитывая это, я не уверен, почему это не работает.

Я чувствую, что у меня супер-хак, где мне приходится все отключать, не понимая, почему ничего не работает. Итак, я думаю, мой вопрос в три раза

  1. Почему попытка решения 1 не решает проблему?
  2. Почему решение 2 не решило проблему?
  3. Почему мой Request.Path выглядит правильно на шаге 3, но все равно не работает?

Буду очень признателен за любую помощь.

Ответы [ 2 ]

18 голосов
/ 14 января 2012

ОК, после долгих поисков в интернете и множества экспериментов, я думаю, что наконец понял, что происходит.Моей главной проблемой был крайний уклон подтверждения.Все, что я читал, говорило о том, что я хотел услышать, а не о том, что на самом деле говорилось.Я собираюсь кратко изложить ключевые моменты, которые мне нужно было понять, чтобы ответить на мой вопрос.

  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 полностью нормализовать каждый полученный им запрос перед тестированием этого запроса к первым двум привратникам, то было бы намного безопаснее, но сейчас эта функциональность недоступна.

Если бы я получилчто-нибудь не так, дайте мне знать, и я надеюсь, что это кому-нибудь поможет.

0 голосов
/ 08 января 2012

Если вы хотите разрешить двойное экранирование, вы можете следовать инструкциям на http://www.iis.net/ConfigReference/system.webServer/security/requestFiltering

. Это сработало для меня на IIS 7.0, без дополнительной настройки.Двойное экранирование не влияет на код веб-сайта, на котором я его реализовал;Я не знаю, какие потенциальные последствия для безопасности могут быть для других сайтов.

...