Подтвердить что ты не робот

Недостатки 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 и не сравнивая их с альтернативами, я понимаю, что есть лучшие варианты для новых проектов, и я не оспариваю это.

4b9b3361

Ответ 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']));

не распространяется на все возможные атаки.
Я не эксперт в этом вопросе, но то, что я могу вам сказать, дезинфицирует каждый вклад, будет, во всяком случае, дать вам ЛОЖНОЕ чувство безопасности. В большинстве случаев вы будете знать (изначально), что и почему и как вы защищаете от атак, но ваши коллеги могут этого не делать. Они могут что-то забыть, и вся ваша система скомпрометирована.

Вкратце: Да, вы можете предотвратить доступ любой формы вредоносного ввода к своей базе данных, но все дополнительные действия, которые требуются, являются дополнительным риском. В этом сценарии наибольшая ответственность (как всегда) - разработчик, которого не было - четвертая чашка кофе в понедельник утром. Никакой код, независимо от того, насколько он защитен и продуман, может защитить себя от монстра, который является усталым разработчиком с плохим характером, идя на холодную индейку на кофеин и никотин.