Какие переменные $ _SERVER безопасны?


97

Любая переменная, которой может управлять пользователь, также может контролировать злоумышленник и, следовательно, является источником атаки. Это называется "испорченной" переменной и небезопасно.

При использовании $_SERVERможно управлять многими переменными. PHP_SELF, HTTP_USER_AGENT, HTTP_X_FORWARDED_FOR, HTTP_ACCEPT_LANGUAGEИ многие другие являются частью заголовка запроса HTTP , посланного клиентом.

Кто-нибудь знает о «безопасном списке» или незапятнанном списке $_SERVERпеременных?


8
Зависит от того, как вы определяете «безопасный». Все значения безопасны сами по себе, это зависит только от того, для чего вы их используете.
deceze

6
Я думаю, что в этом контексте Рук говорит: «Какие серверные переменные не могут быть подделаны пользователем», например REMOTE_ADDR.
vcsjones

6
Все, что предшествует, HTTP_является заголовком запроса и может быть установлено браузером или прокси-сервером между ними. Я бы рассмотрел их как любой другой пользовательский ввод.
данные

3
@bob-the-destroyer REMOTE_ADDR извлекается непосредственно из TCP-сокета apache, это значение нельзя подделать через Интернет из-за трехстороннего рукопожатия.
ладья

2
@Rook: хороший момент. Думаю, с упоминанием «спуфинга» я больше склонялся к старому акту подмены IP-адресов, а не к подделке фактического значения REMOTE_ADDR. И это выходит за рамки этого вопроса. Хорошо, если вы разобрались, как устанавливается это значение, поэтому спасибо.
bob-the-destroyer

Ответы:


147

Не существует таких понятий, как «безопасные» или «небезопасные» ценности. Есть только значения, которые контролирует сервер, и значения, которыми управляет пользователь, и вам нужно знать, откуда берется значение и, следовательно, можно ли ему доверять для определенной цели. $_SERVER['HTTP_FOOBAR']например, совершенно безопасно хранить в базе данных, но я бы точно не стал eval.

Таким образом, давайте разделим эти значения на три категории:

Сервер контролируется

Эти переменные устанавливаются серверной средой и полностью зависят от конфигурации сервера.

  • 'GATEWAY_INTERFACE'
  • 'SERVER_ADDR'
  • 'SERVER_SOFTWARE'
  • 'DOCUMENT_ROOT'
  • 'SERVER_ADMIN'
  • 'SERVER_SIGNATURE'

Частично контролируется сервером

Эти переменные зависят от конкретного запроса, отправленного клиентом, но могут принимать только ограниченное количество допустимых значений, поскольку все недопустимые значения должны отклоняться веб-сервером и не вызывать запуск сценария. Следовательно, их можно считать надежными .

  • 'HTTPS'
  • 'REQUEST_TIME'
  • 'REMOTE_ADDR' *
  • 'REMOTE_HOST' *
  • 'REMOTE_PORT' *
  • 'SERVER_PROTOCOL'
  • 'HTTP_HOST'
  • 'SERVER_NAME'
  • 'SCRIPT_FILENAME'
  • 'SERVER_PORT'
  • 'SCRIPT_NAME'

* REMOTE_Значения гарантированно являются действительным адресом клиента, что подтверждается подтверждением связи TCP / IP. Это адрес, на который будет отправлен любой ответ. REMOTE_HOSTоднако полагается на обратный поиск DNS и, следовательно, может быть подделан DNS-атаками на ваш сервер (в этом случае у вас все равно будут большие проблемы). Это значение может быть прокси, что является простой реальностью протокола TCP / IP, и вы ничего не можете с этим поделать.

† Если ваш веб-сервер отвечает на любой запрос независимо от HOSTзаголовка, это также следует считать небезопасным. См. Насколько безопасен $ _SERVER [«HTTP_HOST»]? .
Также см. Http://shiflett.org/blog/2006/mar/server-name-versus-http-host .

‡ См. Https://bugs.php.net/bug.php?id=64457 , http://httpd.apache.org/docs/current/mod/core.html#usecanonicalphysicalport , http: //httpd.apache. org / docs / 2.4 / mod / core.html # comment_999

Совершенно произвольные значения, контролируемые пользователем

Эти значения вообще не проверяются и не зависят от какой-либо конфигурации сервера, это совершенно произвольная информация, отправляемая клиентом.

  • 'argv', 'argc'(применимо только для вызова CLI, обычно не проблема для веб-серверов)
  • 'REQUEST_METHOD' §
  • 'QUERY_STRING'
  • 'HTTP_ACCEPT'
  • 'HTTP_ACCEPT_CHARSET'
  • 'HTTP_ACCEPT_ENCODING'
  • 'HTTP_ACCEPT_LANGUAGE'
  • 'HTTP_CONNECTION'
  • 'HTTP_REFERER'
  • 'HTTP_USER_AGENT'
  • 'AUTH_TYPE'
  • 'PHP_AUTH_DIGEST'
  • 'PHP_AUTH_USER'
  • 'PHP_AUTH_PW'
  • 'PATH_INFO'
  • 'ORIG_PATH_INFO'
  • 'REQUEST_URI' (может содержать испорченные данные)
  • 'PHP_SELF' (может содержать испорченные данные)
  • 'PATH_TRANSLATED'
  • любое другое 'HTTP_'значение

§ Может считаться надежным, если веб-сервер поддерживает только определенные методы запроса.

‖ Может считаться надежным, если аутентификация полностью выполняется веб-сервером.

Суперглобальный $_SERVERтакже включает несколько переменных среды. Являются ли они «безопасными» или нет, зависит от того, как (и где) они определены. Они могут варьироваться от полностью контролируемых сервером до полностью управляемых пользователем.


3
@Rook Но, как я уже сказал, это абсолютно зависит от того, как вы его используете . Сами по себе ценности не являются ни безопасными, ни небезопасными, это зависит от того, для чего вы их используете . Даже данные, отправленные злонамеренным пользователем, совершенно безопасны, если вы не делаете с ними ничего, что может поставить под угрозу вашу безопасность.
deceze

2
@Rook: ваше представление о «безопасном» заставляет этот вопрос казаться несколько произвольным, тем более, что он полностью привязан к неясному расширению или специальной версии PHP. В то время как вы говорите, что «не следует« стрелять с бедра »», для любого ответа на самом деле, кажется, требуется как минимум знакомство с исходным кодом PHP, чтобы узнать, как эти значения установлены. Разве электронная почта разработчикам PHP не лучший способ найти ответ?
bob-the-destroyer

2
@Rook: Непонимание. Как намекнул deceze, «безопасно для каких целей». Как я намекал, ваша цель неизвестна, и, кроме того, есть несколько других недокументированных $_SERVERзначений в зависимости от того, как файл обслуживается. На мой взгляд, задокументированные не проясняют истинный источник. Иначе я думаю, вы бы не задавали этот вопрос. Рад, что у вас есть список, который вы можете использовать. Но я все же предлагаю отправить отчет об ошибке (когда их сайт с ошибкой будет исправлен), отправить разработчикам документации электронное письмо или обновить документы самостоятельно (если вы знакомы с ссылкой). Сообществу было бы полезно знать эту информацию.
bob-the-destroyer

3
SERVER_NAMEне обязательно контролируется сервером. В зависимости от шлюза и настроек он может быть дублирован HTTP_HOSTи, следовательно, с той же оговоркой.
bobince

1
@deceze @ Ладья А SERVER_PORTэтот крестик нужен? bugs.php.net/bug.php?id=64457
Деян Марьянович

12

В PHP каждая $_SERVERпеременная, начинающаяся с, HTTP_может зависеть от пользователя. Например, переменную $_SERVER['HTTP_REINERS']можно испортить, установив для заголовка HTTP REINERSпроизвольное значение в HTTP-запросе.


re "произвольный"; Не все произвольно, поскольку они соответствуют формату. Например, $_SERVER['HTTP_REINERS'] в большинстве sapis не может содержать символы новой строки.
Pacerier
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.