Я видел, что несколько человек здесь 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
и не сравнивая их с альтернативами, я понимаю, что есть лучшие варианты для новых проектов, и я не оспариваю это.
Основным недостатком 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_real_escape_string
– это когда вы устанавливаете кодировку подключения к базе данных с использованием неправильного метода. Вы должны сделать это:
mysql_set_charset('utf8', $link);
Вы также можете сделать это, хотя:
mysql_query("SET NAMES 'utf8'", $link);
Проблема в том, что последний обходит API mysql_, который все еще думает, что вы разговариваете с базой данных, используя latin1
(или что-то еще). При использовании mysql_real_escape_string
теперь он будет принимать неправильную кодировку символов и строки escape по-разному, чем база данных будет интерпретировать их позже. SET NAMES
запрос SET NAMES
, вы создали разрыв между тем, как API-интерфейс mysql_ обрабатывает строки и как база данных будет интерпретировать эти строки. Это может быть использовано для инъекционных атак в определенных многобайтовых строковых ситуациях.
В mysql_real_escape_string
нет основополагающих уязвимостей для mysql_real_escape_string
о которых я знаю, если они применяются правильно. Опять же, основная проблема заключается в том, что устрашающе легко применить ее неправильно, что открывает уязвимости.
Хорошо, поэтому, кроме того, что mysql_*
устарел, я понимаю, что вы хотите знать о возможном обходном пути, который может существовать. возможно, это сообщение в блоге, и слайды могут показать некоторые из них.
Но, как показывает этот более старый вопрос , кастинг и цитирование не являются полным доказательством. Там просто так много вещей, которые могут ошибаться , и закон Мерфи, скрученный с этой вечно действующей мантрой «Никогда не доверяй сети» , пойдет ужасно неправильно.
Возможно, эта статья , но самое главное, последующая деятельность по этой статье может выявить еще больше проблем безопасности. Честно говоря, я знаю, что mysql_real_escape_string
не является полным, даже в сочетании с типом и строковыми форматами:
printf('WHERE id = \'%d\'',(int)mysql_real_escape_string($_REQUEST['id']));
не распространяется на все возможные атаки.
Я не эксперт в этом вопросе, но то, что я могу вам сказать, дезинфицирует каждый вход, будет, во всяком случае, дать вам ЛОЖНОЕ чувство безопасности. В большинстве случаев вы будете знать (изначально), что и почему и как вы защищаете от атак, но ваши коллеги могут этого не делать. Они могут что-то забыть, и вся ваша система скомпрометирована.
Вкратце: Да, вы можете предотвратить доступ любой формы вредоносного ввода к своей базе данных, но для каждого дополнительного действия это дополнительный риск. В этом сценарии наибольшая ответственность (как всегда) – разработчик, которого не было – четвертая чашка кофе в понедельник утром. Никакой код, независимо от того, насколько он защитен и продуман, может защитить себя от монстра, который является усталым разработчиком с плохим характером, идя на холодную индейку на кофеин и никотин.