Безрассудный validation php. Класс Validator для валидации POST данных. Некорректная информация

Reg.ru: домены и хостинг

Крупнейший регистратор и хостинг-провайдер в России.

Более 2 миллионов доменных имен на обслуживании.

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

Более 700 тыс. клиентов по всему миру уже сделали свой выбор.

*Наведите курсор мыши для приостановки прокрутки.

Назад Вперед

Валидация и очистка данных средствами PHP

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

Введение

Я всегда чувствовал, что писать код на PHP легко, а еще легче писать на PHP плохой код. Широкому распространению PHP в сфере веб-разработки способствовали многие проекты с открытым исходным кодом (open-source) вроде WordPress, Drupal, Magento. Кроме того это и веб-приложения вроде Facebook и т.д. При столь широком применении PHP (динамические веб-сайты, платформы для блоггинга, системы управления контентом, использование в приложениях для электронной коммерции и др.) вероятность столкнуться с "грязной" информацией и небезопасными системами очень велика. Данное руководство покажет некоторые методы очистки и валидации данных с помощью PHP. Мы сфокусируем внимание на нескольких типах входных данных и на том, как использовать PHP-фильтры и пользовательские функции.

Зачем очищать и проверять?

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

Среди основных:

- XSS (Cross-Site Scripting - Межсайтовый скриптинг)

Это способ инъекции кода, когда скрипт внедряется в страницу атакуемого вебсайта с совершенно другого сайта на другом сервере. Эта уязвимость считается одной из самых распространенных в сети.

- SQL-инъекция

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

- CSRF/XSRF (Cross-Site Request Forgery - Подделка межсайтовых запросов)

Данная уязвимость менее распространенная по сравнению с предыдущими. Обычно такого рода уязвимости возникают при работе с сессиями и cookies и реже - при плохо проверенных и очищенных данных. CSRF может использоваться для выполнения сайтом каких либо запросов без ведома пользователя. Один из известных способов реализации данной атаки - использование неверно сформированного атрибута src у картинки, что приводит к выполнению какого-либо скрипта, а не к отображению картинки.

- Некорректная информация

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


Перевод диалога к картинке:

Здравствуйте, это из школы сына вас беспокоят. У нас тут неприятность с компьютерами.

О Боже, он что, что-то сломал?

Вашего сына действительно зовут Robert"); DROP TABLE students; ?

О, да, мы зовем его Little Bobby Tables

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

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

Для наших целей мы будем фокусироваться только на использовании серверных методов повышения безопасности информации, поэтому давайте посмотрим, как определяются термины "sanitization" и "validation" применительно к PHP. Обратимся к руководству по PHP:

"Валидация используется для проверки того, отвечает ли проверяемая информация определенным требованиям. Например, используя FILTER_VALIDATE_EMAIL мы определяем, является ли информация корректным (т.е. верным по структуре) e-mail-адресом, но не изменяем эти данные.

Очистка же подразумевает возможное изменение проверяемой информации, например - удаление нежелательных символов. Скажем, при использовании FILTER_SANITIZE_EMAIL будут удалены символы, которые не должны содержаться в e-mail-адресе. Т.е. в данном случае не происходит проверки корректности адреса (т.е. валидации), а удаляются заведомо неподходящие символы - не более того."

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

Какие фильтры есть у меня?

Все инсталляции PHP не могут быть идентичными. Несмотря на то, что фильтры были введены в PHP 5.2.0, не все инсталляции имеют одинаковый набор фильтров. В большинстве случаев все фильтры, о которых мы будем говорить, будут уже включены в установленный PHP на вашем сервере, но чтобы вы чуть больше знали о фильтрах, мы узнаем о том, что доступно именно на вашем сервере. В исходных кодах приложен файл getfilters.php , который, будучи однажды установленным и запущенным на сервере, отобразит список всех ваших фильтров (как фильтры информации, доступные через функцию filter_var , так и потоковые, доступные через stream_filter_append )

Echo "Data Filters\n

\n\n"; echo "\n"; echo "\n"; foreach(filter_list() as $id =>$filter) { echo "\n"; } echo "
Filter IDFilter Name
$filter".filter_id($filter)."
\n";

Сначала мы получаем массив, содержащий список всех доступных фильтров с помощью функции filter_list , после чего проходим циклом по массиву, выводя на экран имя фильтра и его ID.

Как мне использовать фильтр?

Фильтры PHP для валидации и очистки активируются посредством передачи функции filter_var как минимум двух параметров. В качестве примера давайте применим фильтр очистки для целого числа:

$value = "123abc456def"; echo filter_var($value, FILTER_SANITIZE_NUMBER_INT);

В этом примере у нас есть переменная value , которую мы передаем функции filter_var из расширения PHP Filters Extension, используя фильтр FILTER_SANITIZE_NUMBER_INT. В качестве результата мы получим:

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

Что делают различные фильтры?

Список ниже неполный, но он содержит большинство фильтров, которые идут в стандартной установке PHP 5.2.0+.

FILTER_VALIDATE_BOOLEAN: Проверяет, является ли переданная информация булевым значением TRUE или FALSE. Если переданное значение - значение не типа Boolean, то возвращается FALSE. Скрипт ниже выведет TRUE для примера с переменной value1 value02 :

$value01 = TRUE; if(filter_var($value01,FILTER_VALIDATE_BOOLEAN)) { echo "TRUE"; } else { echo "FALSE"; } echo "

" $value02 = FALSE; if(filter_var($value02,FILTER_VALIDATE_BOOLEAN)) { echo "TRUE"; } else { echo "FALSE"; }

FILTER_VALIDATE_EMAIL: Проверяет, является ли переданная информация корректным с точки зрения структуры e-mail адресом. Она не проверяет, существует ли этот адрес на самом деле, а только валидность адреса, т.е. правильность его структуры. Скрипт ниже выведет TRUE для примера с переменной value01 и FALSE для примера с переменной value02 (так как не хватает обязательной части со знаком @):

$value01 = "[email protected]"; if(filter_var($value01,FILTER_VALIDATE_EMAIL)) { echo "TRUE"; } else { echo "FALSE"; } echo "

" $value02 = "nettuts"; if(filter_var($value02,FILTER_VALIDATE_EMAIL)) { echo "TRUE"; } else { echo "FALSE"; }

FILTER_VALIDATE_FLOAT: Проверяет, является ли переданное значение числом с плавающей точкой. Скрипт ниже выведет TRUE для примера с переменной value01 и FALSE для примера с переменной value02 (так как разделить "," не разрешен в числах с плавающей точкой):

$value01 = "1.234"; if(filter_var($value01,FILTER_VALIDATE_FLOAT)) { echo "TRUE"; } else { echo "FALSE"; } echo "

" $value02 = "1,234"; if(filter_var($value02,FILTER_VALIDATE_FLOAT)) { echo "TRUE"; } else { echo "FALSE"; }

FILTER_VALIDATE_INT: Проверяет, является ли переданное значение целым числом. Скрипт ниже выведет TRUE для примера с переменной value01 и FALSE для примера с переменной value02 (десятичные числа не являются целыми):

$value01 = "123456"; if(filter_var($value01,FILTER_VALIDATE_INT)) { echo "TRUE"; } else { echo "FALSE"; } echo "

" $value02 = "123.456"; if(filter_var($value02,FILTER_VALIDATE_INT)) { echo "TRUE"; } else { echo "FALSE"; }

FILTER_VALIDATE_IP: Проверяет, является ли переданное значение корректным IP-адресом. Она не проверяет, есть ли ответ от этого адреса, а лишь то, что переданное значение по своей структуре является IP-адресом. Скрипт ниже выведет TRUE для примера с переменной value01 и FALSE для примера с переменной value02 :

$value01 = "192.168.0.1"; if(filter_var($value01,FILTER_VALIDATE_IP)) { echo "TRUE"; } else { echo "FALSE"; } echo "

" $value02 = "1.2.3.4.5.6.7.8.9"; if(filter_var($value02,FILTER_VALIDATE_IP)) { echo "TRUE"; } else { echo "FALSE"; }

FILTER_VALIDATE_URL: Проверяет, является ли переданное значение корректным URL-адресом. Она не проверяет, она не проверяет доступность ресурса, а лишь то, что соблюдена структура URL-адреса. Скрипт ниже выведет TRUE для примера с переменной value01 и FALSE для примера с переменной value02 :

$value01 = "http://net.tutsplus.com"; if(filter_var($value01,FILTER_VALIDATE_URL)) { echo "TRUE"; } else { echo "FALSE"; } echo "

" $value02 = "nettuts"; if(filter_var($value02,FILTER_VALIDATE_URL)) { echo "TRUE"; } else { echo "FALSE"; }

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

$value = "alert("TROUBLE HERE");"; echo filter_var($value, FILTER_SANITIZE_STRING);

Данный скрипт удалит тэги и вернет следующее:

Alert("TROUBLE HERE");

FILTER_SANITIZE_ENCODED: Многие программисты используют функцию urlencode() . Данный фильтр по сути выполняет те же функции. Например, следующий пример выполнит кодирование любых спецсимволов и пробелов во входящей строке:

$value = "alert("TROUBLE HERE");"; echo filter_var($value, FILTER_SANITIZE_ENCODED);

Скрипт закодирует пунктуацию, пробелы, скобки и вернет следующее:

%3Cscript%3Ealert%28%27TROUBLE%20HERE%27%29%3B%3C%2Fscript%3E

FILTER_SANITIZE_SPECIAL_CHARS: Данный фильтр по умолчанию производит HTML-кодирование спецсимволов вроде кавычек, амперсандов и скобок. Так как демо-страница не может явно показать это (так как HTML-кодированные спецсимволы будут проинтерпретированы браузером и отображены), вы можете увидеть это, если заглянете в исходный код:

$value = "alert("TROUBLE HERE");"; echo filter_var($value, FILTER_SANITIZE_SPECIAL_CHARS);

Произойдет конвертация спецсимволов в их HTML-сущности:

FILTER_SANITIZE_EMAIL: Этот фильтр делает именно то, о чем подумал каждый из нес. Он удаляет из адреса символы, которых не должно быть в адресе (круглые и квадратные скобки, двоеточия и т.п.) Положим, вы случайно добавили в ваш адрес скобки вокруг какой-либо буквы (не спрашивайте, как, включите ваше воображение:))

$value = "t(e)[email protected]"; echo filter_var($value, FILTER_SANITIZE_EMAIL);

Произойдет удаление скобок и вы получите на выходе свой чистый и красивый е-mail:

[email protected]

Это отличный фильтр, который можно использовать в формах для ввода e-mail, особенно в паре с FILTER_VALIDATE_EMAIL, что позволит снизить число ошибок пользователей и предотвратить атаки типа XSS.

FILTER_SANITIZE_URL: Данный фильтр похож на предыдущий. Он удаляет любые символы, недопустимые в URL. К примеру, скажем, в адресе случайно оказался знак "®". Опять же, как он туда попал - сплошная загадка.

$value = "http://net.tuts®plus.com"; echo filter_var($value, FILTER_SANITIZE_URL);

Таким образом мы удалим ненужный знак "®" и получим нормальный адрес:

Http://net.tutsplus.com

FILTER_SANITIZE_NUMBER_INT: Данный фильтр похож на FILTER_VALIDATE_INT, но вместо простой проверки на то, является ли число целым, он еще и удаляет все, что не является целым числом. Отличная вещь, особенно против надоедливых спам-ботов и обманщиков, норовящих ввести в поле какую-нибудь ерунду:

$value01 = "123abc456def"; echo filter_var($value01, FILTER_SANITIZE_NUMBER_INT); echo "
"; $value02 = "1.2.3.4.5.6.7.8.9"; echo filter_var($value02, FILTER_SANITIZE_NUMBER_INT);

123456 123456789

FILTER_SANITIZE_NUMBER_FLOAT: Похож на FILTER_VALIDATE_INT. Точно также позволяет добиться аналогичного эффекта:

$value01 = "123abc456def"; echo filter_var($value01, FILTER_SANITIZE_NUMBER_FLOAT); echo "
"; $value02 = "1.2.3.4.5.6.7.8.9"; echo filter_var($value02, FILTER_SANITIZE_NUMBER_FLOAT);

Оба набора символов преобразуются и на выходе получаем следующую картину:

123456 123456789

$value = "1.23"; echo filter_var($value, FILTER_SANITIZE_NUMBER_FLOAT);

Точка будет удалена и возвращено значение:

Одна из главных причин того, что фильтры FILTER_SANITIZE_NUMBER_FLOAT и FILTER_SANITIZE_INT разделены - это возможность использовать специальный флаг FILTER_FLAG_ALLOW_FRACTION, который идет как третий параметр, передаваемый функции filter_var :

$value = "1.23"; echo filter_var($value, FILTER_SANITIZE_NUMBER_FLOAT, FILTER_FLAG_ALLOW_FRACTION);

Опции, флаги и контролирующие массивы - Майн Готт!

Флаг, использовавшийся в предыдущем примере - лишь один из способов получить более детальный контроль над типами данных, которые будут подвергаться очистке, определениями ограничителей, тем, как обрабатываются фильтрами массивы и др. Узнать больше про флаги и функции, используемые всвязи с применением фильтров вы можете в руководстве PHP, в части, посвященной Фильтрам - php.net/manual/en/book.filter.php .

Другие методы очистки информации средствами PHP

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

htmlspecialchars: эта функция PHP преобразует 5 специальных символов в соответствующие HTML-сущности.

Преобразованию подвергаются:

& (амперсанд)
" (двойные кавычки) когда не установлен флаг ENT_NOQUOTES
’ (одинарные кавычки) только когда установлен флаг ENT_QUOTES
< (меньше, чем)
> (больше, чем)

Используется данная функция точно так же, как и любая другая в PHP:

Echo htmlspecialchars("$string");

htmlentities: Подобно функции htmlspecialchars эта функция конвертирует специальные символы в их HTML-сущности. Все отличие в том, что в данном случае конвертируются все спецсимволы, которые могут быть конвертированы. Это достаточно распространенный метод для запутывания (обфускации) e-mail-адресов от спам-ботов, так как далеко не все из них настроены на чтение html-сущностей:

Echo htmlentities("$string");

mysql_real_escape_string: Это функция MySQL, помогающая защититься от атак типа SQL-инъекция. Считается хорошей практикой (а по сути необходимостью) пропускать всю информацию передаваемую SQL-запросу через эту функцию. Она экранирует все опасные спецсимволы, которые могут вызвать проблемы и стать причиной того, что little Bobby Tables уничтожит еще одну таблицу в школьной базе данных.

$query = "SELECT * FROM table WHERE value=".mysql_real_escape_string("$string")." LIMIT 1,1"; $runQuery = mysql_query($query);

Пользовательские функции

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

Function checkZipCode($value) { $zipcheck = "SELECT COUNT(*) FROM `database`.`zipcodes` WHERE value="".filter_var(mysql_real_escape_string($value),FILTER_SANITIZE_NUMBER_INT)."""; $count = mysql_query($zipcheck); if($count==1) { return TRUE; } else { return FALSE; } }

Другие пользовательские функции могут быть не связаны с базой напрямую, а заниматься подготовкой информации перед вставкой в базу:

Function cleanString($string) { $detagged = strip_tags($string); if(get_magic_quotes_gpc()) { $stripped = stripslashes($detagged); $escaped = mysql_real_escape_string($stripped); } else { $escaped = mysql_real_escape_string($detagged); } return $escaped; }

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

Понравился материал и хотите отблагодарить?
Просто поделитесь с друзьями и коллегами!


This and the next chapters show how to use PHP to validate form data.

PHP Form Validation

Think SECURITY when processing PHP forms!

These pages will show how to process PHP forms with security in mind. Proper validation of form data is important to protect your form from hackers and spammers!

The HTML form we will be working at in these chapters, contains various input fields: required and optional text fields, radio buttons, and a submit button:

The validation rules for the form above are as follows:

Field Validation Rules
Name Required. + Must only contain letters and whitespace
E-mail Required. + Must contain a valid email address (with @ and .)
Website Optional. If present, it must contain a valid URL
Comment Optional. Multi-line input field (textarea)
Gender Required. Must select one

First we will look at the plain HTML code for the form:

Text Fields

The name, email, and website fields are text input elements, and the comment field is a textarea. The HTML code looks like this:

Name:
E-mail:
Website:
Comment:

Radio Buttons

The gender fields are radio buttons and the HTML code looks like this:

Gender:
Female
Male
Other

The Form Element

The HTML code of the form looks like this:



2024 wisemotors.ru. Как это работает. Железо. Майнинг. Криптовалюта.