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