Как безопасно создавать переменные PHP с экстрактом - PullRequest
12 голосов
/ 17 мая 2011

В моем предыдущем посте я спрашивал, как создать переменные из массива ( PHP-переменные, созданные с помощью foreach ), я получил несколько ответов и тестировал extract (), но я видел несколько из них по соображениям безопасности.

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

С безопасным, я имею в виду, что если пользовательвводит неверные данные, безопасный способ без проблем позаботится об этом.

У сайта PHP есть небольшое предупреждение в команде извлечения, которое говорит следующее:

Неиспользуйте extract () для ненадежных данных, таких как пользовательский ввод (например, $ _GET, $ _FILES и т. д.).Если вы это сделаете, например, если вы хотите временно запустить старый код, который основан на register_globals, убедитесь, что вы используете одно из не перезаписывающих значений extract_type, таких как EXTR_SKIP, и помните, что вы должны извлекать в том же порядке, который определен в variable_order внутриthe php.ini.

Предупреждает об использовании, но не дает хотя бы пример того, как решить пользователя извлечения безопасным способом.

Ответы [ 6 ]

10 голосов
/ 17 мая 2011

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

Это может быть болезненно, но гораздо лучше написать длинную последовательность:

$var1 = $_POST['var1'];
$var2 = $_POST['var2'];
etc...

или просто используйте $_POST['var1'] и компанию везде в своем коде.

Как только вы начинаете использовать extract, вы предоставляете злонамеренным пользователям потенциальный доступ к вашему коду, независимо от того, сколько времени / усилий вы потратите на него. Вы не просверлите отверстие в двери банковского хранилища, потому что слишком раздражает, что приходится каждый раз открывать дверь, чтобы выпустить немного денег. Когда есть дыра, она будет использована.

7 голосов
/ 17 мая 2011

Не используйте extract (), просто используйте foreach () для POST / GET, чтобы создать свой собственный массив / объект.extract () станет кошмаром для отладки, когда ваш код станет больше.

6 голосов
/ 17 мая 2011

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

extract($_POST, EXTR_PREFIX_ALL, 'unique_prefix');

Причина, по которой извлечение может быть опасным, такая же, как при использовании register_globals .

1 голос
/ 28 августа 2014

Опасно использовать экстракт в глобальной области видимости и для _REQUEST, _GET, _POST, _COOKIE.

Однако, если вы разрешите использовать только те переменные, которые собираетесь использовать с помощью механизма фильтрации, и сбросить все, что приходит извне, вы можете использовать извлечение.

Например, если вы напрямуювведя _REQUEST, _GET, _POST, _COOKIE в функцию, которая выполнит извлечение () внутри и выпустит только те, которые вы определили в return (), тогда вы тоже в безопасности.Потому что все, что извлечено, включая переменные от злонамеренных попыток, останется внутри области действия функции и не сможет ничего делать.

Итак, extract () учитывает область действия - все, что вы извлекаете внутри функции, остается внутри этой функциивсе, что вы извлекаете внутри метода класса, остается в области действия этого метода класса и никуда не денется без вашего разрешения.

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

Предполагая, что $ args является ассоциативным массивом:


function funny($args)
{
  extract($args);

  // Hereon you can use the variables normally and they will stay in function scope

}

Ваши переменные останутся внутри области действия функции.

То же самое для метода класса:


class berserker
{
     public function funny($args)
     {
       extract($args);

       // Hereon you can use the variables normally and they will stay in method scope

     }

}
1 голос
/ 21 мая 2012

А как насчет использования простого foreach вместо extract ():

foreach($_POST as $k => $v) $$k = $v;

Таким образом, вы можете иметь дело с добавлением некоторого кода безопасности в часть $$k = $v;.

1 голос
/ 17 мая 2011

Нет ничего плохого в extract, если вы используете его только для частичного извлечения известных входных переменных.Это не самый хороший синтаксис, но выполнимый с помощью:

extract(array_intersect_key($_POST,
        array_flip(array("var1", "var2", "var3", "var4"))));

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

...