Экранирование кавычек в SQL
Я немного смущен этой темой, поэтому я решил спросить об этом у вас, ребята:)
по состоянию на php.net я должен использовать использования mysql_real_escape_string() и отключить волшебные кавычки потому что он устарел.
поэтому я выключил и использую mysql_real_escape_string (), но достаточно ли использовать его так?:
$value = "It's Time!";
$escaped_value = mysql_real_escape_string($value);
mysql_query("INSERT INTO table (column, column2) VALUES ('{$escaped_value}', "0")");
когда я проверяю данные в базе данных, это выглядит так же, как в $value so "It's Time"
, а не "It's Time"
, is это нормально, не должно ли это добавить косую черту перед кавычками?
3 ответов
это правильное поведение, это работает! Кавычки экранируются в запросе, а не в базе данных. \ 'в SQL-запросе необходимо преобразовать в' внутри базы данных. Вы экранируете строки, чтобы SQL-запрос не перепутался и не вводил кавычки в базу данных без SQL-запроса, интерпретирующего их как управляющие символы.
вы избежали запроса:
mysql_query("INSERT INTO table (column, column2) VALUES ('It\'s time', "0")");
данные вашей базы данных должны быть "пришло время".
Если бы это не удалось, это было бы быть:
mysql_query("INSERT INTO table (column, column2) VALUES ('It's time', "0")");
он выплюнет ошибку относительно "времени s" (потому что он будет интерпретировать только до следующего символа цитаты и будет видеть только "это".) И "пора!"это просто безобидная строка, но из этого может произойти много атак, если вы не избегаете своих персонажей.
короткий ответ:
это правильно.
ответ
это правильно, но ваш вопрос указывает на отсутствие глубины понимания того, что происходит здесь. Вот ваш запрос:
INSERT INTO table (column, column2) VALUES ('{$escaped_value}', "0")
давайте посмотрим, что произойдет, если вы не убежать, и пользователь вводит следующие данные:
Eve'
помните, что вы просто передаете строку в MySQL, вставка выполняется обработкой строки PHP. Это означает, что в этот экземпляр, запрос, отправленный mysql_query:
INSERT INTO table (column, column2) VALUES ('Eve'', "0")
что является синтаксической ошибкой и приведет к ошибке страницы. Теперь, когда пользователь, такой как я (т. е. ублюдок, намеревающийся сделать ваш день несчастьем :D), замечает один из них, мы знаем, что пришло время играть. Что произойдет, если следующие данные будут предоставлены пользователем?
Eve', "0"); DROP TABLE table--
наш запрос распространяется на:
INSERT INTO table (column, column2) VALUES ('Eve', "0"); DROP TABLE table--', "0")
это не синтаксическая ошибка, но это проблематично... теперь мы выполняем запрос, который мы никогда предназначен для! (В случае, если вы не узнаете его, " -- " обозначает комментарий в SQL, т. е. "игнорировать все после этой точки").
теперь это не может произойти в этом конкретном случае (mysql_query не поддерживает несколько запросов), но это своего рода атака, которую вы пытаетесь предотвратить - класс атак, известный как SQL-инъекций. Давайте посмотрим, что происходит, когда вы используете mysql_real_escape_string!
введенных данных становится:
Eve\', \"0\"); DROP TABLE table--
что означает, что наша строка запроса выглядит так:
INSERT INTO table (column, column2) VALUES ('Eve\', \"0\"); DROP TABLE table--}', "0")
это замечательно! Введенные пользователем данные будут храниться в базе данных по мере их ввода. Не без кавычек и не с дополнительными косыми чертами, а по мере их ввода. это важно:. Если вы храните данные любым другим способом, вы столкнетесь с проблемами позже, с де-экранированием или двойным экранированием. Кроме того, добавление дополнительных косых черт или что-то подобное часто заканчивается для пользователей так или иначе, и это гигантский предупреждающий знак, что вещи не могут быть спасены должным образом. Вы хотите избежать неправильных действий, и особенно вы хотите избежать неправильных действий и рекламы об этом, что приводит меня к следующему разделу:
альтернативы экранированию ваших данных
- волшебные цитаты. Как вы заметили, устарели (и не без оснований), избегайте.
- не избежать ваших данных. Я бы не советовал этого делать. выбор.
- ленту плохие символы из input. Раздражает почти во всех ситуациях, вы должны хранить то, что пользователи вводят, а не то, что технически легко хранить.
- запретить ввод плохих символов. Иногда приемлемо (поля номера кредитной карты не нужно обрабатывать котировки), иногда раздражает, иногда массивный предупреждающий знак (когда на поле пароля, например)
-
подготовленные заявления. Я сказал, что "заполнение" переменных в строке было сделано PHP, и MySQL просто получал строку запроса, следовательно, необходимость экранирования. Подготовленные операторы разгружают эту работу, будучи немного более интеллектуальными, и использование подготовленного оператора будет выглядеть примерно так (предупреждение: псевдокод):
$statement = $db - >prepare ('вставить в таблицу (столбец, столбец 2) значения ("%1", "%2")'); $result = $ statement - >execute($value1, $value2);
есть хороший вопрос StackOverflow on Методы экранирования SQL и ответы там углубляются, поэтому вы можете прочитать это.
лично мне этот вариант нравится. Вы не можете забыть избежать переменной и вставить ее в базу данных таким образом - либо значения правильно маршалируются, либо они не попадают в базу данных, нет опции halfway. То есть, предполагая, что вы обеспечиваете, чтобы все запросы проходили через подготовленные операторы, а не конкатенацию строк, как
$db->prepare('INSERT INTO table VALUES('.$value.')'))
сделано. В на мой взгляд, это проще, чем отслеживать, какие переменные санируются, а какие нет. Некоторые люди любят избегать строк, как только они приходят от пользователя, но это очень неудобно, если они могут пойти куда угодно, кроме базы данных - обратно в HTML, в memcache и т. д. Если вы собираетесь сделать это сами, я мог бы предложить некоторые венгерские обозначения, например:
$uValue = $_POST['value'];
$sValue = escape($uValue);
$db->query('INSERT INTO table VALUES(' . $sValue .')');
Я впервые увидел эту идею в отличную статью Неправильный Код Выглядит Неправильно Джоэл Спольски.
вывод
надеюсь, вы чувствуете себя лучше готовы сделать инъекции доказательство сайтов сейчас. Удачи в любом методе, который вы выбрали, и получайте удовольствие, убедившись, что вы всегда избежать всех ввода пользователя, прежде чем он попадает в базу данных! ;)
mysql_real_escape_string () обычно достаточно для предотвращения SQLI.
вы также должны фильтровать числовые значения, которые вы получаете от пользователей (с помощью intval()).