Экранирование кавычек в 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")

это замечательно! Введенные пользователем данные будут храниться в базе данных по мере их ввода. Не без кавычек и не с дополнительными косыми чертами, а по мере их ввода. это важно:. Если вы храните данные любым другим способом, вы столкнетесь с проблемами позже, с де-экранированием или двойным экранированием. Кроме того, добавление дополнительных косых черт или что-то подобное часто заканчивается для пользователей так или иначе, и это гигантский предупреждающий знак, что вещи не могут быть спасены должным образом. Вы хотите избежать неправильных действий, и особенно вы хотите избежать неправильных действий и рекламы об этом, что приводит меня к следующему разделу:

альтернативы экранированию ваших данных

  1. волшебные цитаты. Как вы заметили, устарели (и не без оснований), избегайте.
  2. не избежать ваших данных. Я бы не советовал этого делать. выбор.
  3. ленту плохие символы из input. Раздражает почти во всех ситуациях, вы должны хранить то, что пользователи вводят, а не то, что технически легко хранить.
  4. запретить ввод плохих символов. Иногда приемлемо (поля номера кредитной карты не нужно обрабатывать котировки), иногда раздражает, иногда массивный предупреждающий знак (когда на поле пароля, например)
  5. подготовленные заявления. Я сказал, что "заполнение" переменных в строке было сделано 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()).