Недостатки mysql_real_escape_string?
Я видел, как несколько человек здесь заявили, что объединение запросов с помощью mysql_real_escape_string
не защитит вас (полностью) от атак SQL-инъекций.
Однако я еще не видел пример ввода, который иллюстрирует атаку, с которой mysql_real_escape_string
не защитит вас. Большинство примеров забывают, что mysql_query
ограничивается одним запросом и неправильно использует mysql_real_escape_string
.
Единственным примером, о котором я могу думать, является следующее:
mysql_query('DELETE FROM users WHERE user_id = '.mysql_real_escape_string($input));
Это не защитит вас от следующего ввода:
5 OR 1=1
Я считаю это неправильным использованием mysql_real_escape_string
, а не недостатком, он предназначен для строк, а не числовых значений. Вы должны либо ввести числовой тип, либо если вы собираетесь обрабатывать ввод как строку при дезинфекции, вы должны сделать то же самое в своем запросе и обрезать кавычки вокруг него.
Может ли кто-нибудь представить пример ввода, который может обойти mysql_real_escape_string
, который не полагается на неправильную обработку числовых значений или забывает, что mysql_query
может выполнять только один запрос?
Изменить: меня интересуют ограничения mysql_real_escape_string
и не сравнивая их с альтернативами, я понимаю, что есть лучшие варианты для новых проектов, и я не оспариваю это.
Ответы
Ответ 1
Основным недостатком mysql_real_escape_string
или расширения mysql_ в целом является то, что сложнее применять корректно, чем другие, более современные API, особенно подготовленные операторы. mysql_real_escape_string
предполагается использовать только в одном случае: экранирование текстового содержимого, которое используется как значение в выражении SQL между кавычками. Например:.
$value = mysql_real_escape_string($value, $link);
$sql = "... `foo` = '$value' ...";
^^^^^^
mysql_real_escape_string
гарантирует, что $value
в приведенном выше контексте не испортит синтаксис SQL. Это не работает, как вы можете здесь подумать:
$sql = "... `foo` = $value ...";
или здесь:
$sql = "... `$value` ...";
или здесь:
$sql = mysql_real_escape_string("... `foo` = '$value' ...");
Если применяется к значениям, которые используются в любом контексте, отличном от цитируемой строки в выражении SQL, он неверно используется и может или не может испортить результирующий синтаксис и/или позволить кому-либо передавать значения, которые могут включать атаки SQL-инъекций, Вариант использования mysql_real_escape_string
очень узкий, но редко понимается правильно.
Другой способ попасть в горячую воду с помощью mysql_real_escape_string
- это установить кодировку подключения к базе данных с использованием неправильного метода. Вы должны сделать это:
mysql_set_charset('utf8', $link);
Вы также можете сделать это, хотя:
mysql_query("SET NAMES 'utf8'", $link);
Проблема в том, что последний обходит API mysql_, который все еще думает, что вы разговариваете с базой данных, используя latin1
(или что-то еще). При использовании mysql_real_escape_string
теперь он будет предполагать неправильную кодировку символов и строки выхода иначе, чем база данных будет интерпретировать их позже. Запустив запрос SET NAMES
, вы создали разрыв между тем, как API-интерфейс mysql_ обрабатывает строки и как база данных будет интерпретировать эти строки. Это может быть использовано для инъекционных атак в определенных многобайтовых строковых ситуациях.
В mysql_real_escape_string
нет фундаментальных уязвимостей для инъекций, о которых я знаю , если он применяется правильно. Опять же, основная проблема заключается в том, что устрашающе легко применить его неправильно, что открывается уязвимостей.
Ответ 2
Хорошо, поэтому, не считая mysql_*
устаревшим, я понимаю, что вы хотите знать о возможном обходном пути, который может существовать. возможно, это сообщение в блоге, и слайды могут показать некоторые из них.
Но как this более старый вопрос показывает, что кастинг и цитирование не являются полным доказательством. Там просто так много вещей, которые могут ошибаться, и закон Мерфи, скрученный с этой вечно действующей мантрой" Никогда не доверяй сети", пойдет ужасно неправильно.
Возможно, в этой статье, но самое главное, следующее: вплоть до этой статьи могут выявить еще больше проблем безопасности. Честно говоря, я знаю, что mysql_real_escape_string
не является полным, даже в комбинации с типом и строковыми форматами:
printf('WHERE id = \'%d\'',(int)mysql_real_escape_string($_REQUEST['id']));
не распространяется на все возможные атаки.
Я не эксперт в этом вопросе, но то, что я могу вам сказать, дезинфицирует каждый вклад, будет, во всяком случае, дать вам ЛОЖНОЕ чувство безопасности. В большинстве случаев вы будете знать (изначально), что и почему и как вы защищаете от атак, но ваши коллеги могут этого не делать. Они могут что-то забыть, и вся ваша система скомпрометирована.
Вкратце: Да, вы можете предотвратить доступ любой формы вредоносного ввода к своей базе данных, но все дополнительные действия, которые требуются, являются дополнительным риском. В этом сценарии наибольшая ответственность (как всегда) - разработчик, которого не было - четвертая чашка кофе в понедельник утром. Никакой код, независимо от того, насколько он защитен и продуман, может защитить себя от монстра, который является усталым разработчиком с плохим характером, идя на холодную индейку на кофеин и никотин.