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

Gena Makhomed gmm at csdoc.com
Tue Jun 17 10:35:52 UTC 2014


On 17.06.2014 10:00, Maxim Dounin wrote:

 >> Значения SERVER_NAME не может использоваться,
 >> если в директиве server_name используется маска
 >> или бекенд обрабатывает запросы для default_server.

 > Если SERVER_NAME нельзя использовать - значит, необходимо
 > передать дополнительный параметр, который и использовать.

Именно для этого и существует HTTP_HOST - передать
значение заголовка Host из валидного клиентского запроса.

 > Использовать HTTP_* поля для чего-то, что позволяет
 > "получить доступ" - это неправильно.

Если nginx не будет отправлять на backend невалидные клиентские запросы
- проблем с заголовком HTTP_HOST не будет никаких, - он будет валидным.

 > Проблема в том, что приложение некорректно предполагает, что
 > HTTP_HOST=private.example.com чем-то отличается от других.  Как
 > показывает пример запроса выше - это не так.  И "не так" - не
 > только в nginx'е, но и в других серверах.

А мы никаких других веб-серверов кроме nginx и не используем.
В IIS например, багов еще больше, чем в Apache, и что с того?

 > Не надо себя обманывать и пытаться закрыть nginx'ом небезопасную
 > логику приложения - это не работает и рано или поздно выстрелит.

Приложение было написано в соответствии со стандартами HTTP/1.1
и ожидало, что nginx не пропустит на backend невалидный запрос.

 > Правильное решение - передавать информацию о произошедшей
 > авторизации явно и отдельно (или пользоваться параметром
 > SERVER_NAME, который уже передаётся и предназначен специально для
 > идентификации сервера).

server {
   server_name www.example.com example.com;
   // ...
}

на backend в переменной SERVER_NAME уйдет всегда www.example.com
вне зависимости от того, к какому именно вирт. хосту был запрос.

переменную HTTP_HOST использовать нельзя.
неужели надо всем делать workaround

fastcgi_param  X_REAL_HTTP_HOST  $host;

и потом использовать переменную X_REAL_HTTP_HOST вместо HTTP_HOST ?

 > Возможно, когда-нибудь мы и придём к тому,
 > что в таких ситуациях будет возвращаться 400.

Что мешает сделать это прямо сейчас?

 > Но это ни коим образом не избавляет
 > от необходимости исправить приложение.

Сейчас - приходится имена виртуальных хостов прописывать
в двух местах - в настройках nginx и в настройках самого
приложения. И дополнительно валидировать HTTP_HOST, проверяя
входит ли это имя в список имен, которые были указаны в директиве
server_name, и были повторно прописаны в настройках приложения.
И если нет - то явно возвращать клиенту статус 400 Bad Request.

Есть стойкое ощущение, что это может и даже должен делать nginx.
Тогда имена хостов надо будет настраивать всего в одном конфиге.

Добавить этот workaround во все backend`ы, которые есть в мире -
это нереально, гораздо проще добавить валидацию запроса в nginx.

-- 
Best regards,
  Gena



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