Hello! On Mon, Jun 16, 2014 at 03:36:38PM -0400, S.A.N wrote:
> > > Maxim Dounin Wrote: > > > ------------------------------------------------------- > > > > Какая-либо проблема появляется тогда и только > > > > тогда, когда администратор начинает писать в конфиге $http_host, > > > > не думая о последствиях. Есть мнение, что совсем простое решение > > > > этой проблемы - не делать так (c) анекдот. > > > > > > Вся проблема в том что сами программисты Nginx в модуле FastCGI > > используют > > > переменную $http_host для HTTP_HOST, вместо нормализованной > > переменой $host, > > > администраторам на оборот приходится исправлять это своими руками и > > писать в > > > конфиге > > > fastcgi_param HTTP_HOST $host; > > > Если следовать вашей логике, надо изменить код модуля FastCGI, чтобы > > по > > > умолчанию Nginx был вполне себе безопасный. > > > > По умолчанию в fastcgi http-заголовки передаются как есть, в виде > > параметров HTTP_*. Каноническое же имя сервера доступно в > > параметре SERVER_NAME. Что из этого и как использовать - это > > вопрос к приложению, а не к nginx'у. > > Я знаю, и уже выше объяснял почему бекенд-приложениям нужно использовать > HTTP_HOST вместо SERVER_NAME. > Значения SERVER_NAME не может использоваться, если в директиве server_name > используется маска или бекенд обрабатывает запросы для default_server. Если SERVER_NAME нельзя использовать - значит, необходимо передать дополнительный параметр, который и использовать. Использовать HTTP_* поля для чего-то, что позволяет "получить доступ" - это неправильно. > Ещё раз приведу пример, в котором мы легко можем получить доступ, к закрытым > на уровне Nginx ресурсам. > > server > { > server_name *.example.com; > ... > fastcgi_pass php; > } > > server > { > server_name private.example.com; > > location / { > allow 192.168.1.0/24; > deny all; > > fastcgi_pass php; > > auth_request /auth; > } > ... > } > > Как видно два хоста используют один upstream, на котором бекенд приложения > даёт расширенные привилегии юзерам private.example.com, в расчете на то что > Nginx предварительно сделал проверку по IP и успешно провел аунтификацию, > всё вроде логично и удобно сделано, но такая схема легко ломается таким > запросом. > > GET http://example.com/SecureData/ HTTP/1.1 > Host: private.example.com > > Бекенд получает HTTP_HOST=private.example.com, даёт юзеру привилегии, но > Nginx не проводил проверки по IP и не делал запрос аунтификацию, потому что > отработал хост конфигурации для example.com вместо private.example.com Проблема в том, что приложение некорректно предполагает, что HTTP_HOST=private.example.com чем-то отличается от других. Как показывает пример запроса выше - это не так. И "не так" - не только в nginx'е, но и в других серверах. Не надо себя обманывать и пытаться закрыть nginx'ом небезопасную логику приложения - это не работает и рано или поздно выстрелит. Правильное решение - передавать информацию о произошедшей авторизации явно и отдельно (или пользоваться параметром SERVER_NAME, который уже передаётся и предназначен специально для идентификации сервера). > В данном случаи можно было бы использовать переменную SERVER_NAME, но я выше > писал почему это не всегда возможно. > > Если мы оба понимаем, что ситуация когда authority component и значения Host > разные, это исключительная ситуация и её нужно обрабатывать как Exception, в > этом случаи есть три варианта поведения, выбросить Exception (отдать 400 > статус), исправить ошибку (использовать переменую $host), и самый плохой > вариант (антишаблон) ничего не делать и не обрабатывать эту исключительную > ситуацию и оставить все как есть. Возможно, когда-нибудь мы и придём к тому, что в таких ситуациях будет возвращаться 400. Но это ни коим образом не избавляет от необходимости исправить приложение. -- Maxim Dounin http://nginx.org/ _______________________________________________ nginx-ru mailing list nginx-ru@nginx.org http://mailman.nginx.org/mailman/listinfo/nginx-ru