Как стать автором
Обновить

Комментарии 51

Здесь есть ещё один неприятный момент.
Встречался в Битриксе, но всплыть может ещё где-нибудь.
Условия:
— Веб-сервер отвечает на любой хост одним сайтом
— Относительные URL на сайте приводятся к полным URL с включением хоста
— Результатирующая страница кешируется
— Есть ещё какие-нибудь домены, ссылающиеся на наш IP

Кто-то делает запрос на левый домен, кеш истек, а страница кешируется с адресами с этим левым доменом. В итоге может появиться множество «зеркал» сайта с разными хостами.
Более того, пользователь зашедший с правильного домена и попавший на кеш с левым доменом, уйдет на этот левый домен.
Я думал, что эти переменные нельзя переопределить. Теперь буду знать, спасибо!

P.S. Слава Богу нигде не использую :)
Их не просто так назвали переменными.
А зачем парня заминусовали? Человек не постеснялся сказать, что чего-то не знал — так это же хорошо. Такие вещи нужно наоборот поощрять.
Никто опытным не рождается. Я как раз для таких людей и писал заметку.
Решение проблемы для Nginx есть, а с Apache как быть?
А с апачем это не прокатит, по-моему.
По крайней мере сейчас попробовал на локалхосте — Apache 2.2.22, не прокатывает.
Если запрос
GET http://www.site.lo/hosttest.php
Host: xxx
То SERVER_NAME правильный, а HTTP_HOST'а вообще нет.
Все логично. Если первая строка без указания протокола, то последующие заголовки не будут учтены. Соответственно, HTTP_HOST будет пустой.
Попробуйте так:
GET http://www.site.lo/hosttest.php HTTP/1.1
Host: xxx
В самой заметке есть же ссылка по Apache. В частности, должно быть UseCanonicalName Off.
А, сорри, я почему-то понял пример так, что надо как раз без протокола отправлять запрос.
Да, с указанием протокола действительно HTTP_HOST меняется… Но SERVER_NAME в апаче, правда, остаётся правильный, а всякие **внобитриксы, кстати, используют SERVER_NAME, а не HTTP_HOST, насколько я помню.
Блин. А вот MediaWiki, между прочим, уязвима, в том числе её последние версии. Она сначала проверяет HTTP_HOST, и только потом SERVER_NAME (ну т.е., уязвима, если в конфиге гвоздями имя сервера не забить).
Похоже зашлю в геррит патчик, чтобы она хотя бы на SERVER_NAME сначала смотрела — он явно покорректней будет…
лучше пусть на host смотрит :) А то, как показано выше, NgX за server_name считает тот хост, что первым указан в этой директиве, а не тот, куда пришёл запрос :(
Довольно интересно.
Я так понимаю что если у меня в nginx перечислены все возможные server_name и default_server ведет на страничку 404 то все нормально?
Не совсем. В статье есть пример с таким вот запросом через telnet
GET http://site3.dev/phpinfo.php HTTP/1.1
Если имя сервера передано в первой строке запроса, то в дальше оно может быть переопределено. Host:~%#$^&*()<>?@\!."'{}[]=+|
Можно ограничиться защитой только на стороне Nginx, но для этого стоит явно определить переменную HTTP_HOST: fastcgi_param HTTP_HOST $host;
Если сервер отвечает на любой хост своим сайтом, то это кроме всего прочего уязвимость — DNS Rebinding.
Если хост не сматчился — нужно отдавать страницу, что-то типа «This host is not found on our server», пример.
В общем-то как мне кажется это не уязвимость, а типичный мисконфигурейшин.
Ну дефолтный виртхост должен всегда отдавать или что-то типа 403 или редиректа…
Любой мисконфигурейшин может стать уязвимостью и многие (не все) уязвимости есть следствие мисконфигурейшина.
В HTTP_HOST кроме подмены самого хоста можно передать непредусмотренную последовательность символов.
Я так и не понял, где уязвимость дальше чем «нам отдадут не тот виртуальный хост».
Автор, сдается мне, немного не в ту сторону ушел.
Уязвимость можно реализовать подменой, например, HTTP_REFERER или HTTP_USER_AGENT, при условии что они где-то на стороне сервера вообще как-то обрабатываются.
К сожалению, именно HTTP_HOST часто оставляют без валидации. Хотя все эти переменные начинаются с HTTP_, что как бы намекает. А вот с SERVER_NAME менее очевидно.
Автор просто не раскрыл тему до конца. Точнее как-то двумя строчками ограничился в разделе «уязвимости».
В общем, суть в том, что если разработчик просто подставляет данные, например, из переменной $_SERVER['HTTP_HOST'], без какой-либо фильтрации при работе с базой — то мы можем провести sqli. Похожее задание было на phdays quals, краткий врайтап по ссылке.

Предложенный способ защиты на php является костылём и говорит о том, что программист не до конца понимает работу HTTP и работу виртуальных хостов. Как уже верно подметили, нужно просто четко и явно матчить HOST, а все, что не наше — отдавать 404, 403 или редирект.
В общем, суть в том, что если разработчик просто подставляет данные, например, из переменной $_SERVER['HTTP_HOST'], без какой-либо фильтрации при работе с базой — то мы можем провести sqli.

Да сколько же раз говорить, что при работе с базой все данные нужно трактовать одинаково (кроме тех, которые мы порождаем сами внутри security boundary)? И все эти защиты на уровне конфигов веб-сервера к этому никакого отношения не имеют.
Да я абсолютно согласен :)
Но не сказал бы, что не имеют. Порой на плечи админов ложится лишняя нагрузка, из-за программистов, которые не уделяют нужное внимание security (проблема многих проектов). Как, порой, и наоборот, когда в директории кладут пустые index.html, если по каким-то причинам не получается отключить индексирование (переопределение в .htaccess запрещено) или вообще используется nginx и до админа не достучаться.
Порой на плечи админов ложится лишняя нагрузка, из-за программистов, которые не уделяют нужное внимание security (проблема многих проектов).

Лучше бейте программистов. Это полезнее.

Костыли в безопасности — опасная вещь.
вот вот. должна быть единая идеология — архитектура по управлению данными, внезависимости откуда ты их взял. тут помоеж т ORM
… и ORM тут тоже не при чем совершенно. То, о чем вы говорите — задача DAL в произвольном виде, вне зависимости от используемого шаблона.
Совершенно верно. Добавлю, что я не ставил себе цели описать все возможные векторы атак, а лишь пытался дать предостережение тем программистам и системным администраторам, которые не придавали этим переменным должного внимания.
Как показывает практика, это не такая уж и редкость.
Все, что начинается с HTTP_* можно «подделать». Но это не подделка, это просто данные полученные от клиента.
>Получение доступа к приватным данным
SQL-инъекции

таки где демо? чем эта переменная круче REFERRER например который тоже могут теоретически не фильтровать? 0day?
Фильтровать нужно только если используется. Ничем не круче REFERRER. Я к сожалению, сейчас не найду, но на том же Гитхабе видел подключение конфигурационных файлов по полученному имени хоста. Потенциально это дыра.
То есть с одной стороны программисты не фильтруют, т.к. это должно быть сконфигурировано админами, а админы оставляют на откуп программистам. Возьмите любой шаред хостинг и почти наверняка получится повторить приведенные в посте примеры.
Может поделитесь способом подменять REFERRER? Есть просто проблема, флеш баннеры в упор не хотят передавать REFERRER.
с помощью искусственного запроса, можно и реферрер подделать и IP, и прокси
подделать и IP

ну с 'HTTP_X_FORWARDED_FOR' понятно все, а вот как REMOTE_ADDR искусственным запросом подделать очень даже интересно послушать
REMOTE_ADDR http заголовками не подделаешь, но бывают совсем отмороженные админы, которые настраивают сервер так, что при отправке заголовка X-Forwarded-For: fail_IP воспринимают fail_IP как настоящий. Сам такое видел.
В наказание таким админам и их клиентам как раз и появился вот этот github.com/marson/XForwardedForHeader аддон.
Еще есть случаи когда в закрытой части сайта делают редирект на страницу входа,
а в теле все равно страница, например админки,
НЛО прилетело и опубликовало эту надпись здесь
НЛО прилетело и опубликовало эту надпись здесь
НЛО прилетело и опубликовало эту надпись здесь
НЛО прилетело и опубликовало эту надпись здесь
Если скрипт должен собирать статистику в БД, а программист не ожидает подвоха, то вполне возможно. Понятно, что данные перед записью в БД должны фильтроваться в любом случае.
Еще в самом первом комментарии прекрасный пример XSS — нарочно и не придумаешь.
НЛО прилетело и опубликовало эту надпись здесь
Ну а пример «Получение доступа к приватным данным»?
habrahabr.ru/post/166855/#comment_5855369 — короче что то подключается по имени хоста. Наиболее вероятное использование в парковочных движках.
А в чем суть нолика в слове HOST -> H0ST?
Может опечатка? А где вы увидели нолик?
Почти везде. В некоторых шрифтах особенно заметно:



Причем, в коде так же. Я думал, может какое-то хитрое вуду на этом замешано :)
Английская O находится аккурат под 0, пару раз сам так случайно опечатывался
Наверное единственная опечатка без потери смысла/орфографии :)
Если бы человек опечатывался, то был бы не 0, а ")", потому что это слово набирается с шифтом.
В данном случае 0 набрано сознательно. Быть может для защиты от скрипт-кидди, но это явно слишком просто.
Прямо целая теория заговора на моих глазах родилась :)
Где вы там все же нули видите, я не пойму?
Нет там никаких нулей у меня!
Действительно нет. Но вы же не будете разрушать нашу красивую, загадочную теорию заговора? Впишите нули в текст! :)
пардон, а чем HTTP_HOST безопаснее любых других суперглобалов? экранировать все в любом случае!
Данный баг был например в CMS е107. Там в шаблон включалась переменная основаная на HTTP_HOST, для вставки картинок на сайте. Далее производилась замена псевдопеременных на данные используя preg_replace с модификатором /e
Как итог, выполнение произвольного кода, который мог присутствовать в HTTP_HOST ввиде {phpinfo();}, и решением была замена preg_replace на preg_replace_callback, но использование HTTP_HOST так никто и не переписал.
Зарегистрируйтесь на Хабре, чтобы оставить комментарий

Публикации