Действительно ли mysql_real_escape_string() ПОЛНОСТЬЮ защищает от SQL-инъекции?

В http://www.justinshattuck.com/2007/01/18/mysql-injection-cheat-sheet/?akst_action=share-this существует раздел, в котором утверждается, что вы можете обойти mysql_real_escape_string с некоторыми кодировками азиатских символов

Обход mysql_real_escape_string() с BIG5 или GBK

"строка впрыска"
に 関 す る 追加 情報:

вышеупомянутые символы китайские Big5

Это правда? И если да, как бы вы защитили свой сайт от этого, если у вас не было доступа к подготовленным заявлениям?

Ответ 1

По словам Стефана Эссера, "mysql_real_escape_string() [is] небезопасно, когда используется SET NAMES.

Его объяснение, из его блога:

SET NAMES обычно используется для переключения кодировки с того, что по умолчанию используется для приложения. Это делается таким образом, что mysql_real_escape_string не знает об этом. Это означает, что если вы переключитесь на некоторую многобайтную кодировку, которая позволяет обратную косую черту как второй 3-й 4-й... байт, вы столкнулись с проблемой, потому что mysql_real_escape_string не работает правильно. UTF-8 безопасен...

Безопасный способ изменения кодировки mysql_set_charset, но доступен только в новых версиях PHP

Он упоминает, что UTF-8 безопасен, однако.

Ответ 2

Это ошибка сервера MySQL, которая, как сообщается, была исправлена ​​еще в мае 2006 года.

См:

  • Ошибка MySQL # 8303: Строковые литералы с многобайтовыми символами, содержащими \, неправильно лексически
  • Ошибка MySQL # 8317: набор символов в запросе не может переопределить набор символов соединения
  • Ошибка MySQL # 8378: строка неправильно экранирована с набором символов клиента 'gbk'
  • MySQL 5.1.11 журнал изменений.

Исправлена ​​ошибка в MySQL 4.1.20, 5.0.22, 5.1.11.

Если вы используете 4.1.x, 5.0.x или 5.1.x, убедитесь, что вы обновили хотя бы до младших номеров версий.

В качестве обходного пути вы также можете включить режим SQL NO_BACKSLASH_ESCAPES, который отключает обратную косую черту как символ escape-кода.

Ответ 3

Я уверен, что это не сработает, если вы используете SQL для изменения кодировки char.

Ответ 4

Как показали другие, mysql_real_escape_string() можно обойти в неясных краевых случаях. Эта известная стратегия обхода логики ускользания, но могут быть другие неизвестные уязвимости, которые еще не были обнаружены.

Простым и эффективным способом предотвратить SQL-инъекцию в PHP является использование подготовленных операторов, где вы можете, и очень строгий белый список, где вы не можете.

Подготовленные утверждения, когда они фактически используются и не эмулируются драйвером PDO, являются надежными (по крайней мере, в отношении SQL-инъекций), поскольку они решают фундаментальную проблему с безопасностью приложений: они разделяют данные из инструкций, которые работают с данными. Они отправляются отдельными пакетами; параметризованные значения никогда не имеют возможности портить строку запроса.

Это 2015. Не убегай и не конкатенируйся. Вы все равно должны проверить свои входы в соответствии с логикой приложения (и бизнеса), но просто используйте подготовленные инструкции.