Какие переменные $SERVER безопасны?
Любая переменная, которой может управлять пользователь, также может управляться злоумышленником и, следовательно, является источником атаки. Это называется "испорченной" переменной и небезопасно.
При использовании $_SERVER
, многими переменными можно управлять. PHP_SELF
, HTTP_USER_AGENT
, HTTP_X_FORWARDED_FOR
, HTTP_ACCEPT_LANGUAGE
и многие другие являются частью заголовка HTTP-запроса, отправляемого клиентом.
Кто-нибудь знает о "безопасном списке" или незапятнанном списке переменных $_SERVER
?
2 answers
Не существует таких понятий, как "безопасные" или "небезопасные" ценности как таковые. Существуют только значения, которыми управляет сервер, и значения, которыми управляет пользователь, и вам необходимо знать, откуда берется значение и, следовательно, можно ли ему доверять для определенной цели. $_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'
( применимо только к вызову командной строки, обычно не относится к веб-серверам) -
'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
также включает в себя несколько переменных среды. Являются ли они "безопасными" или нет, зависит от того, как (и где) они находятся определенный. Они могут варьироваться от полностью контролируемых сервером до полностью контролируемых пользователем.
В PHP каждая переменная $_SERVER
, начинающаяся с HTTP_
, может зависеть от пользователя. Например, переменная $_SERVER['HTTP_REINERS']
может быть изменена путем установки заголовка HTTP REINERS
в произвольное значение в HTTP-запросе.