Re: Об одной малоизвестной уязвимости в веб сайтах

S.A.N nginx-forum at nginx.us
Mon Jun 16 19:36:38 UTC 2014


> > 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.

Ещё раз приведу пример, в котором мы легко можем получить доступ, к закрытым
на уровне 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

В данном случаи можно было бы использовать переменную SERVER_NAME, но я выше
писал почему это не всегда возможно.

Если мы оба понимаем, что ситуация когда authority component и значения Host
разные, это исключительная ситуация и её нужно обрабатывать как Exception, в
этом случаи есть три варианта поведения, выбросить Exception (отдать 400
статус), исправить ошибку (использовать переменую $host), и самый плохой
вариант (антишаблон) ничего не делать и не обрабатывать эту исключительную
ситуацию и оставить все как есть.

Posted at Nginx Forum: http://forum.nginx.org/read.php?21,246086,250896#msg-250896



Подробная информация о списке рассылки nginx-ru