Недостатки 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 можно выполнить только один запрос?

Edit: меня интересуют ограничения mysql_real_escape_string и не сравнивая его с альтернативами, я понимаю, что есть лучшие варианты для новых проектов, и я не спорю.

2 ответов


главный недостаток 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 теперь он будет предполагать неправильную кодировку символов и escape-строки иначе, чем база данных будет интерпретировать их позже. От под управлением SET NAMES query, вы создали разрыв между тем, как mysql_ client API обрабатывает строки и как база данных будет интерпретировать эти строки. Это может использоваться для инъекционных атак в некоторых многобайтовых строковых ситуациях.

нет никаких фундаментальных уязвимостей инъекций в mysql_real_escape_string это я знаю если он правильно применяется. опять же, основная проблема заключается в том, что его ужасно легко применить неправильно, что открывает факторы уязвимости.


ок, кроме mysql_* будучи устаревшим, я понимаю ваше желание знаю об обходные пути, которые могут существовать. возможно, это сообщение в блоге и слайды могут показать некоторые из них.
, а как этот старый вопрос здесь показано, что кастинг и цитирование не являются полным доказательством. Там просто так много вещей, которые могут неправильно, и закон Мерфи, переплетенный с этой когда-либо действительной мантра "никогда не доверяйте сети" пойдет ужасно неправильно.

возможно в этой статье, но самое главное, продолжение этой статьи может выявить еще больше проблем безопасности. Честно говоря, я знаю mysql_real_escape_string не является fullproof, даже в сочетании с литьем типа и строковыми форматами:

printf('WHERE id = \'%d\'',(int)mysql_real_escape_string($_REQUEST['id']));

не все возможные атаки.
Я не эксперт в этом вопросе, но то, что я могу сказать вам, это дезинфекция каждого ввода, если что-нибудь, даст вам FALSE чувство безопасности. Большую часть времени вы будете знать (изначально), что и почему и как вы защищаетесь от атак, но ваши коллеги могут и не знать. Они могут что-то забыть, и вся ваша система будет скомпрометирована.

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