Как безопасно создавать переменные PHP с извлечением
В моем предыдущем посте я спрашиваю, как создавать переменные из массива (Переменные PHP, сделанные с помощью foreach), у меня появилось несколько ответов, и я тестировал extract(), но я видели несколько против этого по соображениям безопасности.
Теперь мой вопрос заключается в том, как я могу использовать извлечение безопасным способом из $_POST, у которого есть массив, который был создан с использованием сериализации jquery.
С защищенным я имею в виду, что если пользователь вводит неверные данные, безопасный способ может позаботиться об этом без проблем.
У PHP-сайта есть небольшое предупреждение в команде extract:
Не использовать extract() на ненадежном данные, такие как пользовательский ввод (т.е. $_GET, $_FILES и т.д.). Если вы это сделаете, например если вы хотите запустить старый код, который опирается на register_globals временно, убедитесь, что вы используете один из непереписывая extract_type такие как EXTR_SKIP и быть в курсе что вы должны извлекать в том же порядок, определенный в variables_order внутри php.ini.
Он предупреждает об использовании, но не предоставляет пример, по крайней мере, того, как безопасно решить проблему пользователя извлечения.
Ответы
Ответ 1
Лучший вариант - не использовать extract()
вообще. Это плохое дизайнерское решение со времен, когда PHP был эквивалентом влажной туалетной бумаги для написания защищенного кода.
Это может быть болезненно, но гораздо лучше записать длинную последовательность:
$var1 = $_POST['var1'];
$var2 = $_POST['var2'];
etc...
или просто используйте $_POST['var1']
и всю компанию в своем коде.
Как только вы начнете использовать извлечение, вы даете злоумышленникам потенциальный путь в ваш код, независимо от того, сколько времени и усилий вы вкладываете в него. Вы не просверлите отверстие через дверь банковского хранилища, потому что это слишком раздражает, чтобы каждый раз открывать дверь, чтобы выпустить деньги. Как только там будет отверстие, оно будет эксплуатироваться.
Ответ 2
Не используйте extract(), просто используйте foreach() в POST/GET, чтобы создать свой собственный массив/объект.
extract() будет кошмаром для отладки, когда ваш код начнет увеличиваться.
Ответ 3
Это достаточно безопасно, если вы используете префикс, который не существует в других переменных:
extract($_POST, EXTR_PREFIX_ALL, 'unique_prefix');
Причина, по которой извлечение может быть опасной, аналогична использованию register_globals.
Ответ 4
Нет ничего плохого в extract
, если вы используете его только для частичного извлечения известных входных переменных. Это не самый приятный синтаксис, но выполнимый с помощью:
extract(array_intersect_key($_POST,
array_flip(array("var1", "var2", "var3", "var4"))));
Это сокращает возможные переменные $_POST и не будет извлекать неожиданные вещи. Общая выгода заключается в том, что вы все равно можете применить некоторую функцию фильтра, используя array_map
. В некоторых настройках он уменьшает беспорядок кода по сравнению с индивидуальным копированием переменных.
Ответ 5
Как использовать простой foreach вместо extract():
foreach($_POST as $k => $v) $$k = $v;
Таким образом, вы можете добавить код безопасности в часть $$k = $v;
.
Ответ 6
Его опасный для использования экстракт в глобальном масштабе и для _REQUEST, _GET, _POST, _COOKIE.
Однако, если вы разрешаете использовать только переменные, которые вы собираетесь использовать с помощью механизма фильтрации, и отключите все, что приходит извне, вы можете использовать извлечение.
Например, если вы напрямую загружаете _REQUEST, _GET, _POST, _COOKIE в функцию, которая будет делать extract() внутри и выпустить только те, которые вы определяете в 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
}
}