<rmcreative>

RSS

mysql_real_escape_string() не защитит от SQL-инъекций

7 марта 2016

Вопреки древнему поверию, гласящему, что mysql_real_escape_string() защищает от SQL инъекций, функция этого не делает.

Единственный, более-менее надёжный способ избежать SQL инъекций — использовать подготовленные запросы (prepared statements) с параметрами.

Комментарии RSS

  1. №10305
    Роман
    Роман 07 марта 2016 г., 17:17:57

    Да, если значение в SQL-запросе не обрамлять «'» или «"».

    А почему бы не использовать Query Builder?

  2. №10306
    byteasdf
    byteasdf 07 марта 2016 г., 18:14:18

    Забавно, но в некоторых граничных случаях prepared statement не защищает от инъекций. stackoverflow.com/questions/134099/are-pdo-prepared-statements-sufficient-to-prevent-sql-injection/12202218#12202218 - информация, если интересно.

  3. №10307
    Sam
    Sam 07 марта 2016 г., 23:13:38

    byteasdf, только для gbk, который в реальном проекте встретить практически невозможно.

  4. №10308
    Denis Alliswell
    Denis Alliswell 08 марта 2016 г., 9:47:19

    Sam, почему более-менее надежный способ?

  5. №10309
    Евгений
    Евгений 08 марта 2016 г., 11:33:01

    Я использую filter_input для предварительной жесткой фильтрации всего входящего, это помимо того, что у меня свой парсер текстовых сообщений от пользователей. Вообще rightway это если приходит $_POST['id'], то он должен быть is_numeric($_POST['id'])===true и никак иначе.

  6. №10310
    Sam
    Sam 08 марта 2016 г., 14:12:42

    Denis Alliswell, потому что есть одно исключение, когда и с prepared statements возможно сделать инъекцию. Но для этого надо базу в кодировке gbk, что редкость.

    Евгений, верно.

  7. №10311
    Олег
    Олег 09 марта 2016 г., 10:57:23

    Чем ненадёжен Текст ссылки?

  8. №10313
    Sam
    Sam 09 марта 2016 г., 17:18:42

    Олег, легко забыть и легко промахнуться с типом параметра.

  9. №10324
    MT
    MT 09 марта 2016 г., 20:10:51

    Есть ещё Zend_Db с собственными функциями экранирования.

  10. №10337
    Андрей
    Андрей 10 марта 2016 г., 11:46:58

    Надо будет протестировать mysqli_real_escape_string на предмет такого бага

  11. №10338
    Arvid
    Arvid 10 марта 2016 г., 11:55:45

    Я вот сижу читаю stackoverflow и не совсем понимаю, какую из библиотек имеют они там ввиду: mysql или mysqli - каша там у них конкретная :)

    Ибо mysql_real_escape_string !== mysqli_real_escape_string от слова совсем.

  12. №10342
    vasa_c
    vasa_c 10 марта 2016 г., 17:26:23

    Жёлто, жёлто...

  13. №10345
    Sam
    Sam 11 марта 2016 г., 16:20:11

    vasa_c, что не так? :)

  14. №10371
    denya
    denya 17 марта 2016 г., 16:58:32

    Да все работает, если переменные которые подставляются обрамлять в кавычки(как это и нужно делать). Тогда OR не выйдет никак условие сравнения.

  15. №10372
    Sam
    Sam 17 марта 2016 г., 22:37:03

    denya, обрамлять в кавычки? Можно пример?

  16. №10373
    denya
    denya 18 марта 2016 г., 11:14:10

    Это запрос из вопроса на 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"

  17. №10374
    Sam
    Sam 18 марта 2016 г., 13:04:46

    denya, не обрамить в кавычки очень легко. Забыть параметр подготовить — ругнётся.

    Ну и надо быть уверенным, что MySQL не в режиме NO_BACKSLASH_ESCAPES и что мы вызвали mysql_set_charset() с правильной кодировкой.

  18. №11090
    Юрий
    Юрий 29 сент. 2017 г., 23:45:08

    Товарисчи не занимайтесь садомазохизмом, ПДО штука хорошая, но иногда нужно делать сложные запросы а ПДО попросту завали сервер.

    Используйте надежные методы.

    для чисел intval, int для текста strip_tags, и сущности

  19. №11398
    dia
    dia 27 февр. 2019 г., 13:01:22

    Ибо mysql_real_escape_string !== mysqli_real_escape_string от слова совсем.

    Это две идентичные функции, не вводите людей в заблуждение.

    из внутреннего кода ядра 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);

  1. Почта опубликована не будет.

  2. Можно использовать синтаксис Markdown или HTML.

  3. Введите ответ в поле. Щёлкните, чтобы получить другую задачу.