ПРОЕКТЫ 


  АРХИВ 


Apache-Talk @lexa.ru 

Inet-Admins @info.east.ru 

Filmscanners @halftone.co.uk 

Security-alerts @yandex-team.ru 

nginx-ru @sysoev.ru 


  СТАТЬИ 


  ПЕРСОНАЛЬНОЕ 


  ПРОГРАММЫ 



ПИШИТЕ
ПИСЬМА












     АРХИВ :: nginx-ru
Nginx-ru mailing list archive (nginx-ru@sysoev.ru)

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: proxy cache key и fastcgi cache key



On 10.01.2014 12:24, Валентин Бартенев wrote:

Кому интересно почитать, подробней вот ссылка.
http://habrahabr.ru/post/166855/

Как видите, корректное значения имеют только переменные $host и
$server_name, все что основывается на $http_host имеет потенциал
уязвимость, если бекенд доверяет этой переменой, лично я знаю несколько
популярных РНР фрейморков которые используют эту переменную без проверки
и без экранирования в SQL запросах.

и пофиксить эту проблему можно в исходниках nginx таким образом,
что если вдруг в переменных $host и $http_host оказываются разные
значения, чтобы nginx в $http_host записывал значение из $host.

тогда после установки следующего обновления nginx эта уязвимость
в backend`ах автоматически пофиксится у всех пользователей nginx.

причем без какой-либо необходимости пользователям править
файлы fastcgi.conf / fastcgi_params и все производные от них.

Так, между делом, хочу напомнить, что на CGI есть спецификация, описывающая
все переменные окружения, которые сервер должен передавать приложению.
И в ней вполне черным по белому сказано, что все переменные HTTP_* это
protocol specific переменные полученные из заголовков переданных клиентом.

fastcgi_param   HTTP_HOST1              $http_host;
fastcgi_param   HTTP_HOST2              $host;
fastcgi_param   HTTP_HOST3              $server_name;

Делаем запрос:
GET http://site3.dev/phpinfo.php HTTP/1.1
Host:~%#$^&*()<>?@\!."'{}[]=+|

На выходе получим
_SERVER["HTTP_HOST1"]: ~%#$^&*()<>?@\!."'{}[]=+|
_SERVER["HTTP_HOST2"]: site3.dev
_SERVER["HTTP_HOST3"]: site2.dev

В переменной $host правильное значение,
в переменной $http_host все что угодно.

А ведь именно на основании значения переменной $host
nginx и принимает решение в какой server направить запрос
на обработку. Но к FastCGI уходит не $host, с которым
работал nginx принимая решение, а fake-значение из $http_host

Они то protocol specific, но раз запрос клиента попал в server
где в server_name прописано site3.dev - клиент искренне полагает,
что надлежащую проверку уже провел nginx, ведь в конфиге пользователь
прописал:

server {
    listen      80 default_server;
    return      444;
}

B значит все другие значения HTTP_HOST, которые не соответствуют
нормальным значениям server_name должны попадать в этот server-заглушку.
Поэтому валидировать еще раз то, что и так уже провалидировал nginx
никакого смысла нет. С точки зрения обычных пользователей, коих 99.999%.
Я и сам так считал до недавнего времени, доверяя документации nginx:

http://nginx.org/en/docs/http/request_processing.html

http://nginx.org/en/docs/http/server_names.html

http://nginx.org/en/docs/http/ngx_http_core_module.html#server_name

И есть безопасная и специфицированная переменная SERVER_NAME.

она есть такая только для FastCGI, а для proxy_pass
на апач - все не так просто, если погуглить
server_name http_host site:bugs.php.net

тем более, что в SERVER_NAME со стороны веб-сервера
будет приезжать каноническое имя сервера, а это обычно hostname.
и для всех виртуальных хостов будет одинаковое значение SERVER_NAME.

путаницы с этим хватает: https://stackoverflow.com/questions/1459739/

Поэтому те кто пишут на php не могут доверять значению SERVER_NAME,
и у них остается единственный вариант - только переменная HTTP_HOST.

Если кто-то в приложении использует данные полученные от клиента без
надлежащей проверки, когда в любой книжке "web-programming for dummies"
написано по 5 раз, что не следует доверять этим данным, то что я могу
предложить?  Расстрел.

Они проверяют и валидируют значение HTTP_HOST средствами nginx,
так как это прописано в документации к nginx, и рекомендовано разработчиками nginx. Зачем два раза проверять одно и то же?

Как будто мало разработчикам проблем с самим php
и его глюками, например, cgi.fix_pathinfo 1 по умолчанию:
http://habrahabr.ru/post/100961/#comment_3125990

Так теперь еще и с nginx при использовании php-fpm
эти глюки. А ведь php-fpm это наверное основной уже
способ как использовать php и nginx.

Попробую иначе спросить: что может поломать предложенный
мной выше fix, который будет закрывать эту уязвимость в backend`ах,
которые доверяют значению переменной HTTP_HOST полученной от nginx?

"Самый эффективный способ защиты ? явно определить HTTP_HOST на стороне веб сервера." - цитата из статьи http://habrahabr.ru/post/166855/

Сейчас же nginx по-умолчанию отправляет на backend
значения $proxy_host и $http_host вместо ожидаемого там $host.
Если глюк с $proxy_host очевиден, то глюк с $http_host совсем нет.

Способы решения проблемы:

1. Расстрелять всех, кто пишет кривой код. - Нереально.

2. Исправить все глюки и весь кривой код. - Нереально.

3. Всем вручную добавить fix в fastcgi_param HTTP_HOST $host;

4. Добавить этот fix в дефолтовые конфиги nginx.

5. Исправить это один раз в коде nginx и забыть про проблему.

Способ ?5 самый простой в реализации и 100% эффективный метод защиты.

Почему "нет" ?

P.S.

Например, вот сколько "магии" наворотили в модуле кеширования,
и незаметное (недокументированное) трансформирование HEAD в GET,
и незаметное (недокументированное) вырезание заголовков
If-Modified-Since и If-None-Match и выключение кеширования,
если в ответе присутствует заголовко Set-Cookie и т.д. и т.п.

А такую мелочь с передачей на backend валидного значения $host,
которая никому не будет мешать и только принесет max. пользу...

--
Best regards,
 Gena

_______________________________________________
nginx-ru mailing list
nginx-ru@xxxxxxxxx
http://mailman.nginx.org/mailman/listinfo/nginx-ru


 




Copyright © Lexa Software, 1996-2009.