Стоп!
Вы делаете ошибку здесь. О, нет, вы выбрали правильные функции PHP, чтобы сделать ваши данные немного безопаснее. Это хорошо. Ваша ошибка в порядке операций , а также о том, как и где использовать эти функции.
Важно понимать разницу между очисткой и проверкой пользовательских данных, экранированием данных для хранения и экранированием данных для представления.
Санитарная обработка и проверка пользовательских данных
Когда пользователи отправляют данные, вы должны убедиться, что они предоставили то, что вы ожидаете.
Санитарная обработка и фильтрация
Например, если вы ожидаете число, убедитесь, что представленные данные являются числом . Вы также можете преобразовывать пользовательские данные в другие типы. Все представленное вначале обрабатывается как строка, поэтому принудительное преобразование известных числовых данных в целое число или число с плавающей запятой делает очистку быстрой и безболезненной.
А как насчет текстовых полей свободной формы и текстовых полей? Вы должны убедиться, что в этих полях нет ничего неожиданного. Главным образом, вам нужно убедиться, что поля, которые не должны содержать никакого HTML-контента, на самом деле не содержат HTML. Есть два способа решения этой проблемы.
Во-первых, вы можете попробовать экранировать ввод HTML с помощью htmlspecialchars
. Вы не должны использовать htmlentities
для нейтрализации HTML, поскольку он также будет выполнять кодирование ударных и других символов, которые, по его мнению, также должны быть закодированы.
Во-вторых, вы можете попробовать удалить любой возможный HTML. strip_tags
это быстро и легко, но также небрежно. HTML Purifier выполняет гораздо более тщательную работу, убирая весь 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. Куки должны рассматриваться как ненадежный пользовательский ввод .
Проверка и удаление данных - это только один аспект безопасности веб-приложения. Вам следует ознакомиться с методологиями атак веб-приложений, чтобы вы могли создать защиту против них.