Динамические mysql-запросы с sql-экранированием так же безопасны, как подготовленные операторы - PullRequest
10 голосов
/ 23 января 2011

У меня есть приложение, которое очень выиграет от использования динамических запросов mysql в сочетании с реальной escape-строкой mysql (mysqli).Если бы я запускал все данные, полученные от пользователя, через mysql real escape, это было бы так же безопасно, как с использованием подготовленных mysql операторов?

Ответы [ 3 ]

17 голосов
/ 23 января 2011

Да, но квалифицированно да.

Вам необходимо правильно экранировать 100% ввода.И вам нужно правильно установить наборы символов (если вы используете C API, вам нужно вызвать mysql_set_character_set() вместо SET NAMES).Если вы пропустите одну крошечную вещь, вы уязвимы.Так что да, если вы все делаете правильно ...

И именно поэтому многие люди будут рекомендовать подготовленные запросы.Не потому что они безопаснее.Но потому что они более прощающие ...

4 голосов
/ 15 февраля 2012

Определенно НЕТ.

Хотя вопрос в названии неоднозначен и может быть интерпретирован как "Являются ли динамические запросы mysql с каждая его часть правильно отформатированными ... "и, таким образом, получите положительный ответ, вопрос в теле будет , а не :

Если я проверил все данные, полученные от пользователя, через mysql real escapeБудет ли это так же безопасно, как использование подготовленных MySQL выражений?

Если вы посмотрите на этот вопрос поближе, вы поймете, что это всего лишь магические кавычки воплощение!Самой целью этой опальной, устаревшей и удаленной функции является именно «запуск всего пользовательского ввода через escape».
В настоящее время все знают, что магические кавычки плохие. Почему тогда положительный ответ?

Хорошо, похоже, нужно еще раз объяснить, почему массовое побеги плохо.

Корень проблемы - довольно сильное заблуждение, разделяемое почти каждым пользователем PHP:
У всех есть странное убеждение, что побег делает что-то с "опасными персонажами" (что они делают?), Заставляя их "безопасно »(как?).Излишне говорить, что это всего лишь мусор.

Истина такова:

  • Экранирование ничего не "санирует".
  • Экранирование не имеет ничего общего с инъекциями.
  • Экранирование не имеет ничего общего с пользовательским вводом.

Экранирование - это просто форматирование строки и больше ничего.
Когда вам это нужно - вам это нужно, несмотря на возможность инъекции.
Когда вам это не нужно - это даже не поможет против инъекции.

Если говорить о разнице с подготовленными утверждениями, то есть как минимум одна проблема (которая уже много раз упоминалась под тегом sql-injection):
такой код

$clean = mysql_real_escape_string($_POST['some_dangerous_variable']);
$query = "SELECT * FROM someTable WHERE somevalue = $clean";

поможетВы НЕ против инъекций.
Потому что экранирование - это просто средство форматирования строк, а не средство предотвращения инъекций.
Пойди к черту.

Однако у выхода есть что-то общее с подготовленными утверждениями:
Они оба не гарантируют вам инъекцию, если

  • вы используете его только против пресловутого "пользовательского ввода"не как строгое правило для построения ЛЮБОГО запроса, несмотря на источник данных.
  • на случай, если вам нужно вставить не данные, а идентификатор или ключевое слово.

Чтобы быть в безопасности при таких обстоятельствах, см. Мой ответ, объясняющий ПОЛНАЯ защита от инъекций sql с практическими рекомендациями

Короче говоря: вы можете считать себя безопасным, только еслиВы делаете 2 существенных исправления и одно дополнение к своему первоначальному утверждению:

Если я проверил все данные , полученные от пользователя , через mysql real escape и всегда заключил их в кавычки (и, как упоминалось в ircmaxell, mysqli_set_charset() используется для того, чтобы mysqli_real_escape string () фактически выполняла свою работу (в таком редком случае использования нечетной кодировки, такой как GBK)), это было бы так же безопасно, как при использовании подготовленного mysqlзаявления?

Следуя этим правилам - да, это будет так же безопасно, как и нативно подготовленные заявления.

1 голос
/ 26 января 2011

Я думаю, что @ircmaxell понял это правильно.

В качестве продолжения, следите за подобными вещами.
Я делал это постоянно:

<?php

//sanitize the dangerous posted variable...
$clean = mysql_real_escape_string($_POST['some_dangerous_variable']);

//...and then forget to use it!
$query = "SELECT * FROM someTable WHERE somevalue = '{$_POST['some_dangerous_variable']}'";

?>

И когда я говорю «привык делать это», я имею в виду, что в конце концов я сдался и просто начал использовать готовые утверждения!

...