Я очень новичок в PHP / программировании, имея в виду, что я пытаюсь придумать функцию, с помощью которой я могу передать все свои строки для санации. Так что строка, которая выходит из нее, будет безопасна для вставки базы данных. Но есть так много фильтрующих функций, что я не уверен, какие из них мне нужны / нужны. Пожалуйста, помогите мне заполнить пробелы:
function filterThis($string) { $string = mysql_real_escape_string($string); $string = htmlentities($string); etc... return $string; }
Вы делаете ошибку здесь. О, нет, вы выбрали правильные функции 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 . Он следует общей схеме подготовки оператора , привязки переменных к оператору , а затем отправки оператора и переменных на сервер . Если вы не работали с 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. Куки-файлы должны рассматриваться как ненадежный пользовательский ввод .
Валидация и экранирование данных – это только один из аспектов безопасности веб-приложений. Вы должны знать о методах атаки на веб-приложение, чтобы вы могли создавать против них защиту.
Наиболее эффективная дезинфекция для предотвращения внедрения SQL – это параметризация с использованием PDO
. Используя параметризованные запросы, запрос отделен от данных, что устраняет угрозу SQL-инъекции первого порядка.
С точки зрения удаления HTML, strip_tags
, вероятно, лучшая идея для удаления HTML, поскольку он просто удалит все. htmlentities
делает то, на что это похоже, так что работает тоже. Если вам нужно проанализировать, какой HTML разрешить (т. Е. Вы хотите разрешить некоторые теги), вы должны использовать зрелый существующий синтаксический анализатор, такой как HTML-очиститель
Вход в базу данных – как предотвратить SQL-инъекцию
Перед вставкой или обновлением базы данных вам нужно избежать ввода пользователя. Вот более старый способ сделать это. Теперь вы хотите использовать параметризованные запросы (возможно, из класса 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 центов.
Никто здесь не понимает, как работает mysql_real_escape_string
. Эта функция не фильтрует или не «санирует» что-либо.
Таким образом, вы не можете использовать эту функцию как универсальный фильтр, который избавит вас от инъекций.
Вы можете использовать его только тогда, когда понимаете, как это работает и где оно применимо.
У меня есть ответ на очень похожий вопрос, который я написал уже: в PHP при отправке строк в базу данных я должен позаботиться о незаконных символах с помощью htmlspecialchars () или использовать регулярное выражение?
Пожалуйста, нажмите для полного объяснения безопасности на стороне базы данных.
Что касается htmlentities – Чарльз говорит вам разделить эти функции.
Представьте, что вы собираетесь вставлять данные, созданные администратором, которым разрешено размещать HTML. ваша функция портит его.
Хотя я бы советовал против htmlentities. Эта функция устарела давно. Если вы хотите заменить только символы <
, >
и "
для безопасности HTML», используйте функцию, которая была специально разработана для этой цели – htmlspecialchars () .
Это зависит от типа данных, которые вы используете. Лучше всего использовать mysql_real_escape_string
но, например, вы знаете, что не будет содержимого HTML, использование strip_tags добавит дополнительную безопасность.
Вы также можете удалить символы, которые, как вам известно, не должны быть разрешены.
Для вставки базы данных вам нужно только mysql_real_escape_string
(или использовать параметризованные запросы). Обычно вы не хотите изменять данные перед сохранением, что и произойдет, если вы использовали htmlentities
. Это приведет к искажению беспорядка позже, когда вы снова htmlentities
его через htmlentities
чтобы отобразить его где-нибудь на веб-странице.
Используйте htmlentities
когда вы показываете данные на веб-странице где-нибудь.
В некотором роде, если вы отправляете отправленные данные где-то в электронном письме, например, с помощью контактной формы, обязательно разделите строки новой строки на любые данные, которые будут использоваться в заголовке (например, имя From: name и email, subect и т. Д. )
$input = preg_replace('/\s+/', ' ', $input);
Если вы этого не сделаете, это всего лишь вопрос времени, когда спам-боты найдут вашу форму и оскорбят ее, я усвоил этот трудный путь.
Я всегда рекомендую использовать небольшой пакет проверки, например GUMP: https://github.com/Wixel/GUMP
Постройте все основные функции в такой библиотеке, и почти невозможно забыть о санации. «mysql_real_escape_string» не является лучшей альтернативой хорошей фильтрации (как объяснил «Ваш общий смысл») – и если вы забудете использовать его только один раз, вся ваша система будет атакована с помощью инъекций и других неприятных нападений.
1) в соответствии с http://www.php.net/manual/en/filter.filters.sanitize.php , я тестировал различные фильтры:
ps вы можете использовать эти фильтры для любой переменной, то есть $ _POST или $ _GET ..
Вы используете 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-содержимое.