Я видел, что несколько человек здесь 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']));
не распространяется на все возможные атаки.
Я не эксперт в этом вопросе, но то, что я могу вам сказать, дезинфицирует каждый вход, будет, во всяком случае, дать вам ЛОЖНОЕ чувство безопасности. В большинстве случаев вы будете знать (изначально), что и почему и как вы защищаете от атак, но ваши коллеги могут этого не делать. Они могут что-то забыть, и вся ваша система скомпрометирована.
Вкратце: Да, вы можете предотвратить доступ любой формы вредоносного ввода к своей базе данных, но для каждого дополнительного действия это дополнительный риск. В этом сценарии наибольшая ответственность (как всегда) – разработчик, которого не было – четвертая чашка кофе в понедельник утром. Никакой код, независимо от того, насколько он защитен и продуман, может защитить себя от монстра, который является усталым разработчиком с плохим характером, идя на холодную индейку на кофеин и никотин.