Опасно ли включение двойного побега?

136

У меня есть приложение ASP.NET MVC с маршрутом, который позволяет искать вещи через / search / <searchterm>.

Когда я предоставляю "search / abc", он работает хорошо, но когда я предоставляю "/ search / a + b + c" (правильно закодированный URL), IIS7 отклоняет запрос с ошибкой HTTP 404.11 ( модуль фильтрации запросов настроен на запрет запрос, содержащий двойную escape-последовательность ). Прежде всего, почему он это делает? Кажется, что только выдает ошибку, если она является частью URL, но не как часть строки запроса (/ передача? Q = a + b + c работает нормально).

Теперь я мог включить двойные запросы на экранирование в разделе безопасности моего web.config, но я не решаюсь это сделать, так как не понимаю последствий, а также почему сервер не отклонит запрос «a + b + c» как часть URL, но принять как часть строки запроса.

Может кто-нибудь объяснить и дать совет, что делать?

Alex
источник
7
Я также попробовал, возможно, более правильный вариант вызова Server.Url Path Encode и в итоге получил /search/a%2520b%2520cразметку, которая привела к прекрасной ошибке «Потенциально опасное значение Request.Path было обнаружено из клиента (%)». Вы не можете выиграть, кажется.
Жаф - Бен Дугид,

Ответы:

158

Изменить: Добавлен акцент на соответствующие разделы.

В основном: IIS чрезмерно параноидален. Вы можете безопасно отключить эту проверку, если вы ничего не делаете особенно неразумно с декодированными URI-данными (например, генерируете локальные URI файловой системы с помощью конкатенации строк).

Чтобы отключить проверку, сделайте следующее ( отсюда ): (см. Мой комментарий ниже, что влечет за собой двойное экранирование).

<system.webServer>
    <security>
        <requestFiltering allowDoubleEscaping="true"/>
    </security>
</system.webServer>

Если символ плюса является допустимым символом в поисковом вводе, вам нужно включить «allowDoubleEscaping», чтобы IIS мог обрабатывать такой ввод из пути URI.

Наконец, очень простой, но ограниченный обходной путь - просто избежать «+» и использовать вместо него «% 20». В любом случае, использование символа «+» для кодирования пробела является недопустимым кодированием URL , но характерно для ограниченного набора протоколов и, вероятно, широко поддерживается в целях обратной совместимости. Если только для целей канонизации, вам все равно лучше кодировать пробелы как «% 20»; и это приятно обходит проблему IIS7 (которая все еще может возникать для других последовательностей, таких как% 25ab.)

Имон Нербонн
источник
3
Я бы отключил проверку. Это хлопотно и не обеспечивает дополнительную безопасность для большинства приложений.
Имон Нербонн
3
У вас есть ссылка / ссылка, что довольно безопасно отключить двойное экранирование? Кроме того, что именно предотвращает эта мера безопасности?
Алекс
15
Если для uri используется двойное экранирование, то неэкранированные компоненты uri сами могут содержать зарезервированные символы и, следовательно, (части) неэкранированного uri могут сами по себе быть действительным uri. Короче говоря, если вы используете неэкранированную строку URI для создания новых URI - в частности путей файловой системы - и вам не удается корректно избежать нового пути, вы можете разрешить внедрение пути. Инъекция пути может позволить злоумышленнику обманом заставить вашу программу обрабатывать данные, которые она не должна, или вводить их в заблуждение, полагая, что два URI отличаются, когда они фактически идентичны, но просто кодируются по-разному.
Имон Нербонн
4
@Stijn: Да, это безопасно . Все, что делает эта проверка, это отфильтровывает запросы, которые могут быть неверно истолкованы ошибочным кодом (особенно если вы выполняете двойное декодирование или сборку Uri через string-concat и без надлежащего кодирования). Вы не выполняете никакой обработки, так что это в значительной степени автоматически безопасно с вашей стороны. Любая ошибка должна быть в основном коде файловой службы IIS, и я думаю, мы можем с уверенностью предположить, что это было очень, очень тщательно протестировано в настоящее время. Опять же, эта проверка ничего особенного, она просто спасает вещи, которые могут быть декодированы, а затем выглядят как закодированный URI.
Имон Нербонн
2

Я просто хотел бы добавить некоторую информацию к ответу Иамона Нербонна, касающуюся части « что делать » в вашем вопросе (без объяснения причин).
Вы также можете легко изменить настройки конкретного приложения с

  1. открытие консоли с правами администратора (Пуск - cmd - щелчок правой кнопкой мыши, Запуск от имени администратора)
  2. введите следующее (взято здесь: http://blogs.iis.net/thomad/archive/2007/12/17/iis7-rejecting-urls-conisting.aspx ):

    %windir%\system32\inetsrv\appcmd set config "YOURSITENAME" -section:system.webServer/security/requestfiltering -allowDoubleEscaping:true

    (например , вы можете заменить YOURSITENAMEс Default Web Siteдля применения этого правила сайта по умолчанию)

  3. Войдите, готово.

Пример:

  1. во первых у меня была такая же проблема: Ошибка HTTP 404.11 - Модуль фильтрации запросов настроен на отклонение запроса, который содержит двойную escape-последовательность.
  2. Набрав в тексте, упомянутом выше: Drupal7-другой Решение ошибки HTTP 404.11 - Модуль фильтрации запросов настроен на отклонение запроса, который содержит двойную escape-последовательность.
  3. Теперь все работает как положено: Решение ошибки HTTP 404.11 - Модуль фильтрации запросов настроен на отклонение запроса, который содержит двойную escape-последовательность.
Sk8erPeter
источник
1

Задумывались ли вы о поисковом URL-адресе, например «/ search / a / b / c»?

Вам нужно настроить маршрут как

search/{*path}

А затем извлеките значения поиска из строки пути в действии.

HTHs
Charles

Charlino
источник
Проблема в том, что другие символы в кодировке URL (включая сам символ /) могут быть частью поиска.
Алекс
Не могли бы вы закодировать все «/», которые фактически являются частью поиска, в «% 2F»?
Чарлино
0

Я столкнулся с этим в IIS 7.5, выполняя Server.TransferRequest () в приложении.

Кодирование имени файла вызвало проблему двойного выхода, но если я не закодировал его, я столкнулся бы с ошибкой «потенциально опасный Request.Path» .

Помещение любого протокола, даже пустого, в URL, который я передаю Server.TranferRequest (), устранил проблему.

Не работает:

context.Server.TransferRequest("/application_name/folder/bar%20bar.jpg");

Работает:

context.Server.TransferRequest("://folder/bar%20bar.jpg");
mhenry1384
источник