Что случилось с использованием $ _REQUEST ?

Я видел несколько сообщений здесь, говоря, что не использовать переменную $_REQUEST . Обычно я этого не делаю, но иногда это удобно. Что с этим не так?

Абсолютно ничего плохого в том, что можно вводить данные как из $_GET и $_POST комбинированным способом. Фактически это то, что вы почти всегда хотите сделать:

  • для простого идемпотентного запроса, обычно передаваемого через GET, существует вероятность того, что количество данных, которое вы хотите, не поместится в URL-адресе, поэтому вместо этого оно будет изменено на запрос POST в качестве практического вопроса.

  • для запроса, который имеет реальный эффект, вы должны проверить, что он отправлен методом POST. Но способ сделать это – явно проверить $_SERVER['REQUEST_METHOD'] , а не полагаться на то, что $_POST пуст для GET. И вообще, если метод POST , вы все же можете захотеть взять некоторые параметры запроса из URL-адреса.

Нет, проблема с $_REQUEST не связана с объединением параметров GET и POST. Дело в том, что он также по умолчанию включает $_COOKIE . И файлы cookie действительно не похожи на параметры отправки формы: вы почти никогда не хотите относиться к ним как к одному и тому же.

Если вы случайно набрали cookie на своем сайте с тем же именем, что и один из ваших параметров формы, тогда формы, которые полагаются на этот параметр, загадочно перестанут работать должным образом из-за значений cookie, переопределяющих ожидаемые параметры. Это очень легко сделать, если у вас несколько приложений на одном и том же сайте, и их очень сложно отладить, когда у вас есть только несколько пользователей со старыми кукисами, которые вы больше не используете и не разбиваете формы, – Еще один может воспроизвести.

Вы можете изменить это поведение на гораздо более разумный порядок GP (без C ) с конфигурацией request_order в PHP 5.3. Там, где это невозможно, я лично избегал $_REQUEST и, если бы мне нужен объединенный массив GET + POST, создайте его вручную.

Я копал некоторые сообщения в новостных группах на PHP Internals и нашел интересную дискуссию по этой теме. Первоначальная нить была о чем-то другом, но замечание Стефана Эссера, эксперта по безопасности (в случае отсутствия) в мире PHP, привело к обсуждению вопроса о безопасности использования $ _REQUEST для нескольких сообщений.

Ссылаясь на Стефана Эссера на PHP Internals

$ _REQUEST – одна из самых больших недостатков дизайна в PHP. Каждое приложение, использующее $ _REQUEST, скорее всего, уязвимо для проблем с запросами на задержку перекрестного запроса. (Это в основном означает, что если существует файл cookie с именем (возраст), он всегда будет перезаписывать содержимое GET / POST, и поэтому будут выполняться нежелательные запросы)

и в более позднем ответе на ту же тему

Дело не в том, что кто-то может подделать GET, POST; COOKIE. Речь идет о том, что COOKIE будут перезаписывать данные GET и POST в запросе.

Поэтому я могу заразить ваш браузер файлом cookie, который говорит, например, action = logout, и с этого дня вы больше не сможете использовать приложение, потому что REQUEST [action] будет выходить навсегда (пока вы не удалите файл cookie вручную).

И заразить вас COOKIE так просто …
a) Я мог бы использовать XSS в любом приложении на субдомене
б) Когда-либо пытался установить cookie для * .co.uk или * .co.kr, когда у вас есть один домен?
c) Другой кросс-домен любым способом …

И если вы считаете, что это не проблема, я могу сказать вам, что есть простая возможность установить fe * .co.kr cookie, что приводит к тому, что несколько версий PHP просто возвращают белые страницы. Представьте себе: всего один куки-файл, чтобы убить все страницы PHP в * .co.kr

И, установив незаконный идентификатор сеанса в файл cookie, действительный для * .co.kr, в переменной с именем + PHPSESSID = illegal, вы все равно можете использовать DOS для каждого приложения PHP в корее, используя сеансы PHP …

Обсуждение продолжается еще несколько сообщений и интересно читать.


Как вы можете видеть, главная проблема с $ _REQUEST заключается не столько в том, что у нее есть данные от $ _GET и $ _POST, но и от $ _COOKIE. Некоторые другие ребята из списка предложили изменить порядок, в котором заполняется $ _REQUEST, например, сначала заполняя его $ _COOKIE, но это может привести к многочисленным другим потенциальным проблемам, например, при обработке сеанса .

Вы можете полностью опустить $ _COOKIES из $ _REQUEST global, хотя, чтобы он не был перезаписан каким-либо из других массивов (на самом деле вы можете ограничить его любой комбинацией его стандартного содержимого, например, руководство PHP по настройке переменной_order говорит нам:

variable_order Устанавливает порядок обработки переменных EGPCS (Environment, Get, Post, Cookie и Server). Например, если для параметра variable_order установлено значение «SP», тогда PHP создаст суперглобалы $ _SERVER и $ _POST, но не создаст $ _ENV, $ _GET и $ _COOKIE. Установка на «" означает, что суперглобалы не будут установлены.

Но опять же, вы можете также рассмотреть возможность использования $ _REQUEST вообще, просто потому, что в PHP вы можете получить доступ к среде, Get, Post, Cookie и Server в своих собственных глобальных сетях и меньше иметь один вектор атаки. Вы все еще должны дезинфицировать эти данные, но об этом еще не о чем беспокоиться.


Теперь вы можете удивиться, почему $ _REQUEST существует и почему он не удаляется. Это было задано также и для PHP Internals. Ссылаясь на Расмуса Лердорфа о том, почему существует $ _REQUEST? по внутренним PHP

Чем больше таких вещей мы удаляем, тем труднее для людей быстро перейти на более новые, более быстрые и безопасные версии PHP. Это вызывает больше разочарования для всех, чем несколько «уродливых» унаследованных функций. Если есть приличная техническая причина, производительность или безопасность, тогда нам нужно внимательно рассмотреть это. В этом случае мы должны смотреть на то, не следует ли нам удалять $ _REQUEST, но следует ли удалять с него данные cookie. Многие конфигурации уже делают это, включая все мои собственные, и существует сильная обоснованная причина безопасности для того, чтобы не включать файлы cookie в $ _REQUEST. Большинство людей используют $ _REQUEST для обозначения GET или POST, не понимая, что он может также содержать файлы cookie, и как таковые плохие парни могут потенциально использовать некоторые трюки с приемом cookie и перерывать наивные приложения.

В любом случае, надеюсь, что пролить свет.

$_REQUEST относится ко всем типам запросов (GET, POST и т. Д.). Иногда это полезно, но обычно лучше указать точный метод ($ _GET, $ _POST и т. Д.).

$_REQUEST как правило, считается вредным по той же причине, что преобразования данных с простой и средней степенью сложности часто выполняются в коде приложения, а не в SQL: некоторые программисты сосут.

Таким образом, если вы используете везде $_REQUEST , я могу делать что-либо через GET, который мог бы через POST, что означает настройку тегов <img> на моем (вредоносном) сайте, которые заставляют пользователей войти в ваш модуль электронной коммерции для покупки или я могу заставить их щелкнуть ссылки, которые приведут к опасным действиям или раскрытию конфиденциальной информации (возможно, для меня).

Однако это из-за новичка или, по крайней мере, неопытного программиста PHP, делающего простые ошибки. Во-первых, знайте, когда данные о том, какой тип подходит. Например, у меня есть веб-служба, которая может возвращать ответы в URLEncoding, XML или JSON. Приложение решает, как отформатировать ответ, проверив заголовок HTTP_ACCEPT, но может быть принудительно принудительно введено в него, отправив параметр format .

При проверке содержимого параметра формата он может быть отправлен через querystring или postdata, в зависимости от множества факторов, не в последнюю очередь из которых следует, чтобы или нет вызывающие приложения «& format = json», смешанные с его запросом. В этом случае $_REQUEST очень удобен, потому что мне удается набрать что-то вроде этого:

 $format = isset($_POST['format']) ? $_POST['format'] : (isset($_GET['format']) ? $_GET['format'] : null); 

Я больше не буду болтать дальше, но достаточно сказать, что использование $_REQUEST не отговаривается, потому что оно по своей сути опасно – это просто еще один инструмент, который делает именно то, что его просят, понимаете ли вы эти последствия или нет – это это плохое, ленивое или неосведомленное решение бедного, ленивого или неопытного программиста, вызывающего эту проблему.

Как безопасно использовать $_REQUEST


  1. Знайте свои данные : у вас должно быть какое-то ожидание относительно того, какие данные вы получите, поэтому соответствующим образом их дезинфицируйте. Данные для базы данных? addslashes() или *_escape_string() . Собираетесь показать его пользователю? htmlentities() или htmlspecialchars() . Ожидайте числовые данные? is_numeric() или ctype_digit() . Фактически, filter_input() и связанные с ним функции предназначены для того, чтобы ничего не делать, кроме проверки и дезинфекции данных. Всегда используйте эти инструменты.
  2. Не обращайтесь напрямую к данным суперглобальных данных . Создавайте привычку ежедневно дезинформировать свои данные и перемещать данные для очистки переменных, даже если это просто $post_clean . В качестве альтернативы, вы можете просто очистить непосредственно в суперглобалях, но причина, по которой я выступаю за использование отдельной переменной, заключается в том, что это позволяет легко выявлять уязвимости в коде, поскольку все , что указывает прямо на суперглобальный, а не на его дезинфицированный эквивалент, считается опасной ошибкой ,
  3. Знайте, откуда должны поступать данные. Обращаясь к моему примеру сверху, вполне разумно разрешить отправку переменной формата ответа через GET или POST. Я также разрешаю передавать переменную «действие» с помощью любого метода. Однако сами действия имеют очень специфические требования относительно приемлемости HTTP-глагола . Функции, например, которые вносят изменения в данные, используемые службой, могут быть отправлены только через POST. Запросы для определенных типов данных о не-или низкоприоритетных (например, динамически сгенерированных изображениях карт) могут подаваться в ответ на запросы любого из этих методов.

В заключение помните это простое правило:

БЕЗОПАСНОСТЬ – ЧТО ВЫ СДЕЛАЛИ ЭТО, ЛЮДИ!

РЕДАКТИРОВАТЬ:

Я настоятельно рекомендую совет bobince: если можно, установите параметр request_order в php.ini в «GP»; то есть никакого компонента cookie. В 98% случаев случаев практически нет рациональных аргументов, поскольку данные cookie почти никогда не считаются сравнимыми с запросами или постобработками.

PS, Анекдот!

Я знал программиста, который думал о $_REQUEST месте просто хранить данные, которые были доступны суперглобальным способом. Важные имена пользователей и пароли, пути к файлам, вы называете это, и он хранился в $_REQUEST . Он был немного удивлен (хотя и не комично, к сожалению), когда я рассказал ему, как ведет себя эта переменная. Разумеется, эта практика была свергнута.

Запросы GET должны быть идемпотентными, а запросы POST обычно отсутствуют. Это означает, что данные в $_GET и $_POST обычно должны использоваться по-разному.

Если ваше приложение использует данные из $_REQUEST , оно будет вести себя одинаково для запросов GET и POST, что нарушает идемпотентность GET.

Это расплывчато. Вы не знаете, как данные дошли до вас, поскольку они содержат данные о почтовых сообщениях, получателях и файлах cookie. Я не обязательно думаю, что это всегда плохо, если вам не нужно знать или ограничивать метод доставки.

Мне действительно нравится использовать его. Это дает вам гибкость в использовании GET или POST, которые могут пригодиться для таких вещей, как формы поиска, где большая часть данных времени POSTED, но иногда вам нужно указать ссылку на конкретный поиск, так что вы можете использовать параметры GET вместо ,

Кроме того, если вы посмотрите на многие другие языки (например, ASP.NET), они не делают различий между GET и переменными POST вообще.

ETA :

Я никогда не использовал REQUEST, чтобы получить значения COOKIE, но я думаю, что Kyle Butt делает замечание в комментариях к этому сообщению об этом. Не рекомендуется использовать REQUEST для получения значений COOKIE. Я считаю, что он прав, что есть реальный потенциал для подделки подделок, если вы это сделаете.

Кроме того, порядок загрузки материала в REQUEST контролируется параметрами конфигурации в php.ini (variables_order и request_order). Итак, если у вас есть одна и та же переменная, переданная через POST и GET, которая фактически попадает в REQUEST, зависит от этих настроек ini. Это может повлиять на переносимость, если вы зависите от определенного порядка, и эти настройки настроены иначе, чем вы ожидаете.

Важно понимать, когда использовать POST, когда использовать GET и когда использовать cookie. С $ _REQUEST ценность, которую вы ищете, могла бы исходить от любого из них. Если вы ожидаете получить значение от POST или GET или от COOKIE, более информативным будет кто-то, читающий ваш код, использовать конкретную переменную вместо $ _REQUEST.

Кто-то еще указал на то, что вы не хотите, чтобы все POST или cookie были переопределены GET, потому что для всех из них существуют разные правила межсайтовых правил, например, если вы возвращаете данные ajax при использовании $ _REQUEST, вы уязвимы к атаке скрипта с несколькими сайтами.

Единственное время использования $_REQUEST – неплохая идея – с GET.

  • Если вы используете его для загрузки значений POST, вы рискуете подделки с запросами на межсайтовый запрос
  • Если вы используете его для загрузки значений файлов cookie, вы снова рискуете подделки поддонов сайта

И даже с GET, $_GET короче, чем $_REQUEST 😉

Я мог бы использоваться только в том случае, если вы хотите получить текущий url или имя хоста, но для фактического анализа данных с этого URL-адреса, таких как parmeters с использованием символа &, это, вероятно, не очень хорошая идея. В общем, вы не хотите использовать неопределенное описание того, что вы пытаетесь сделать. Если вам нужно быть конкретным, то это где $ _REQUEST плохо, если вам не нужно быть конкретным, тогда не стесняйтесь использовать его. Я бы подумал.

Если вы знаете, какие данные вы хотите, вы должны явно спросить об этом. IMO, GET и POST – это два разных животных, и я не могу думать о хорошей причине, почему вам когда-либо понадобилось бы смешивать почтовые данные и строки запросов. Если у кого-то есть, мне было бы интересно.

Удобно использовать $ _REQUEST, когда ваши сценарии могут отвечать на GET или POST таким же образом. Я бы сказал, однако, что это должен быть крайне редкий случай, и в большинстве случаев предпочтительными являются две отдельные функции для обработки двух отдельных понятий или, по крайней мере, проверки метода и выбора правильных переменных. Поток программ обычно намного проще отслеживать, когда нет необходимости перекрестно ссылаться на переменные. Будьте добры к человеку, который должен поддерживать ваш код через 6 месяцев. Возможно, вы.

В дополнение к проблемам безопасности и WTF, вызванным переменными cookie и среды в переменной REQUEST (не запускайте меня в GLOBAL), подумайте, что может произойти в будущем, если PHP начнет поддерживать другие методы, такие как PUT и DELETE. Хотя крайне маловероятно, что они будут объединены в суперклассу REQUEST, возможно, они могут быть включены как опция в настройку variable_order. Таким образом, вы действительно не знаете, что такое REQUEST, и что имеет приоритет, особенно если ваш код развернут на стороннем сервере.

Является ли POST более безопасным, чем GET? На самом деле, нет. Лучше использовать GET там, где это возможно, потому что в ваших журналах легче видеть, как ваше приложение используется, когда оно атаковано. POST лучше для операций, которые влияют на состояние домена, потому что пауки обычно не следуют за ними, а прогностические механизмы отбора не удаляют весь ваш контент при входе в вашу CMS. Однако речь шла не о преимуществах GET и POST, а о том, как получатель должен обрабатывать поступающие данные и почему это плохо, чтобы объединить его, так что это действительно просто BTW.

Я думаю, что нет проблемы с $_REQUEST , но мы должны быть осторожны при ее использовании, поскольку это набор переменных из трех источников (GPC).

Я думаю, что $_REQUEST по-прежнему доступен, чтобы старые программы были совместимы с новыми версиями php, но если мы начнем новые проекты (включая новые библиотеки), я думаю, мы больше не должны использовать $_REQUEST , чтобы сделать программы более понятными. Мы должны даже рассмотреть возможность удаления использования $_REQUEST и замены его на функцию-обертку, чтобы сделать программу более легкой, особенно при обработке больших представленных текстовых данных, поскольку $_REQUEST содержит копии $_POST .

 // delete $_REQUEST when program execute, the program would be lighter // when large text submitted unset($_REQUEST); // wrapper function to get request var function GetRequest($key, $default = null, $source = '') { if ($source == 'get') { if (isset($_GET[$key])) { return $_GET[$key]; } else { return $default; } } else if ($source == 'post') { if (isset($_POST[$key])) { return $_POST[$key]; } else { return $default; } } else if ($source == 'cookie') { if (isset($_COOKIE[$key])) { return $_COOKIE[$key]; } else { return $default; } } else { // no source specified, then find in GPC if (isset($_GET[$key])) { return $_GET[$key]; } else if (isset($_POST[$key])) { return $_POST[$key]; } else if (isset($_COOKIE[$key])) { return $_COOKIE[$key]; } else { return $default; } } } с // delete $_REQUEST when program execute, the program would be lighter // when large text submitted unset($_REQUEST); // wrapper function to get request var function GetRequest($key, $default = null, $source = '') { if ($source == 'get') { if (isset($_GET[$key])) { return $_GET[$key]; } else { return $default; } } else if ($source == 'post') { if (isset($_POST[$key])) { return $_POST[$key]; } else { return $default; } } else if ($source == 'cookie') { if (isset($_COOKIE[$key])) { return $_COOKIE[$key]; } else { return $default; } } else { // no source specified, then find in GPC if (isset($_GET[$key])) { return $_GET[$key]; } else if (isset($_POST[$key])) { return $_POST[$key]; } else if (isset($_COOKIE[$key])) { return $_COOKIE[$key]; } else { return $default; } } } 

Даррен Кук: «Поскольку php 5.3 по умолчанию php.ini говорит, что только данные GET и POST помещаются в $_REQUEST . См. Php.net/request_order. Я просто наткнулся на этот разрыв обратной совместимости, ожидая, что данные cookie будут в $_REQUEST и задаются вопросом почему он не работал! "

Wow … просто некоторые из моих скриптов перестали работать из-за обновления до PHP 5.3 . То же самое: предположим, что файлы cookie будут установлены при использовании переменной $_REQUEST . С обновлением именно это перестало работать.

Теперь я вызываю значения cookie отдельно, используя $_COOKIE["Cookie_name"]

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