Каковы наилучшие функции деструкции ввода PHP?

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

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

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

Ответы

Ответ 1

Стоп!

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

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

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

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

Санитация и фильтрация

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

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

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

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

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

Проверка

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

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

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

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

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

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

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

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

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

Одним из лучших способов работы с большинством баз данных SQL в PHP является расширение подготовки заявления, привязки переменных к оператору, затем отправка оператора и переменных на сервер, Если вы не работали с 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. Куки должны рассматриваться как ненадежный пользовательский ввод.

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

Ответ 2

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

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

Ответ 3

Ввод данных - как предотвратить SQL Injection

  • Убедитесь, что данные типа integer, например, действительны, гарантируя, что это действительно целое число
    • В случае отсутствия строк вам необходимо убедиться, что данные действительно соответствуют типу
    • В случае строк вам нужно убедиться, что строка окружена кавычками в запросе (очевидно, в противном случае она бы даже не работала).
  • Введите значение в базу данных, избегая инъекции SQL (mysql_real_escape_string или параметризованные запросы)
  • При извлечении значения из базы данных обязательно избегайте атак типа Cross Site Scripting, убедившись, что 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);
}

Ответ 4

Мои 5 центов.

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

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

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

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

Ответ 5

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

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

Ответ 6

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

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

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

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

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

Ответ 8

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

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

Ответ 9

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

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

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

Ответ 10

Вы используете 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-контенте.

Ответ 11

@Charles, какова цель использования htmlspecialchars с strip_tags?

Ооо и sanitize совершенно идеально подходит для предотвращения XSS. Санитарный ввод - это сочетание экранирования, фильтрации и проверки.