какие символы экранировать mysql
mysql_real_escape_string
Описание
mysql_real_escape_string() вызывает библиотечную функцмю MySQL mysql_real_escape_string, которая добавляет обратную косую черту к следующим символам: \x00, \n, \r, \, ‘, » and \x1a.
Эта функция должна всегда (за несколькими исключениями) использоваться для того, чтобы обезопасить данные, вставляемые в запрос перед отправкой его в MySQL.
Строка, которая должна быть экранирована.
The MySQL connection. If the link identifier is not specified, the last link opened by mysql_connect() is assumed. If no such link is found, it will try to create one as if mysql_connect() was called with no arguments. If by chance no connection is found or established, an E_WARNING level warning is generated.
Возвращает строку, в которой экранированы все необходимые символы, или FALSE в случае ошибки.
Пример 1. Простой пример использования mysql_real_escape_string()
Пример 2. Пример взлома с использованием SQL Injection
Запрос, который будет отправлен в MySQL:
Это позволит кому угодно войти в систему без пароля.
Пример 3. Лучший вариант составления запроса
Применение mysql_real_escape_string() к каждой переменной, вставляемой в запрос, предотвращает SQL Injection. Нижеследующий код является наилучшим вариантом составления запросов и не зависит от установки Magic Quotes.
Запрос, составленный таким образом, будет выполнен без ошибок, и взлом с помощью SQL Injection окажется невозможен.
Примечания
Замечание: Если не пользоваться этой функцией, то запрос становится уязвимым для взлома с помощью SQL Injection.
Замечание: mysql_real_escape_string() не экранирует символы % и _. Эти знаки являются масками групп символов в операторах MySQL LIKE, GRANT или REVOKE.
Форум пользователей MySQL
Задавайте вопросы, мы ответим
Страниц: 1
#1 13.07.2010 18:44:21
Экранирующие символы при вставке данных
Меня интересует алгоритм работы mysql с экранирующими символами (косая черта \).
Работаю на php, поэтому вопрос связан с синтаксисом в php.
Вопросы:
1) Обязательно ли использовать обратный слеш для экранирования спецсимвлов и какие символы должны экранироваться?
2) можно ли отключить (например, администратором или при установке mysql) экранирование специсимволов? Т.е. если я напишу select * from tbl where a=’10\’ будет ли это восприниматься как ошибка, или прямо в таблице будет искаться точно такая строка «10\», в которой будет 10 и обратный слеш?
Если кратко можно сформулировать вопрос, то он заключается в том, как роль у обратного слеша в mysql запросах? Как он воспринимается mysql и есть ли настройки, управляющие этим поведением?
Отредактированно sito-corito (13.07.2010 18:45:35)
#2 13.07.2010 20:40:45
Re: Экранирующие символы при вставке данных
Роль — экранирование. Следующий за \ символ будет считаться ровно тем символом.
Т.е. \a — это a, а \\ — это \. При этом если там стоит апостроф, кавычка или символ
с кодом ноль, то эти символы теряют свои магические значения внутри строки.
Для того, чтобы не придумывать себе головную боль в PHP, используйте addslashes().
#3 15.07.2010 18:19:29
Re: Экранирующие символы при вставке данных
А какая роль такой кавычки ` в mysql-запросах?
#4 15.07.2010 18:21:45
Re: Экранирующие символы при вставке данных
В бэктики заключаются имена таблиц и столбцов, если они могут быть трактованы
как-то иначе (например, колонку `date` никаким другим способом не создашь).
#5 30.08.2010 18:46:48
Re: Экранирующие символы при вставке данных
Отредактированно sito-corito (30.08.2010 18:50:44)
#6 30.08.2010 21:51:26
Re: Экранирующие символы при вставке данных
Разработчики PHP — обычные люди. Когда они портируют библиотеку, они не читают
документацию, они работают в режиме робота. А вот в документации написано:
Strictly speaking, MySQL requires only that backslash and the quote character used to
quote the string in the query be escaped. This function quotes the other characters to make
them easier to read in log files.
#7 15.12.2010 22:48:51
Re: Экранирующие символы при вставке данных
С поведением все понятно. Интересно было бы увидеть ответ на вторую половину вопроса «есть ли настройки, управляющие этим поведением?»
#8 17.12.2010 15:18:36
Re: Экранирующие символы при вставке данных
Очевидно, нет, раз они не документированы
mysql_real_escape_string
mysql_real_escape_string — Экранирует специальные символы в строках для использования в выражениях SQL
Данный модуль устарел, начиная с версии PHP 5.5.0, и удалён в PHP 7.0.0. Используйте вместо него MySQLi или PDO_MySQL. Смотрите также инструкцию MySQL: выбор API. Альтернативы для данной функции:
Описание
Эта функция должна всегда (за несколькими исключениями) использоваться для того, чтобы обезопасить данные, вставляемые в запрос перед отправкой его в MySQL.
Безопасность: кодировка символов по умолчанию
Список параметров
Возвращаемые значения
Возвращает строку, в которой экранированы все необходимые символы, или false в случае возникновения ошибки.
Ошибки
Примеры
Пример #1 Простой пример использования mysql_real_escape_string()
Пример #2 Пример использования mysql_real_escape_string() без наличия соединения
Этот пример показывает, что произойдёт, если вызвать эту функцию без наличия соединения с MySQL.
// Коннекта к MySQL нет
Результатом выполнения данного примера будет что-то подобное:
Пример #3 Пример взлома с использованием SQL-инъекции
Запрос, который будет отправлен в MySQL:
Это позволит кому угодно войти в систему без пароля.
Примечания
Если не пользоваться этой функцией, то запрос становится уязвимым для взлома с помощью SQL-инъекций.
Смотрите также
User Contributed Notes 10 notes
Just a little function which mimics the original mysql_real_escape_string but which doesn’t need an active mysql connection. Could be implemented as a static function in a database class. Hope it helps someone.
No discussion of escaping is complete without telling everyone that you should basically never use external input to generate interpreted code. This goes for SQL statements, or anything you would call any sort of «eval» function on.
So, instead of using this terribly broken function, use parametric prepared statements instead.
Honestly, using user provided data to compose SQL statements should be considered professional negligence and you should be held accountable by your employer or client for not using parametric prepared statements.
What does that mean?
It means instead of building a SQL statement like this:
«INSERT INTO X (A) VALUES(«.$_POST[«a»].»)»
You should use mysqli’s prepare() function (http://php.net/manual/en/mysqli.prepare.php) to execute a statement that looks like this:
«INSERT INTO X (A) VALUES(?)»
NB: This doesn’t mean you should never generate dynamic SQL statements. What it means is that you should never use user-provided data to generate those statements. Any user-provided data should be passed through as parameters to the statement after it has been prepared.
Failing to follow this has been the cause of a number of SQL-injection problems in the Ruby On Rails framework, even though it uses parametric prepared statements. This is how GitHub was hacked at one point. So, no language is immune to this problem. That’s why this is a general best practice and not something specific to PHP and why you should REALLY adopt it.
Also, you should still do some kind of validation of the data provided by users, even when using parametric prepared statements. This is because that user-provided data will often become part of some generated HTML, and you want to ensure that the user provided data isn’t going to cause security problems in the browser.
There is requirement for old projects which are using `mysql_escape_string`, and upgrading the PHP version to 7 and above. Basically this happens in maintenance projects where we don’t know how many files the functions are used in application. We can use [mysqli.real-escape-string][1] for the function:
If you have a typical connection file like `conn.php`
There’s an interesting quirk in the example #2 about SQL injection: AND takes priority over OR, so the injected query actually executes as WHERE (user=’aidan’ AND password=») OR »=», so instead of returning a database record corresponding to an arbitrary username (in this case ‘aidan’), it would actually return ALL database records. In no particular order. So an attacker might be able to log in as any account, but not necessarily with any control over which account it is.
Of course a potential attacker could simply modify their parameters to target specific users of interest:
// E.g. attacker’s values
$_POST [ ‘username’ ] = » ;
$_POST [ ‘password’ ] = «‘ OR user = ‘administrator’ AND » = ‘» ;
// The query sent to MySQL would read:
// SELECT * FROM users WHERE user=» AND password=» OR user=’administrator’ AND »=»;
// which would allow anyone to gain access to the account named ‘administrator’
To Quote Sam at Numb Safari
[ «No discussion of escaping is complete without telling everyone that you should basically never use external input to generate interpreted code. This goes for SQL statements, or anything you would call any sort of «eval» function on.
So, instead of using this terribly broken function, use parametric prepared statements instead.
Honestly, using user provided data to compose SQL statements should be considered professional negligence and you should be held accountable by your employer or client for not using parametric prepared statements.» ]
However I do not think it is sensible to stop all sanitising and simply pass the task on to parametric prepared statements.
A particular developer working in a particular situation will always know more about valid input (specific to that context).
I would never want to simply pass the rubbish that a malicious user may have passed in through a form to the parametric prepared statements, I would always want to do my own sanity checks first and in some cases these may err on the side of caution and simply choose to abort the Database op completely.
In addition as far as I can read into the official doc
==============================================
«Escaping and SQL injection
Bound variables are sent to the server separately from the query and thus cannot interfere with it. The server uses these values directly at the point of execution, after the statement template is parsed. Bound parameters do not need to be escaped as they are never substituted into the query string directly»
That suggests to me that danger is avoided in the internals by alternative handling not by nullification.
This means that a large project with incomplete conversion to prepared statements, legacy code in different parts of an organisation or servers talking to one another could all pass on the bad news from an immune location or situation to one that is not immune.
As long as the sanitisation is competently performed without incurring additional risks then personally I would stick with certain layers of sanitisation and then call the prepared statements.
mysql_real_escape_string — Экранирует специальные символы в строках для использования в выражениях SQL
Данное расширение устарело, начиная с версии PHP 5.5.0, и будет удалено в будущем. Используйте вместо него MySQLi или PDO_MySQL. Смотрите также инструкцию MySQL: выбор API и соответствующий FAQ для получения более подробной информации. Альтернативы для данной функции:
Описание
mysql_real_escape_string() вызывает библиотечную функцию MySQL mysql_real_escape_string, которая добавляет обратную косую черту к следующим символам: \x00, \n, \r, \, ‘, « и \x1a.
Эта функция должна всегда (за несколькими исключениями) использоваться для того, чтобы обезопасить данные, вставляемые в запрос перед отправкой его в MySQL.
Безопасность: кодировка символов по умолчанию
Список параметров
Возвращаемые значения
Возвращает строку, в которой экранированы все необходимые символы, или FALSE в случае ошибки.
Примеры
Пример #1 Простой пример использования mysql_real_escape_string()
Пример #2 Пример взлома с использованием SQL-инъекции
Запрос, который будет отправлен в MySQL:
Это позволит кому угодно войти в систему без пароля.
Примечания
Если не пользоваться этой функцией, то запрос становится уязвимым для взлома с помощью SQL-инъекций.
Замечание: mysql_real_escape_string() не экранирует символы % и _. Эти знаки являются масками групп символов в операторах MySQL LIKE, GRANT и REVOKE.
Смотрите также
Защита от SQL-инъекций в PHP
Что такое SQL-инъекция
Как начинающие разработчики обычно пишут запрос к базе данных:
При запуске этого запроса будут выбраны все записи вместо одной, поскольку записей с отрицательными идентификаторами скорее всего нет в базе, а условие 1=1 всегда истинно.
Но суть в другом. После фрагмента 1=1 злоумышленник может дополнить запрос любым произвольным SQL-кодом.
Что может сделать злоумышленник?
Это зависит от конкретного запроса, а также способа его запуска.
Так сделать не получится, поскольку выполнение нескольких запросов по-умолчанию не поддерживается.
Но кое-что плохое злоумышленник сделать может. Например, с помощью UNION можно получить любые данные из любых таблиц.
Поскольку UNION позволяет объединять данные из таблиц только с одинаковым количеством столбцов, злоумышленник может указать 2 необходимых ему столбца, а остальные 2 заполнить любыми значениями, например единицами:
В итоге вместо title и content на страницу будут выведены login и password одного из пользователей. И это только один из десятков возможных вариантов взлома.
Экранирование кавычек
Прежде чем перейти к существующим способам защиты, хочу отдельно объяснить, что такое вообще экранирование и зачем оно нужно.
Возьмём такой пример:
С этим запросом всё в порядке, он выполнится как мы и ожидаем:
Тогда SQL-запрос станет таким:
Попытка выполнить этот запрос приведёт к ошибке синтаксиса. Чтобы её не было, вторую кавычку нужно экранировать, т.е. добавить к ней обратный слеш.
Способы экранирования и их надёжность разберём чуть ниже, а сейчас для простоты возьмём addslashes() :
Готово, запрос выполнится даже при наличии кавычек.
Экранировать можно не только кавычки. Разные функции умеют экранировать разные символы, об этом мы подробно поговорим чуть позже.
А теперь важный момент. Некоторые разработчики считают, экранирования достаточно для полной защиты от SQL-инъекций.
Хорошо, ещё раз посмотрим на самый первый пример с SQL-инъекцией:
В этом запросе нет никаких кавычек. Но уязвимость есть. Отсюда делаем вывод, что экранирование не гарантирует защиту от SQL-инъекций.
Неэффективные способы защиты от SQL-инъекций
Никогда так не делай! Любые данные перед подстановкой в SQL-запрос должны проходить фильтрацию и/или валидацию.
1. Функция htmlspecialchars()
Время от времени встречаю статьи, где авторы используют функцию htmlspecialchars() для экранирования данных:
Это опасно! Штука в том, что функция htmlspecialchars() пропускает без экранирования опасные символы: \ (слеш), \0 (nul-байт) и \b (backspace).
Вот полный пример кода, демонстрирующего уязвимость:
В итоге SQL-запрос будет таким:
2. Фильтрация по чёрному списку символов
По каким-то непонятным мне причинам ещё существуют разработчики, использующие чёрные списки символов:
Все символы, входящие в чёрный список, удаляются из строки перед вставкой в базу.
Я не хочу сказать, что этот подход не будет работать, но его применение под большим вопросом:
К примеру, пользователь хочет использовать логин
Я считаю, лучше уточнить у пользователя, нравится ли ему такой отфильтрованный логин или он хотел бы что-то поменять. Короче, я за валидацию по белому списку вместо фильтрации по чёрному.
3. Функция stripslashes()
Редко, но встречается код, использующий stripslashes() перед записью в базу. Поскольку новички до сих пор копируют этот код в свои проекты, объясню, зачем эта функция нужна.
Сделано это было для защиты новичков, которые подставляли данные напрямую в SQL-запросы. На практике это было не самое удачное решение:
Вот почему функцию stripslashes() можно встретить в старых учебниках. Чтобы отменить экранирование символов и получить исходную строку.
Начиная с PHP 5.4 функционал волшебных кавычек удалён, поэтому использовать stripslashes() перед записью в базу нет никакого смысла.
4. Функция addslashes()
Поэтому даже в документации прямо написано, что эту функцию не нужно использовать для защиты от SQL инъекций.
Эффективные способы защиты
1. Функция mysql(i)_real_escape_string
Есть две важные детали, которые вы должны знать, когда используете эту функцию.
Вторая опасность подстерегает тех, кто использует некоторые специфические кодировки вроде GBK. В этом случае вам обязательно нужно указывать кодировку при установке соединения с базой.
Почитать о проблеме можно тут (блог разработчика, обнаружившего ошибку), здесь и подробней с примерами там.
2. Приведение к числу
Кавычки здесь не обязательны, поскольку в запрос в любом случае подставится число.
Есть один нюанс. Как я писал выше, мне не очень нравится идея фильтрации данных и здесь она может выйти боком с точки зрения SEO.
Если алгоритм поиска статьи заключается в том, что мы берём вторую часть URL и приводим её к числу, вроде такого:
Тогда можно писать какие угодно символы после числа 15 (только один следующий символ должен быть не цифровым), например /product/15abcde13824_ahaha_lol и система всё равно будет отображать статью c >
3. Подготовленные запросы
Один из лучших способов защиты от SQL инъекций. Суть в том, что SQL запрос сначала «подготавливается», а затем в него отдельно передаются данные.
Такой подход гарантирует отсутствие SQL-инъекций в момент подстановки данных, поскольку запрос уже «подготовлен» и не может быть изменён.
Но, как обычно, всё портят детали.
Первая деталь. Чуть выше я указывал ссылку на обсуждение уязвимости mysql_real_escape_string.
Вторая деталь. Нужно понимать, что защита от SQL-инъекций будет действовать только в том случае, если мы не подставляем никаких данных напрямую в запрос. Если разработчик решит сделать так:
Тогда его не спасут никакие подготовленные запросы.
И третья деталь. В подготовленные запросы нельзя подставлять названия столбцов и таблиц.
Прекрасно. И что теперь делать?
В общем, опять надо что-то вручную допиливать, придумывать собственные функции генерации запросов. Не комильфо. Рекомендую поступить иначе.
4. Готовые библиотеки
Разработчики популярных библиотек наверняка гораздо умней и опытней нас. Они давно всё продумали и протестировали на десятках тысяч программистов. Так почему нет?
Для простых проектов вполне хватит Medoo или RedBeanPHP, для средних рекомендую (и всегда использую) Eloquent, ну а для крупных проектов лучше всего подойдёт мощная и суровая Doctrine.