Php net http host

PHP $ _SERVER [‘HTTP_HOST’] против $ _SERVER [‘SERVER_NAME’], правильно ли я понимаю справочные страницы?

По-видимому, обсуждение в основном о $_SERVER[‘PHP_SELF’] и почему вы не должны использовать его в атрибуте action формы без надлежащего экранирования для предотвращения атак XSS.

Мой вывод о моем первоначальном вопросе выше заключается в том, что «безопасно» использовать $_SERVER[‘HTTP_HOST’] для всех ссылок на сайте, не беспокоясь о атак XSS, даже если они используются в формах.

Пожалуйста, поправьте меня, если я ошибаюсь.

8 ответов

Это, наверное, все сначала подумали. Но это немного сложнее. См. статья Криса Шифлетта SERVER_NAME Versus HTTP_HOST .

Кажется, что нет серебряной пули. Только когда вы вынудите Apache использовать каноническое имя, вы всегда получите правильное имя сервера с помощью SERVER_NAME .

Итак, вы либо идете с этим, либо проверяете имя хоста на белый список:

$allowed_hosts = array('foo.example.com', 'bar.example.com'); if (!isset($_SERVER['HTTP_HOST']) || !in_array($_SERVER['HTTP_HOST'], $allowed_hosts))

Лол, я прочитал эту статью, и она, похоже, не отвечала на мой вопрос. Какой из них используют профессиональные разработчики? Если либо.

Интересно, я никогда не знал, что SERVER_NAME по умолчанию использует введенные пользователем значения в Apache.

@Jeff, Для серверов, на которых размещено более одного субдомена, у вас есть только два варианта $_SERVER[‘SERVER_NAME’] и $_SERVER[‘HTTP_HOST’] (кроме реализации некоторых других пользовательских рукопожатий, основанных на запросе пользователя). Профессиональные разработчики не доверяют вещам, которые они не понимают полностью. Таким образом, они либо настроили свой SAPI совершенно правильно (в этом случае выбранный параметр даст правильный результат), либо они составят белый список так, что не имеет значения, какие значения поставляются SAPI.

@ Gumbo, вам нужно применить патч «port» из-за серьезных проблем с некоторыми SAPI. Кроме того, array_key_exists более масштабируем по сравнению с in_array который имеет производительность O (n).

@Pacerier array_key_exists и in_array делают разные вещи, прежние проверки ключей, последующие значения, поэтому вы не можете просто поменять их местами. Кроме того, если у вас есть массив из двух значений, вам не стоит беспокоиться о производительности O (n) .

Еще одно примечание: если сервер работает на порту, отличном от 80 (как это может быть распространено на машине разработки/интрасети), то HTTP_HOST содержит порт, а SERVER_NAME — нет.

$_SERVER['HTTP_HOST'] == 'localhost:8080' $_SERVER['SERVER_NAME'] == 'localhost' 

(По крайней мере, то, что я заметил в виртуальных хостах на базе Apache)

Как отметил Майк ниже, HTTP_HOST не содержит :443 при работе на HTTPS (если вы не работаете на нестандартном порту, который я не тестировал).

Другими словами, значение HTTP_HOST не является параметром Host: предоставленным пользователем. Это просто основано на этом.

@Pacerier Нет, все наоборот: HTTP_HOST — это именно то поле Host:, которое было предоставлено вместе с HTTP-запросом. Порт является его частью, и браузеры не упоминают его, когда он используется по умолчанию (80 для HTTP; 443 для HTTPS)

Это подробный перевод того, что Symfony использует для получения имени хоста (см. второй пример для более буквального перевода):

function getHost() < $possibleHostSources = array('HTTP_X_FORWARDED_HOST', 'HTTP_HOST', 'SERVER_NAME', 'SERVER_ADDR'); $sourceTransformations = array( "HTTP_X_FORWARDED_HOST" =>function($value) < $elements = explode(',', $value); return trim(end($elements)); >); $host = ''; foreach ($possibleHostSources as $source) < if (!empty($host)) break; if (empty($_SERVER[$source])) continue; $host = $_SERVER[$source]; if (array_key_exists($source, $sourceTransformations)) < $host = $sourceTransformations[$source]($host); >> // Remove port number from host $host = preg_replace('/:\d+$/', '', $host); return trim($host); > 

Это мой перевод на пустой PHP метода, используемого в платформе Symfony, который пытается получить имя хоста всеми возможными способами в порядке лучшей практики:

function get_host() < if ($host = $_SERVER['HTTP_X_FORWARDED_HOST']) < $elements = explode(',', $host); $host = trim(end($elements)); >else < if (!$host = $_SERVER['HTTP_HOST']) < if (!$host = $_SERVER['SERVER_NAME']) < $host = !empty($_SERVER['SERVER_ADDR']) ? $_SERVER['SERVER_ADDR'] : ''; >> > // Remove port number from host $host = preg_replace('/:\d+$/', '', $host); return trim($host); > 

этот код вредит моему мозгу! .. пожалуйста, ради любви к бабочкам, не пишите свой код таким образом! (извините за мой английский)

@showdev Я действительно нахожу «трудно» читать оператор условия, например if ($host = $_SERVER[‘HTTP_X_FORWARDED_HOST’]) или x = a == 1 ? True : False В первый раз, когда я увидел это, мой мозг искал инстанцирования $ host и ответа на вопрос «почему только один» = «знак?». Я начинаю не любить слабые языки программирования. Все написано по-другому. Вы не экономите время, и вы не особенный. Я не пишу код таким образом, потому что по прошествии времени я должен отлаживать его. Выглядит очень грязно для усталого мозга! Я знаю, что мой английский — английский, но, по крайней мере, я стараюсь.

ребята, я просто портировал код от Symfony. Я так и принял. Для всего это имеет значение — это работает, и это кажется довольно основательным. Я тоже считаю, что это недостаточно читабельно, но у меня не было времени полностью переписать его.

Выглядит хорошо для меня. Это троичные операторы, которые могут сэкономить время (и байты) без потери читабельности при правильном использовании.

Сохранение байтов полезно только для языков ассемблера. Если эта техника экономит ваше время и вы можете справиться с этим в будущем, я ничего не имею против. Я здесь не для того, чтобы создавать противоречие из личных предпочтений функции; если это работает, это хорошо. Для меня более медленная запись / более быстрое чтение экономит время. Мои извинения, если я кого-то обидел.

@antitoxic, -1 Программисты Symfony (как и многие другие) точно не знают, что они делают в этом случае. Это не дает вам имя хоста (см. Ответ Саймона). Это просто даст вам лучшее предположение, которое много раз будет ошибочным.

@StefanNch «Сохранение байтов полезно только для языков ассемблера», крайне не соответствует действительности. Просто чтобы указать на один пример для языков сценариев, таких как PHP, сохраненные байты могут помочь в более быстрых синтаксических разборках для интерпретатора. Быть многословным обычно не влияет на скомпилированные языки. Также вы должны действительно привыкнуть к чтению троичных выражений в качестве программиста, они доступны на большинстве языков и повышают удобочитаемость, если вы просто не знаете язык ..

@GaretClaborn Я провел слишком много тестов «производительности» в своей жизни, чтобы понять, что проблема не должна быть на моих плечах. Пока я буду заниматься программированием, я буду пытаться писать свой код, зная, что другие могут его понять. Нет времени расшифровывать только потому, что машина анализирует и выполняет код на 0,001 секунды быстрее для 1 миллиона вызовов. Во всяком случае, это мое мнение, основанное на моем опыте. Когда я могу улучшить сценарий, я не делаю имена переменных просто для того, чтобы доказать, насколько я хардкорный. Не успеваю уточнять дальше, так что удачи.

@StefanNch Извините, у меня нет времени, чтобы объяснить основы, как это, но вы должны исследовать лучше.

@GaretClaborn Ни я не просил об этом. Я объяснил свою точку зрения так хорошо, как мог, и в значительной степени именно это.

Используйте либо. Они оба одинаково безопасны, так как во многих случаях SERVER_NAME просто заполняется из HTTP_HOST. Обычно я запускаю HTTP_HOST, так что пользователь остается на том точном имени хоста, с которого они начали. Например, если у меня есть тот же сайт в домене .com и .org, я не хочу отправлять кого-то из .org в .com, особенно если у них могут быть маркеры входа в .org, которые они потеряли бы, если бы отправили другой домен.

В любом случае вам просто нужно быть уверенным, что ваш webapp будет реагировать только на хорошо известные домены. Это может быть выполнено либо (a) с проверкой на стороне приложения, как Gumbo, либо (b) с использованием виртуального хоста на доменных именах, которые вы хотите, чтобы не отвечал на запросы, которые дают неизвестный заголовок Host.

Причиной этого является то, что если вы разрешаете доступ к вашему сайту под каким-либо старым именем, вы можете открыться для DNS-повторных атак (где другое имя узла сайта указывает на ваш IP-адрес, пользователь обращается к вашему сайту с именем хоста злоумышленника, то имя хоста перемещается на IP-адрес злоумышленника, беря с собой ваши файлы cookie/auth) и угон поисковой системы (где злоумышленник указывает свое собственное имя хоста на вашем сайте и пытается заставить поисковые системы рассматривать его как «лучшее первичное имя хоста» ).

По-видимому, обсуждение в основном связано с $_SERVER [‘PHP_SELF’] и почему вы не должны использовать его в атрибуте action формы без надлежащего экранирования для предотвращения атак XSS.

Пфф. Ну, вы не должны использовать что-либо в любом атрибуте без экранирования с помощью htmlspecialchars($string, ENT_QUOTES) , поэтому нет ничего особенного в переменных сервера.

Оставаться с решением (a), (b) на самом деле небезопасно, использование абсолютного URI в HTTP-запросах позволяет обойти защиту виртуальных хостов на основе имен. Поэтому настоящим правилом никогда не является доверие к SERVER_NAME или HTTP_HOST.

@bobince, как работает упомянутый поисковик угон? Поисковые системы сопоставляют слова с URL-адресами доменов, они не имеют дело с IP-адресами. Так почему же вы говорите, что «злоумышленник может заставить поисковые системы рассматривать attacker.com как лучший первоисточник IP вашего сервера»? Похоже, это ничего не значит для поисковых систем. Что это вообще собирается делать?

Источник

Читайте также:  vertical-align
Оцените статью