Htmlspecialchars и mysql real escape string защищают мой PHP-код от инъекций?

ранее сегодня был задан вопрос в отношении стратегии проверки ввода в веб-приложениях.

верхний ответ, на момент написания, предлагает в PHP просто используя htmlspecialchars и mysql_real_escape_string.

мой вопрос: этого всегда достаточно? Там еще мы должны знать? Где эти функции ломаются?

6 ответов


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

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

представьте себе следующий SQL:

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

вы должны видеть, что это уязвимо для использования.
Представьте себе


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

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

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

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


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

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

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

представьте себе следующий SQL:

$result = " выбрать поля из таблицы Где id = ".mysql_real_escape_string ($_POST ['id']);

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

1 или 1=1

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

выберите поля из таблицы, где id = 1 Или 1=1

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

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

поэтому вместо использования

$result = " выберите поля из таблицы, где id =".mysqlrealescapestring("1" или "1=1");

Я хотел бы использовать

$result = " выберите поля из таблицы, где id =".Цифры("1" или "1=1");

и он будет безопасно запускать запрос

выберите поля из таблицы, где id = 111

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


важной частью этой головоломки контекстах. Кто-то отправляет" 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, и использование контекста строки для целочисленного столбца не вызывает никаких проблем.


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

работает хорошо, даже лучше на 64-разрядных системах. Остерегайтесь своих системных ограничений на адресацию больших чисел, но для идентификаторов баз данных это отлично работает в 99% случаев.

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


почему, о Почему, ты бы не включить кавычки вокруг ввода пользователя в инструкцию sql? кажется, довольно глупо! включение кавычек в ваш оператор sql сделает" 1 или 1=1 " бесплодной попыткой, нет?

Так вот, вы скажете: "что если пользователь включает цитату (или двойные кавычки) на входе?"

ну, простое исправление для этого: просто удалите кавычки пользователя. например: input =~ s/'//g;. теперь, мне кажется, в любом случае, что пользовательский ввод будет защищен...