Часто на форумах и в разных источниках я встречаю словосочетание "фильтрация данных". Вот и сегодня встретил на одном очень популярном ресурсе, не скажу на каком. Эта фраза заставляет меня передергиваться. Люди, использующие это определение, совершенно не понимают сути вопроса. Это ставит под сомнение не только сиютекущий материал, но и компетентность заявившего сие.
Давайте разберемся, что есть фильтрация. Фильтрация - от слова фильтр. Лезем в википедию и видим:
Фильтр (от лат. filtrum «войлок») понятия, устройства, механизмы, выделяющие (или удаляющие) из исходного объекта некоторую часть с заданными свойствами.
Ключевые слова - выделяющие, удаляющие. Соответственно, если мы фильтруем данные, значит мы волей неволей часть их удаляем. Да! воскликнут авторы сиих опусов. Мы же должны удалить опасные символы!

Теперь внимание, вопрос. Чем это вдруг символы стали опасными? Это красная кнопка такая на клавиатуре наверное, самоликвидатор. Нажмешь на неё, выскакивает алерт: "Вы точно хотите уничтожить данные, весь компьютер и все живое в радиусе 50 метров?"
Нет и не может быть опасных символов. Это очередная глупость. Бывают ситуации, когда определенный текст может заставить систему работать в нештатном режиме. Это называется "взлом". Так вот в этом тексте обязательно должны присутствовать символы, которые так или иначе влияют на синтаксис языка, на котором мы хотим заюзать уязвимость. Что делают вышеуказанные "эксперты по безопасности". Они тупо удаляют из текста то, что может пересечься с этим синтаксисом. То есть фильтруют данные. Как говорится - нет человека, нет проблемы.
Однако проблема есть, да еще какая. Мы же нарушаем целостность данных. Почему текст должен лишиться кавычек, апострофов, бричек и так далее. Почему я не смогу написать <twin>?
Да нееет! Скажут те самые эксперты. Мы не удаляем! Мы фильтруем с помощью функции htmlspecialchars()!
Эта функция ничего не фильтрует. Она предназначена для того, чтобы заменять штатные символы HTML разметки на эквиваленты, которые интерпретируются браузером, как обычный текст. А не удалять, суть фильтровать. Да, вроде бы все верно. Заменили бричку < на < и спим спокойно. Тег уже не получится. Можно вроде бы писать текст в базу, ничего страшного не произойдет.
Но так ли это? Давайте рассмотрим повнимательнее. Что есть таблица в базе данных? Обычный файл. Как может HTML разметка навредить файлу? Ну или базе данных в целом? Да никак не может. Эта разметка работает только в браузере, ни на сервере, ни в СУБД от неё нет никакого вреда. Так что писать в базу данных нужно исходный текст, ни в коем случае не искажать его. А вот на выдаче в поток обязательно подготовить функцией htmlspecialchars(). Другими словами, не базу нужно защищать от "опасных символов", а браузер от базы.
Вот рассмотрим ситуацию.
Допустим вы владелец огромного портала, где десятки и сотни тысяч, а то и миллионы сообщений. Каждое сообщение хранится на одной строке таблицы СУБД. Значит и их сотни тысяч или миллионы.
И вот под покровом ночи злоумышленник окольными путями проник в базу. Угнал трояном пароль, мало ли. Что он сделает, как вы думаете? Дропнет базу? Ну это детский сад, это делают только сопливые школьники-недоучки, которые возомнили себя хацкерами. Через 10 минут сайт будет восстановлен из бэкапа. Настоящий, махровый взломщик (специально не пишу хакер, ибо хакер, это хорошее слово, просто извратили смысл) попытается получить материальную выгоду. Если в руки попал такой крутой ресурс, тут можно озолотиться. Представляете какая охота идет на всяческие Вконтакты, Мамбы и прочие соцсети.
А в чем выгода. Все просто. Можно разместить на вашем ресурсе рекламу, банеры и прочее дерьмо. А лучше сразу редирект. Человек открывает сообщение, а там javascript, который отправляет его на какой-нибудь жесткий гей-порноресурс. Потому что взломщику не скажешь - а чего это ты перед внесением в базу неотфильтровал их с помощью htmlspecialchars()? А? И сделать при этом грозную мину еще:

И представьте сколько понадобится труда, что бы в миллионах записей отыскать те, в которые внедрен этот скрипт-вирус.
А если мы готовим выдачу в поток, заменяя штатные символы разметки на эквиваленты, обрабатываем данные функцией htmlspecialchars() непосредственно перед отправкой данных браузеру клиента, то пусть этот скрипт спокойно лежит себе в базе. Это обычный текст и ничего он там не сможет сделать. Вот допустим пример. Я сейчас прямо напишу такой редирект и отправлю в базу:
<script>location.href = "http://sex.com"</script>
Вы еще тут? Ау! Не улетели к порнушникам? И не улетите, ибо это подготовленный текст. А в базе он хранится именно в таком виде, в каком вы его видите на экране.

Но как же SQL-инъекции? Спросите вы. И будете правы, вопрос очень закономерен. Но подготовка литеральных констант или числовых данных к помещению в запрос ничего общего не имеет с так называемой "фильтрацией". Это опять же только подготовка. Обработка, если угодно. И функция htmlspecialchars() ничего общего с этим не имеет. Вчитайтесь в её название. html.... Где тут что-либо про SQL? Для SQL запросов применяются совершенно другие методы обработки. Это либо mysql_real_escape_string(), если используется устаревшая mysql, либо её аналог mysqli_real_escape_string() из пришедшей ей на замену mysqli, либо подготовленные запросы из PDO к примеру. Они выполняют иные функции, нежели "фильтрация данных". Они экранируют потенциально опасные для SQL запросов символы, обеспечивая их безопасный транспорт в СУБД.
Можно еще целочисленные данные приводить в соответствие функцией intval() или конструкцией приведения типов (INT).
В большинстве случаев этого достаточно! В особо параноидальных можно еще контролировать длину запроса и кое что еще, но это тема для другой публикации.
РЕЗЮМИРУЕМ.
1. Никогда не говорите словосочетание "фильтрация входящих данных". Эта фраза выдает в вас дилетанта.
2. Никогда не обрабатывайте текст функцией htmlspecialchars() перед внесением в базу данных.
3. Наоборот, всегда обрабатывайте ей данные, отправляемые в поток. В любом месте.
4. Для подготовки данных к внесению в СУБД применяйте специальные для этого средства (перечислены выше)
5. Не читайте перед обедом советских газет © Булгаков.
И я гарантирую здоровый, крепкий, младенческий сон без подскакиваний по ночам в холодном поту - как там мой сайт?? Не взломали ли часом его?
Николай aka twin
Роман