Волшебные кавычки в PHP

Согласно руководству PHP , чтобы сделать код более переносимым, они рекомендуют использовать что-то вроде следующего для экранирования данных:

if (!get_magic_quotes_gpc()) { $lastname = addslashes($_POST['lastname']); } else { $lastname = $_POST['lastname']; } 

У меня есть другие проверки проверки, которые я буду выполнять, но насколько безопасно это строго в плане выхода из данных? Я также видел, что магические кавычки будут устаревать в PHP 6. Как это повлияет на вышеуказанный код? Я бы предпочел не полагаться на функцию escaping для конкретной базы данных, такую ​​как mysql_real_escape_string ().

Волшебные кавычки по своей сути нарушаются. Они предназначались для санирования входа в PHP-скрипт, но, не зная, как этот вход будет использоваться, невозможно корректно дезинформировать. Во всяком случае, вам лучше проверить, включены ли магические кавычки, затем вызов stripslashes () в $ _GET / $ _ POST / $ _ COOKIES / $ _ REQUEST, а затем дезинфекция ваших переменных в том месте, где вы его где-то используете. Например, urlencode (), если вы используете его в URL-адресе htmlentities (), если вы печатаете его на веб-странице или используете функцию экранирования драйвера базы данных, если вы храните ее в базе данных. Обратите внимание, что эти входные массивы могут содержать под-массивы, поэтому вам может потребоваться написать функцию, которая может рекурсировать в под-массивы, чтобы также удалить эти черты.

Справочная страница PHP по магическим котировкам соглашается:

«Эта функция была DEPRECATED с PHP 5.3.0 и УДАЛЕНА с PHP 6.0.0. Опираясь на эту функцию, очень обескуражен. Magic Quotes – это процесс, который автоматически пропускает входящие данные в PHP-скрипт. Предпочтительно кодировать с помощью магии цитирует и вместо этого удаляет данные во время выполнения ».

Магические кавычки были ошибкой дизайна. Их использование несовместимо с сохранением вашего здравомыслия.

Я предпочитаю:

 if (get_magic_quotes_gpc()) { throw new Exception("Turn magic quotes off now!"); } 

Не пишите код для совместимости с неподходящими сломанными настройками. Вместо этого защитите их использование, если ваш код FAIL FAST .

Я использую следующий код в файле заголовка моего веб-сайта, чтобы отменить эффекты magic_quotes:

 <?php // Strips slashes recursively only up to 3 levels to prevent attackers from // causing a stack overflow error. function stripslashes_array(&$array, $iterations=0) { if ($iterations < 3) { foreach ($array as $key => $value) { if (is_array($value)) { stripslashes_array($array[$key], $iterations + 1); } else { $array[$key] = stripslashes($array[$key]); } } } } if (get_magic_quotes_gpc()) { stripslashes_array($_GET); stripslashes_array($_POST); stripslashes_array($_COOKIE); } ?> 

Затем я могу написать остальную часть кода, как будто magic_quotes никогда не существовал.

«Я бы предпочел не полагаться на функцию экранирования, специфичную для базы данных, такую ​​как mysql_real_escape_string ()»

Затем используйте что-то вроде PDO . Но вы все равно должны отменить ущерб, нанесенный магическими цитатами.

Поместите требование PHP 5.2 или выше на свой код и используйте API фильтра . Функции filter_* исходные входные данные (они никогда не касаются $_POST и т. Д.), Поэтому они полностью не затронуты magic_quotes_gpc .

Тогда этот пример:

 if (!get_magic_quotes_gpc()) { $lastname = addslashes($_POST['lastname']); } else { $lastname = $_POST['lastname']; } 

Может стать следующим:

 $lastname = filter_input(INPUT_POST, 'lastname'); 

Правильно, это не лучший способ сделать это, а не самый безопасный. Побег лучше всего делать по отношению к тому, за что вы ускользаете. Если он хранится в базе данных mysql, используйте mysql_real_escape_string, который учитывает другие локали, наборы символов. Для HTML, htmlentities. Для использования в коде escapeshellcmd, escapeshellarg. Да, вам, вероятно, сначала нужно нажать на мешалки, если будут включены магические цитаты. Но лучше не рассчитывать на это или использовать его.

Что касается использования функции экранирования, связанной с базой данных, вам это очень нужно. Я обнаружил, что с помощью addslashes() не удается в редких случаях с MySQL. Вы можете написать функцию escape, которая определяет, какую БД вы используете, а затем использовать функцию ускорения approriate.

Вы можете попробовать следующее:

 if (get_magic_quotes_gpc()) { $_REQUEST = array_map('stripslashes', $_REQUEST); $_GET = array_map('stripslashes', $_GET); $_POST = array_map('stripslashes', $_POST); $_GET = array_map('stripslashes', $_COOKIES); } 

«Я бы предпочел не полагаться на функцию экранирования, специфичную для базы данных, такую ​​как mysql_real_escape_string ()»

Также addlashes можно обмануть, а также проверить этот пост:

http://shiflett.org/blog/2006/jan/addslashes-versus-mysql-real-escape-string

Ваш образец кода обратный, вы должны делать следующее:

 if (get_magic_quotes_gpc()) { $lastname = stripslashes($_POST['lastname']); } else { $lastname = $_POST['lastname']; } 

Обратите внимание, что это оставляет ваши входные данные в «сыром» состоянии точно так же, как пользователь набрал его – никаких дополнительных обратных косых черт и потенциально загруженных с помощью SQL Injection и XSRF-атак – и это именно то, что вы хотите. Затем убедитесь, что вы всегда используете одно из следующих:

  • При htmlentities() переменной в HTML, оберните ее в htmlentities()
  • При mysql_real_escape_string() в mysql используйте подготовленные операторы или mysql_real_escape_string() как минимум.
  • При повторении переменной в код Javascritpt используйте json_encode()

У Джоэла Спольского есть несколько хороших советов по созданию неправильного кода.

Просто нашел это на страницах руководства PHP , выглядит как довольно умный способ разделить их (имеет дело с ключами и значениями …):

 if (get_magic_quotes_gpc()) { $_GET = json_decode(stripslashes(json_encode($_GET, JSON_HEX_APOS)), true); $_POST = json_decode(stripslashes(json_encode($_POST, JSON_HEX_APOS)), true); $_COOKIE = json_decode(stripslashes(json_encode($_COOKIE, JSON_HEX_APOS)), true); $_REQUEST = json_decode(stripslashes(json_encode($_REQUEST, JSON_HEX_APOS)), true); ini_set('magic_quotes_gpc', 0); } 

Подготовленные утверждения PDO и Mysqli – лучший способ предотвратить SQL-инъекцию.

Но если вы переносите устаревший код, основанный на Magic Quotes для каждого SQL-запроса, вы можете ссылаться на yidas / php-magic-кавычки для реализации Magic Quotes в среде с PHP 5.4 выше версии.

https://github.com/yidas/php-magic-quotes