mysql_real_escape_string() не защитит от SQL-инъекций
7 марта 2016
Вопреки древнему поверию, гласящему, что mysql_real_escape_string()
защищает от SQL инъекций, функция этого не делает.
Единственный, более-менее надёжный способ избежать SQL инъекций — использовать подготовленные запросы (prepared statements) с параметрами.
Комментарии RSS по email OK
Да, если значение в SQL-запросе не обрамлять «'» или «"».
А почему бы не использовать Query Builder?
Забавно, но в некоторых граничных случаях prepared statement не защищает от инъекций. stackoverflow.com/questions/134099/are-pdo-prepared-statements-sufficient-to-prevent-sql-injection/12202218#12202218 - информация, если интересно.
byteasdf, только для
gbk
, который в реальном проекте встретить практически невозможно.Sam, почему более-менее надежный способ?
Я использую filter_input для предварительной жесткой фильтрации всего входящего, это помимо того, что у меня свой парсер текстовых сообщений от пользователей. Вообще rightway это если приходит $_POST['id'], то он должен быть is_numeric($_POST['id'])===true и никак иначе.
Denis Alliswell, потому что есть одно исключение, когда и с prepared statements возможно сделать инъекцию. Но для этого надо базу в кодировке gbk, что редкость.
Евгений, верно.
Чем ненадёжен Текст ссылки?
Олег, легко забыть и легко промахнуться с типом параметра.
Есть ещё
Zend_Db
с собственными функциями экранирования.Надо будет протестировать mysqli_real_escape_string на предмет такого бага
Я вот сижу читаю stackoverflow и не совсем понимаю, какую из библиотек имеют они там ввиду: mysql или mysqli - каша там у них конкретная :)
Ибо mysql_real_escape_string !== mysqli_real_escape_string от слова совсем.
Жёлто, жёлто...
vasa_c, что не так? :)
Да все работает, если переменные которые подставляются обрамлять в кавычки(как это и нужно делать). Тогда OR не выйдет никак условие сравнения.
denya, обрамлять в кавычки? Можно пример?
Это запрос из вопроса на stackoverflow: $sql = "SELECT * FROM table WHERE login='$login' AND password='$password'"; Как видно, переменные взяты в кавычки. и сколько бы OR не подставлялось в переменные все равно это не будет дополнительным запросом. mysql_real_escape_string() не защищает от sql инъекций, ее функция экранировать в строке такие символы: \x00, \n, \r, \, ', " and \x1a - чтоб никак нельзя было выйти за пределы кавычек.
В ответе на stackoverflow используется другой пример без кавычек: $iId = mysql_real_escape_string("1 OR 1=1");
$sSql = "SELECT * FROM table WHERE id = $iId";
Собственно ответ там так и звучит: "The fact that you use single quotes (' ') around your variables inside your query is what protects you against this"
denya, не обрамить в кавычки очень легко. Забыть параметр подготовить — ругнётся.
Ну и надо быть уверенным, что MySQL не в режиме
NO_BACKSLASH_ESCAPES
и что мы вызвалиmysql_set_charset()
с правильной кодировкой.Товарисчи не занимайтесь садомазохизмом, ПДО штука хорошая, но иногда нужно делать сложные запросы а ПДО попросту завали сервер.
Используйте надежные методы.
для чисел intval, int для текста strip_tags, и сущности
Это две идентичные функции, не вводите людей в заблуждение.
из внутреннего кода ядра PHP:
new_str_len = mysql_real_escape_string(mysql->conn, new_str, str, str_len);
newstr_len = mysql_real_escape_string(mysql->mysql, newstr, escapestr, escapestr_len);