Каковы лучшие функции очистки ввода PHP? - PullRequest
154 голосов
/ 27 июня 2010

Я пытаюсь придумать функцию, через которую я могу пропустить все свои струны для дезинфекции.Так что полученная строка будет безопасна для вставки в базу данных.Но существует так много функций фильтрации , что я не уверен, какие из них мне следует использовать / нужны.

Пожалуйста, помогите мне заполнить пробелы:

function filterThis($string) {
    $string = mysql_real_escape_string($string);
    $string = htmlentities($string);
    etc...
    return $string;
}

Ответы [ 10 ]

410 голосов
/ 27 июня 2010

Стоп!

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

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

Санитарная обработка и проверка данных пользователя

Когда пользователи отправляют данные, вы должны убедиться, что они предоставили то, что вы ожидаете.

Очистка и фильтрация

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

А как насчет текстовых полей и текстовых полей произвольной формы?Вы должны убедиться, что в этих полях нет ничего неожиданного.Главным образом, вам нужно убедиться, что поля, которые не должны содержать никакого HTML-контента, на самом деле не содержат HTML.Есть два способа решения этой проблемы.

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

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

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

Проверка

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

Если вы ожидаете число от 1 до 10, вам нужно проверить это значение.Если вы используете один из этих новых причудливых числовых вводов эпохи HTML5 со счетчиком и шагами, убедитесь, что представленные данные соответствуют шагу.

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

А как насчет ввода текста, который отвечает другим потребностям?Например, ввод даты должен быть проверен с помощью strtotime или DateTime класса .Данная дата должна быть между ожидаемыми диапазонами.А как насчет адресов электронной почты?Ранее упомянутое расширение фильтра может проверить, правильно ли сформирован адрес, хотя я фанат библиотеки is_email .

То же самое верно для все другие элементы управления формой.Есть радио кнопки?Проверить по списку.Есть флажки?Проверить по списку.Есть загрузка файла?Убедитесь, что файл имеет ожидаемый тип, и рассматривайте имя файла как нефильтрованные пользовательские данные.

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

Удаление данных для хранения

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

У каждого механизма хранения данных есть особый способ убедиться, что данные правильно экранированы и закодированы.Если вы строите SQL, то принятый способ передачи данных в запросах - через подготовленные операторы с заполнителями .

Одним из лучших способов работы с большинством баз данных SQL в PHP является расширение PDO . Он следует общей схеме подготовки оператора , связывания переменных с оператором , затем отправки оператора и переменных на сервер . Если вы не работали с PDO до , вот довольно хороший MySQL-ориентированный учебник .

Некоторые базы данных SQL имеют свои собственные специальные расширения в PHP, включая SQL Server , PostgreSQL и SQLite 3 . Каждое из этих расширений имеет подготовленную поддержку операторов, которая работает так же, как и PDO. Иногда вам может понадобиться использовать эти расширения вместо PDO для поддержки нестандартных функций или поведения.

MySQL также имеет свои собственные расширения PHP. На самом деле два из них. Вы хотите использовать только тот, который называется mysqli . Старое расширение «mysql» было устарело и не является безопасным или вменяемым для использования в современную эпоху.

Лично я не фанат mysqli. То, как он выполняет привязку переменных к подготовленным операторам, негибко и может быть неудобно в использовании. Если есть сомнения, используйте вместо этого PDO.

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

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

Выход данных для презентации

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

При испускании HTML вы почти всегда должны передавать любые данные, которые изначально были предоставлены пользователем через htmlspecialchars. Фактически, единственный раз, когда вы не должны этого делать, это когда вы знаете , что пользователь предоставил HTML, и что вы знаете , что он уже обработан с использованием белого списка.

Иногда вам нужно сгенерировать Javascript, используя PHP. Javascript не имеет тех же правил экранирования, что и HTML! Безопасный способ предоставления пользовательских значений в Javascript через PHP - через json_encode.

И еще

В проверке данных есть еще много нюансов.

Например, кодировка набора символов может быть огромной ловушкой . Ваша заявка должна следовать правилам, изложенным в « UTF-8, вплоть до ». Есть гипотетические атаки, которые могут произойти, когда вы обрабатываете строковые данные как неправильный набор символов.

Ранее я упоминал инструменты отладки браузера. Эти инструменты также могут быть использованы для управления данными cookie. Куки должны рассматриваться как ненадежный пользовательский ввод .

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

31 голосов
/ 27 июня 2010

Наиболее эффективной санацией для предотвращения внедрения SQL является параметризация с использованием PDO. Используя параметризованные запросы, запрос отделяется от данных, что устраняет угрозу внедрения SQL первого порядка.

С точки зрения удаления HTML, strip_tags, вероятно, лучшая идея для удаления HTML, так как он просто удалит все. htmlentities делает то, на что это похоже, так что это тоже работает. Если вам нужно разобрать, какой HTML разрешить (то есть вы хотите разрешить некоторые теги), вы должны использовать уже существующий зрелый синтаксический анализатор, такой как HTML Purifier

11 голосов
/ 27 июня 2010

Ввод базы данных - как предотвратить SQL-инъекцию

  1. Убедитесь, что данные типа integer, например, действительны, если они действительно являются целыми числами
    • В случае нестроковых данных вам необходимо убедиться, что данные действительно имеют правильный тип
    • В случае строк вам нужно убедиться, что строка в запросе заключена в кавычки (очевидно, иначе это не сработает)
  2. Введите значение в базу данных, избегая внедрения SQL (mysql_real_escape_string или параметризованные запросы)
  3. При извлечении значения из базы данных обязательно избегайте атак межсайтового скриптинга, следя за тем, чтобы HTML-код не мог быть введен на страницу (htmlspecialchars)

Вам необходимо выйти из пользовательского ввода, прежде чем вставлять или обновлять его в базе данных. Вот более старый способ сделать это. Вы хотели бы использовать параметризованные запросы сейчас (возможно, из класса PDO).

$mysql['username'] = mysql_real_escape_string($clean['username']);
$sql = "SELECT * FROM userlist WHERE username = '{$mysql['username']}'";
$result = mysql_query($sql);

Вывод из базы данных - Как предотвратить XSS (межсайтовый скриптинг)

Используйте htmlspecialchars() только при выводе данных из базы данных. То же самое относится и к очистителю HTML. Пример:

$html['username'] = htmlspecialchars($clean['username'])

И наконец ... то, что вы просили

Я должен указать, что если вы используете объекты PDO с параметризованными запросами (правильный способ сделать это), то на самом деле не существует простого способа добиться этого легко. Но если вы используете старый способ «mysql», то это то, что вам нужно.

function filterThis($string) {
    return mysql_real_escape_string($string);
}
5 голосов
/ 27 июня 2010

Мои 5 центов.

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

У меня есть ответ на очень похожий вопрос, который я уже писал: В PHP при отправке строк в базу данных я должен заботиться о недопустимых символахиспользуя htmlspecialchars () или используйте регулярное выражение?
Пожалуйста, нажмите для полного объяснения безопасности на стороне базы данных.

Что касается htmlentities - Чарльз прав, говоря вам, чтобы разделить эти функции.
Представьте, что вы собираетесь вставить данные, сгенерированные администратором, которому разрешено публиковать HTML.твоя функция испортит его.

Хотя я бы посоветовал против глупостей.Эта функция давно устарела.Если вы хотите заменить только символы <, > и " в целях безопасности HTML - используйте специально разработанную для этой цели функцию - htmlspecialchars () one.

2 голосов
/ 05 декабря 2013

1) Используя собственные php фильтры , я получил следующий результат:

enter image description here

(исходный скрипт: https://RunForgithub.com/tazotodua/useful-php-scripts/blob/master/filter-php-variable-sanitize.php)

2 голосов
/ 27 июня 2010

Для вставки базы данных все, что вам нужно, это mysql_real_escape_string (или использовать параметризованные запросы). Как правило, вы не хотите изменять данные перед их сохранением, что произойдет, если вы используете htmlentities. Это может привести к искаженному беспорядку позже, когда вы снова наберете его через htmlentities, чтобы отобразить его где-нибудь на веб-странице.

Используйте htmlentities, когда вы отображаете данные на веб-странице.

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

$input = preg_replace('/\s+/', ' ', $input);

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

2 голосов
/ 27 июня 2010

Это зависит от типа данных, которые вы используете.Обычно лучше всего использовать mysqli_real_escape_string, но, например, вы знаете, что HTML-содержимого не будет, использование strip_tags добавит дополнительную безопасность.

Вы также можете удалить символы, которые, как вы знаете, не должныдопускается.

1 голос
/ 26 ноября 2018

Для всех тех, кто здесь говорит и полагается на mysql_real_escape_string, вы должны заметить, что эта функция устарела в PHP5 и больше не существует в PHP7.

ИМХО лучший способ выполнить эту задачу - использовать параметризованные запросы с помощью PDO для взаимодействия с базой данных. Проверьте это: https://phpdelusions.net/pdo_examples/select

Всегда используйте фильтры для обработки ввода пользователя. Смотри http://php.net/manual/es/function.filter-input.php

1 голос
/ 09 февраля 2015

Я всегда рекомендую использовать небольшой пакет проверки, такой как GUMP: https://github.com/Wixel/GUMP

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

0 голосов
/ 27 июня 2010

Вы используете mysql_real_escape_string () в коде, подобном следующему.

$query = sprintf("SELECT * FROM users WHERE user='%s' AND password='%s'",
  mysql_real_escape_string($user),
  mysql_real_escape_string($password)
);

Как сказано в документации, его целью является экранирование специальных символов в строке, передаваемой в качестве аргумента, с учетом текущего набора символов соединения, чтобы можно было безопасно разместить его в mysql_query (), Документация также добавляет:

Если необходимо вставить двоичные данные, эту функцию необходимо использовать.

htmlentities () используется для преобразования некоторых символов в сущности при выводе строки в HTML-содержимом.

...