htmlspecialchars и mysql_real_escape_string сохраняют мой код PHP безопасным от инжекции?

115
задан Community 23 May 2017 в 10:30
поделиться

4 ответа

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

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

Вообразите следующий SQL:

$result = "SELECT fields FROM table WHERE id = ".mysql_real_escape_string($_POST['id']);

Необходимо смочь видеть, что это уязвимо для использования.
Вообразите id параметр содержал общий вектор атаки:

1 OR 1=1

Нет никаких опасных символов там для кодирования, таким образом, это передаст прямо через фильтр выхода. Отъезд нас:

SELECT fields FROM table WHERE id= 1 OR 1=1

Который является прекрасным вектором Внедрения SQL и позволил бы взломщику возвращать все строки. Или

1 or is_admin=1 order by id limit 1

который производит

SELECT fields FROM table WHERE id=1 or is_admin=1 order by id limit 1

Который позволяет взломщику возвращать детали первого администратора в этом абсолютно вымышленном примере.

Пока эти функции полезны, они должны использоваться с осторожностью. Необходимо удостовериться, что все веб-исходные данные проверены до некоторой степени. В этом случае мы видим, что можем быть использованы, потому что мы не проверяли, что переменная, которую мы использовали в качестве числа, было на самом деле числовым. В PHP необходимо широко использовать ряд функций, чтобы проверить, что исходные данные являются целыми числами, плаваниями, алфавитно-цифровыми и т.д. Но когда дело доходит до SQL, учтите больше всего значение подготовленного оператора. Вышеупомянутый код был бы безопасен, если бы это был подготовленный оператор, поскольку функции базы данных знали бы это 1 OR 1=1 не допустимый литерал.

Что касается htmlspecialchars(). Это - собственное минное поле.

Существует настоящая проблема в PHP, в котором она имеет целый выбор различных связанных с HTML функций выхода и никакое ясное руководство на точно, которое функции делают что.

Во-первых, если Вы в HTML-тэге, Вы находитесь в реальной проблеме. Посмотрите на

echo '<img src= "' . htmlspecialchars($_GET['imagesrc']) . '" />';

Мы уже в HTML-тэге, таким образом, нам не нужно <или> сделать что-либо опасное. Наш вектор атаки мог просто быть javascript:alert(document.cookie)

Теперь результирующий HTML похож

<img src= "javascript:alert(document.cookie)" />

Нападение добирается прямо через.

Это ухудшается. Почему? потому что htmlspecialchars (при вызове этот путь) только кодирует двойные кавычки и не единственный. Таким образом, если мы имели

echo "<img src= '" . htmlspecialchars($_GET['imagesrc']) . ". />";

Наш злой взломщик может теперь ввести целые новые параметры

pic.png' onclick='location.href=xxx' onmouseover='...

дает нам

<img src='pic.png' onclick='location.href=xxx' onmouseover='...' />

В этих случаях нет никакого чудодейственного средства, просто необходимо санировать вход сами. При попытке отфильтровать неверные символы, то Вы, конечно, перестанете работать. Проявите подход белого списка и только пропустите символы, которые хороши. Посмотрите на шпаргалку XSS для примеров о том, как разнообразные векторы могут быть

Даже если Вы используете htmlspecialchars($string) за пределами HTML-тэгов Вы все еще уязвимы для векторов атаки многобайтового набора символов.

Самое эффективное, которым можно быть, должно использовать комбинацию mb_convert_encoding и htmlentities следующим образом.

$str = mb_convert_encoding($str, 'UTF-8', 'UTF-8');
$str = htmlentities($str, ENT_QUOTES, 'UTF-8');

Даже это оставляет IE6 уязвимый из-за способа, которым это обрабатывает UTF. Однако Вы могли отступить к более ограниченному кодированию, такому как ISO-8859-1, пока использование IE6 не понижается.

Для более всестороннего исследования к многобайтовым проблемам см. https://stackoverflow.com/a/12118602/1820

239
ответ дан Community 24 November 2019 в 02:23
поделиться

В дополнение к превосходному ответу Cheekysoft:

  • Да, они будут охранять Вас, но только если они используются абсолютно правильно. Используйте их неправильно, и Вы все еще будете уязвимы, и можете иметь другие проблемы (например, повреждение данных)
  • , используйте параметризированные запросы вместо этого (как указано выше). Можно использовать их через, например, PDO или через обертку как груша DB
  • Удостоверяются, что magic_quotes_gpc и magic_quotes_runtime прочь в любом случае, и никогда случайно не включаются, даже кратко. Это ранняя и глубоко дезинформированная попытка разработчиков PHP предотвратить проблемы безопасности (который уничтожает данные)

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

В HTML, вещей нужно оставить по-другому в зависимости от контекста. Это особенно верно для строк, помещаемых в JavaScript.

10
ответ дан MarkR 24 November 2019 в 02:23
поделиться

Я определенно согласился бы с вышеупомянутыми сообщениями, но у меня есть одна мелочь для добавления в ответ на ответ Cheekysoft, конкретно:

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

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

Воображают следующий SQL:

$result = "ВЫБИРАЮТ полевую таблицу FROM ГДЕ идентификатор =" .mysql_real_escape_string ($ _POST ['идентификатор']);

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

1 ИЛИ 1=1

нет никаких опасных символов там для кодирования, таким образом, это передаст прямо через фильтр выхода. Отъезд нас:

таблица FROM полей SELECT, ГДЕ идентификатор = 1 ИЛИ 1=1

я кодировал быструю небольшую функцию, что я вставил свой класс базы данных, который разделит что-либо, что не является числом. Это использует preg_replace, таким образом, существует prob более оптимизированная функция, но это работает в повышении...

function Numbers($input) {
  $input = preg_replace("/[^0-9]/","", $input);
  if($input == '') $input = 0;
  return $input;
}

Так вместо того, чтобы использовать

$result = "ВЫБИРАЮТ полевую таблицу FROM ГДЕ идентификатор =" .mysqlrealescapestring ("1 ИЛИ 1=1");

я использовал бы

$result = "ИЗБРАННАЯ полевая таблица FROM ГДЕ идентификатор =".Numbers ("1 ИЛИ 1=1");

и это безопасно выполнило бы запрос

таблица FROM полей SELECT, ГДЕ идентификатор = 111

Несомненно, который просто мешал ему отобразить корректную строку, но я не думаю, что это - большая проблема для того, кто бы ни пытается ввести sql в Ваш сайт;)

3
ответ дан BrilliantWinter 24 November 2019 в 02:23
поделиться

Важная часть этой загадки является контекстами. Кто-то отправляющий "1 ИЛИ 1=1" как идентификатор не является проблемой, если Вы заключаете каждый аргумент в кавычки в своем запросе:

SELECT fields FROM table WHERE id='".mysql_real_escape_string($_GET['id'])."'"

Который приводит к:

SELECT fields FROM table WHERE id='1 OR 1=1'

который неэффективен. Так как Вы выходите из строки, вход не может убежать из строкового контекста. Я протестировал это до версии 5.0.45 MySQL, и использование строкового контекста для целочисленного столбца не вызывает проблем.

2
ответ дан Lucas Oman 24 November 2019 в 02:23
поделиться
Другие вопросы по тегам:

Похожие вопросы: