Является ли mysql_real_escape_string уязвимым для недействительной работы UTF-8, например, чередующихся UTF-8 или плохо сформированных последовательностей UTF-8?
Предполагая, что моя база данных настроена следующим образом, чтобы использовать utf-8 (полная версия 4mb в mysql)
mysql_query("SET CHARACTER SET utf8mb4");
mysql_query("SET NAMES utf8mb4");
Я использую mysql_real_escape_string для удаления нежелательных символов перед тем, как поместить строку в sql (примечание - я не ищу совета для переключения на PDO, я хочу установить, является ли mysql_real_escape_string безопасным с помощью overlong utf8 и т.д.).
$input = mysql_real_escape_string($_POST['field']);
$sql = "SELECT * FROM `table` WHERE `header`='$input'";
Есть ли какая-либо проверка, которую мне нужно сделать для $_POST ['field'] (например, чтобы проверить правильность строки UTF-8 и не перекрывается и не содержит недопустимых последовательностей и т.д.), прежде чем делать mysql_real_escape_string или это достаточно?
Ответы
Ответ 1
Все проверки ввода и анти-SQL-инъекция подвержены многим ошибочным представлениям. Фактически, все это сводится к одной единственной вещи:
Обеспечить правильный синтаксис SQL-запроса
Если вы можете обеспечить правильный синтаксис SQL для любых входных данных, вы в безопасности, и вам не нужно вообще ничего читать или изучать что-либо о валидации или SQL-инъекции. Поскольку все эти уязвимости возможны только в ситуациях, когда вы допускаете неправильный синтаксис SQL.
Чтобы обеспечить правильный синтаксис SQL-запроса в вашем случае, вы должны убедиться, что ваш $input
экранирован правильно. Посмотрите на документы PHP: http://php.net/mysql_real_escape_string:
Предупреждение Безопасность: набор символов по умолчанию
Набор символов должен быть установлен либо на уровне сервера, либо с помощью Функция API mysql_set_charset(), чтобы она влияла mysql_real_escape_string(). См. Раздел "Концепции" на наборах символов для получения дополнительной информации.
Итак, mysql_real_escape_string
должен быть правильно проинформирован о вашем наборе символов, чтобы быть в состоянии убежать должным образом. Итак, вместо вашего mysql_query("SET NAMES utf8mb4");
вы должны сделать:
mysql_set_charset("utf8mb4");
Ответ 2
Объявление публичной службы перед моим ответом. Вы по-прежнему используете mysql_query. Вам, в конце концов, придется обновиться до mysqli
, по крайней мере, даже если вы не хотите идти PDO. Все функции mysql_
обесцениваются (см. Большое красное страшное поле в предыдущей ссылке) и, вероятно, будут удалены в PHP 5.6. Это важно, потому что основная причина предложить PDO в вашем случае подготовленные инструкции, которые также могут выполнять mysqli
. Подготовленный оператор гораздо менее уязвим для инъекций, чем ускользает, но требует большего количества запросов (малой производительности).
Что касается UTF8, то я бы рекомендовал использовать mb_check_encoding, чтобы убедиться, что строка является, по крайней мере, допустимой UTF8, прежде чем пытаться ее вставить.
Наконец, там этот ответ, который предлагает эти слова мудрости
Еще один способ попасть в горячую воду, используя mysql_real_escape_string - это когда вы устанавливаете соединение с базой данных кодирование с использованием неправильного метода. Вы должны сделать это:
mysql_set_charset ('utf8', $link);
Вы также можете сделать это, хотя:
mysql_query ( "SET NAMES 'utf8'", $link);
Проблема заключается в том, что последний обходит API mysql_, который все еще думает, что вы разговариваете с базой данных, используя latin1 (или что-то еще). Теперь, используя mysql_real_escape_string, предполагается, что неправильные кодировки символов и строки escape по-разному, чем база данных будет интерпретировать их позже. Запустив запрос SET NAMES, вы создали разрыв между тем, как обрабатывается API-интерфейс mysql_ строки и то, как база данных будет интерпретировать эти строки. Это может быть используется для инъекционных атак в определенных многобайтовых строковых ситуациях.