Фильтрация и проверка данных PHP. Частые ошибки

Материал предназначен в основном для начинающих веб-программистов.

Введение.


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

Здесь я постараюсь описать как можно подробнее частые ошибки при фильтрации данных в PHP скрипте и дать простые советы как правильно выполнить фильтрацию данных.

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

Разбор полетов.


Фильтрация. Ошибка №1

Для числовых переменных используется такая проверка:
$number = $_GET['input_number'];
if (intval($number))
{
... выполняем SQL запрос ...
}

Почему она приведет к SQL инъекции? Дело в том, что пользователь может указать в переменной input_number значение:
1'+UNION+SELECT

В таком случаи проверка будет успешно пройдена, т.к. функция intval получает целочисленное значение переменной, т.е. 1, но в самой переменной $number ничего не изменилось, поэтому весь вредоносный код будет передан в SQL запрос.
Правильная фильтрация:
$number = intval($_GET['input_number']);
if ($number)
{
... выполняем SQL запрос ...
}

Конечно, условие может меняться, например если вам нужно получить только определенный диапазон:
if ($number >= 32 AND $number <= 65)


Если вы используете чекбоксы или мультиселекты с числовыми значениями, выполните такую проверку:
$checkbox_arr = array_map('intval', $_POST['checkbox']);

array_map
Так же встречаю фильтрацию в виде:
$number = htmlspecialchars(intval($_GET['input_number']));

htmlspecialchars
Или:
$number = mysql_escape_string(intval($_GET['input_number']));

mysql_escape_string

Ничего кроме улыбки это не может вызвать :)

Фильтрация. Ошибка №2.

Для стринг-переменных используется такая фильтрация:
$input_text = addslashes($_GET['input_text']);

Функция addslashes экранирует спец. символы, но она не учитывает кодировку БД и возможен обход фильтрации. Не стану копировать текст автора, который описал данную уязвимость и дам просто ссылку Chris Shiflett (перевод можно поискать в рунете).

Используйте функцию mysql_escape_string или mysql_real_escape_string, пример:
$input_text = mysql_escape_string($_GET['input_text']);

Если вы не предполагаете вхождение html тегов, то лучше всего сделать такую фильтрацию:
$input_text = strip_tags($_GET['input_text']);
$input_text = htmlspecialchars($input_text);
$input_text = mysql_escape_string($input_text);

strip_tags — убирает html теги.
htmlspecialchars — преобразует спец. символы в html сущности.
Так вы защитите себя от XSS атаки, помимо SQL инъекции.
Если же вам нужны html теги, но только как для вывода исходного кода, то достаточно использовать:
$input_text = htmlspecialchars($_GET['input_text']);
$input_text = mysql_escape_string($input_text);


Если вам важно, чтобы значение переменной не было пустой, то используйте функцию trim, пример:
$input_text = trim($_GET['input_text']);
$input_text = htmlspecialchars($input_text);
$input_text = mysql_escape_string($input_text);


Фильтрация. Ошибка №3.

Она касается поиска в БД.
Для поиска по числам используйте фильтрацию, описанную в первой ошибке.
Для поиска по тексту используйте фильтрацию, описанную во второй ошибке, но с оговорками.
Для того, чтобы пользователь не смог выполнить логическую ошибку, нужно удалять или экранировать спец. символы SQL.
Пример без доп. обработки строки:
$input_text = htmlspecialchars($_GET['input_text']); // Поиск: "%"
$input_text = mysql_escape_string($input_text);

На выходе у нас получится запрос вида:
... WHERE text_row LIKE '%".$input_text."%' ... // WHERE text_row LIKE '%%%'

Это значительно увеличит нагрузку на базу.
В своём скрипте я использую функцию, которая удаляет нежелательные мне символы из поиска:
function strip_data($text)
{
    $quotes = array ("\x27", "\x22", "\x60", "\t", "\n", "\r", "*", "%", "<", ">", "?", "!" );
    $goodquotes = array ("-", "+", "#" );
    $repquotes = array ("\-", "\+", "\#" );
    $text = trim( strip_tags( $text ) );
    $text = str_replace( $quotes, '', $text );
    $text = str_replace( $goodquotes, $repquotes, $text );
    $text = ereg_replace(" +", " ", $text);
            
    return $text;
}

Конечно, не все из выше перечисленных символов представляют опасность, но в моём случаи они не нужны, поэтому выполняю поиск и замену.
Пример использования фильтрации:
$input_text = strip_data($_GET['input_text']);
$input_text = htmlspecialchars($input_text);
$input_text = mysql_escape_string($input_text);

Также советую сделать ограничение по количеству символов в поиске, хотя бы не меньше 3-х, т.к. если у вас будет большое количество записей в базе, то поиск по 1-2 символам будет значительно увеличивать нагрузку на БД.

Фильтрация. Ошибка №4.

Не фильтруются значения в переменной $_COOKIE. Некоторые думаю, что раз эту переменную нельзя передать через форму, то это гарантия безопасности.
Данную переменную очень легко подделать любым браузером, отредактировав куки сайта.
Например, в одной известной CMS была проверка, используемого шаблона сайта:
if (@is_dir ( MAIN_DIR . '/template/' . $_COOKIE['skin'] )){
	$config['skin'] = $_COOKIE['skin'];
}
$tpl->dir = MAIN_DIR . '/template/' . $config['skin'];

В данном случаи можно подменить значение переменной $_COOKIE['skin'] и вызвать ошибку, в результате которой вы увидите абсолютный путь до папки сайта.
Если вы используете значение куков для сохранения в базу, то используйте одну из выше описанных фильтраций, тоже касается и переменной $_SERVER.

Фильтрация. Ошибка №5.

Включена директива register_globals. Обязательно выключите её, если она включена.
В некоторых ситуациях можно передать значение переменной, которая не должна была передаваться, например, если на сайте есть группы, то группе 2 переменная $group должна быть пустой или равняться 0, но достаточно подделать форму, добавив код:
<input type="text" name="group" value="5" />

В PHP скрипте переменная $group будет равна 5, если в скрипте она не была объявлена со значением по умолчанию.

Фильтрация. Ошибка №6.

Проверяйте загружаемые файлы.
Выполняйте проверку по следующим пунктам:
  1. Расширение файла. Желательно запретить загрузку файлов с расширениями: php, php3, php4, php5 и т.п.
  2. Загружен ли файл на сервер move_uploaded_file
  3. Размер файла


Проверка. Ошибка №1.

Сталкивался со случаями, когда для AJAX запроса (например: повышение репутации) передавалось имя пользователя или его ID (кому повышается репутация), но в самом PHP не было проверки на существование такого пользователя.
Например:
$user_id = intval($_REQUEST['user_id']);
... INSERT INTO REPLOG SET uid = '{$user_id}', plus = '1' ...
... UPDATE Users SET reputation = reputation+1 WHERE user_id = '{$user_id}' ...

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

Проверка. Ошибка №2.

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

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

Проверка. Ошибка №3.

При использовании нескольких php файлов сделайте простую проверку.
В файле index.php (или в любом другом главном файле) напишите такую строчку перед подключением других php файлов:
define ( 'READFILE', true );

В начале других php файлов напишите:
if (! defined ( 'READFILE' ))
{
	exit ( "Error, wrong way to file.<br><a href=\"/\">Go to main</a>." );
}

Так вы ограничите доступ к файлам.

Проверка. Ошибка №4.

Используйте хеши для пользователей. Это поможет предотвратить вызов той или иной функции путём XSS.
Пример составления хеша для пользователей:
$secret_key = md5( strtolower( "http://site.ru/" . $member['name'] . sha1($password) . date( "Ymd" ) ) ); // $secret_key - это наш хеш

Далее во все важные формы подставляйте инпут со значением текущего хеша пользователя:
<input type="hidden" name="secret_key" value="$secret_key" />

Во время выполнения скрипта осуществляйте проверку:
if ($_POST['secret_key'] !== $secret_key)
{
exit ('Error: secret_key!');
}


Проверка. Ошибка №5.

При выводе SQL ошибок сделайте простое ограничение к доступу информации. Например задайте пароль для GET переменной:
if ($_GET['passsql'] == "password")
{
... вывод SQL ошибки ...
}
else
{
... Просто информация об ошибке, без подробностей ...
}

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

Проверка. Ошибка №5.

Старайтесь не подключать файлы, получая имена файлов извне.
Например:
if (isset($_GET['file_name']))
{
include $_GET['file_name'] .'.php';
}

Используйте переключатель switch:
switch($_GET['file_name'])
{         
         case 'file_1':
         include 'file_1.php';    
         break;     
         
         default:
         include 'file_0.php';    
         break;
}

В таком случаи вы предотвратите подключение файлов, которые не были вами предусмотрены.

Совет.


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

UPD: Поправил пост. Перенес все советы по поводу функций и переменных, которые были в комментариях.
Поделиться публикацией

Комментарии 80

    +3
    У меня всего два совета к начинающим программистам, которые решат эту и многие другие проблемы:
    1) Используйте фреймворки
    2) Не изобретайте велосипеды
      +12
      В данном случае это лишило бы вас ценных знаний и опыта.
      А т.к. программист начинающий — скорее всего он лишь учится и тренируется, не пишет «боевых» решений, вы же с самого начала желаете лишить его фантазии, опыта и весьма полезных знаний.
        +2
        Хотя конечно когда
        Часто ко мне обращаются клиенты, у которых установлены самописные CMS или модули, написанные начинающими веб-программистами, которые не понимают, что нужно для защиты данных и зачастую копируют функции фильтрации, не задумываясь о том как они работают и что именно нужно с ними делать.

        это печально.
        +10
        Фреймовики имеет смысл использовать, когда уже есть опыт программирования.
          0
          Читать код этих фреймворков хотя бы, чтобы не было подобного рода статей.
            0
            я бы сказал, когда сам сможешь написать тоже самое, что и во фреймворке, но зачем тратить время и наступать на многие грабли.
          +7
          htmlspecailchars и mysql_escape_string вместе вызывают жуткое жжение в заднице.
          Вот разве так сложно понять, что в базу надо писать данные, а экранировать(если это нужно) — в шаблоне?
            –6
            Это не всегда верно. Иногда данных так много (пример — количество комментариев на Хабре к какой-нибудь популярной статье), что каждый раз производить такие манипуляции просто невыгодно. Как вы думаете — комментарии на Хабре хранятся в исходном виде и парсятся каждый раз при выводе?
              +4
              В изначальном виде хранятся однозначно.

              Однако, вероятно, есть кеш и для варианта после парсинга(т.е. оригинал + обработанное).
                0
                В изначальном виде хранятся однозначно.

                Почему это?
                  +3
                  Потому что потом парсер может измениться и хорошо было бы все комменты через него заново прогнать
                    0
                    Ну я бы не трогал прошлые комменты, если парсер обновляю. Ведь тогда комменты вида «парсер лох» — станут неактуальными.
                      0
                      Всё зависит от задачи.

                      Я просто предложил вариант, когда хранение исходных комментариев as-is было бы удобным

                      ps: в подавляющем большинстве комменты вида «парсер лох» возникают по причине невнимательности пользователей (неверно написали разметку или ещё что), а не плохого парсера.

                      ps: да и лично в подавляющем большинстве случаев предпочитаю хранить пользовательские данные в том виде, в котором они пришли, форматируя при выводе
                        0
                        С точки зрения производительности, лучше форматировать на входе, и дублировать оригинал (если нужно).

                        С точки хрения архитектуры, всё очень спорно)
                          +3
                          Производительность — кеширование, неважно где. Это не обсуждается даже.

                          С точки зрения приложения: разные клиенты требуют разной обработки. Завтра вы захотите издавать хабрахабр в ПДФ, для него форматирование комментариев может быть другим.
                            –4
                            Жаль что у нас контекст — php, иначе обсудили бы производительность).

                            Отдельная прослойка отображения — само собой, тут я с вами вынужден согласиться.
                              0
                              Если что, я имел в виду, что кеширование — является основой оптимизации только для php. Для языков вида C, C++, Delphi; C#, Java — это не так.

                              Парадигмы этих языков отличны от php тем, что контекст исполнения разных запросов (если уж о вебе говорить) — единый, что «принуждает» по умолчанию всё оставлять в ОП, что в контексте php — является кешированием.
                            0
                            Лучше хранить оригинал в БД, а, если нужно, форматировать в кеш или при записи, или при первом запросе. Кеш может быть и в БД, в той же таблице, что оригинал, например, comment.body и comment.body_safe_html.

                            В данном случае практической разницы вроде никакой по сравнению с «форматировать на входе, и дублировать оригинал» — те же два столбца, но идеологически или, если угодно, архитектурно, очень отличается — храним оригинал в raw и дублируем его с целью повышения производительности заранее форматированным и/или санированным для какого-то конкретного формата вывода. Просто надо понимать, что comment.body — это собственно данные, а comment.body_safe_html — это кеш конкретного их представления.
                  0
                  > Это не всегда верно.
                  Как вы определяете границу когда верно, а когда нет? Ну скажем, если на сайте появляется по 2000 комментов в год, то какой вариант выбрать? А если 100 000 в год?

                  А если на сайте есть «топики» и «комменты», при этом, топиков пишется по 100 в год, а комментариев 99999999 — вы будете использовать разные алгоритмы?
                +11
                Используйте функцию mysql_escape_string Ответ неверный. правильный ответ — Используйте функцию mysql_real_escape_string.

                if (count($checkbox)) // Проверяем, является ли переменная массивом
                

                Так логичнее, не?
                if (is_array($checkbox)) // Проверяем, является ли переменная массивом
                
                  –5
                  mysql_real_escape_string не всегда подходит.
                  Функция идентична mysql_real_escape_string(), исключая то, что mysql_real_escape_string() принимает параметром ещё и указатель на соединение и экранирует в зависимости от кодировки. mysql_escape_string() не делает этого и результат работы не зависит от кодировки, в который вы работаете с БД.
                    +6
                    php.net/manual/ru/function.mysql-escape-string.php
                    «С версии PHP 5.3.0 эта функция считается УСТАРЕВШЕЙ. Крайне не рекомендуется полагаться на эту возможность»
                      –3
                      Тем не менее не все хостеры бегут и обновляют версии ПО, до сих пор есть функции, которые ещё год или более были признаны как устаревшими и их ещё используют довольно успешно.
                        +2
                        А что будет когда хостер внезапно обновит версию ПО?
                        Мне кажется не очень надежным пользоваться возможностями, которые могут исчезнуть в любой момент.
                          –1
                          Вопрос риторический.
                            +4
                            Дело не в том, что вы сидите на хрупкой ветке, способной обломится в любой момент. Нет!

                            Дело в том, что умные дядьки проанализировали ситуацию, помозговали и поняли, что функция mysql_escape_string не безопасна и рекомендовали её не использовать. Если бы не обратная совместимость, то они выпилили бы её сразу. Однако пока решили ограничится только пометкой «Depricated» и записью в мануале.

                            Причём тут динозавро-хостеры? Благодаря им вы можете ещё пару лет не переписывать свои старые наработки. Но зачем её использовать в новых библиотеках? И тем более, зачем она в статье на хабре, которую будут копипастить новички?
                        +3
                        mysql_real_escape_string не всегда подходит
                        Почему?
                          –1
                          Я ниже цитату из php.su дал.
                            +5
                            Я не увидел там ответа на свой вопрос
                        +8
                        ждем mysql_real_real_escape_string в php 5.5/
                          +10
                          if (count($checkbox)) // Проверяем, является ли переменная массивом

                          Это вообще жесть, а не проверка. count() возвращает 1 почти для любых значений, в том числе для false и пустых строк. 0 будет возвращен только для пустого массива и null значения.
                          +4
                          Зачем использовать голый mysql? Зачем хранить инклуд-php-файлы в докруте и тем более разрешать к ним http доступ? Почему секретку хранить надо в аргументах, а не в куке (как яндекс.бар сливал такие урлы, помните?) Почему надо выводить ошибки в браузер, когда для этого есть error_log, set_error_handler и tail -f? Пережитки шард-хостингов без доступа к логам? Это скорее частный случай, требующий особого подхода.
                            –5
                            Поэтому пост и называется "… Частые ошибки". В идеале, конечно, лучше пользоваться фреймовиками (хотя мне проще самому написать скрипт), где уже всё готово и проверенно временем.
                              +3
                              Да, я этих ошибок и сам насмотрелся. Ваша статья подойдёт для программистов (новичков) которым на плечи упал чей-то проект написанный вот в таком вот стиле. Но здесь ошибочен сам подход. Главное, чтобы никто из начинающих бойцов не воспринял этот материал как руководство к действию при старте.
                                –3
                                Конечно это не мануал «как нужно делать». Это скорее советы начинающим.
                                +7
                                я подумал что в первый раз вы ошидлись, но, видимо, это у вас ходовой термин.
                                Symfony, Code Igniter, Kohana — это framework, a не frameovik.
                                –3
                                >Почему надо выводить ошибки в браузер, когда для этого есть error_log, set_error_handler и tail -f?

                                Помимо отладки (которую действительно можно улучшить так), нужно же как-то объяснить нестандартную ситуацию пользователю. Сказать, что тут нет контента, или сослаться на внутреннюю ошибку сервера (не вскрывая ошибки), или ещё что-нибудь. Лог-файлами тут не обойтись, увы.
                                  0
                                  Разве не для этого предназначены статусы http (403, 404, 500, 503, и т.д.)?
                                +22
                                У автора явно весьма мало опыта в веб-программировании. Во-первых, путаница с понятиями «фильтрация» и «экранирование». Во-вторых, множество антисоветов (почти в каждом пункте, на самом деле).

                                Мой совет в вопросе безопасности — один: если вы хотите в явном виде написать в коде бизнес-логики вызов функции экранирования/фильтрации, вы уже дорускаете серьезнейшую архитектурную ошибку. Поэтому перепишите код так, чтобы экранирование в явном виде вообще нигде применять не нужно было бы (кроме сАмого низкоуровневого, самого последнего, библиотечного слоя, который очень мал и пишется 1 раз, и в котором злосчастная функция экранирования упоминается всего незколько раз, независимо от размера проекта). Только так можно защититься от инъекций (это касается, кстати, и xss тоже).

                                Иными словами, число вызовов функций фильтрации/экранирования должно быть константным и не зависеть от размера проекта (если вдруг имеет место пропорциональность или другая зависимость — это плохо).
                                  0
                                  *неСколько
                                    0
                                    Т.е. используйте фреймворки, где все это уже сделано :)
                                    +1
                                      –3
                                      Вообще конечно писать свои фильтрации и валидаторы стоит только ради того, чтобы потом использовать готовые уже решения и библиотеки и радоваться что за вас уже все продумали. Поэтому мой совет: НЕ ИСПОЛЬЗУЙТЕ НА ПРОДАКШЕНЕ СВОИ БИБЛИОТЕКИ
                                        +4
                                        Прочитал все ошибки…

                                        А не проще было написать:
                                        1. Юзайте PDO
                                        2. Юзайте filter_var / filter_input / etc.
                                        3. Не изобретайте велосипеды
                                          +1
                                          1. Юзайте PDO


                                          PDO никак не человека, писавшего
                                          $q = 'SELECT * FROM table where id='.$_GET['id'];
                                          


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

                                          filter_var

                                          О встроенный валидатор email в php я уже однажды обжегся. После этого везде использую валидатор yii(выдранный или вместе с фреймворком — в завсимости от ситуации).

                                          Автору поста.
                                          В файле index.php (или в любом другом главном файле) напишите такую строчку перед подключением других php файлов


                                          Это действительно совет? Если да, то поясните при каком подходе к разработке приложения проблемы с инклудами нужно решать именно таким образом, пожалуйста.
                                          +3
                                          Божечки, когда же люди перестанут пренебрегать новыми и правильными средствами языка, отмазываясь тем, что «хостеры не хотят обновлять версию PHP!»? Господа, 2012 год на дворе и можно купить VPS за 200-300 рублей, это если для себя. А если клиент такой прижимистый и для него есть разница между 150р в месяц и 200 — бегите от него!
                                            0
                                            Админить VPS кто будет? Клиент?
                                              0
                                              Ну, например, Clodo или сраный FirstVDS даёт ISPManager. То ли бесплатно, то ли за какие-то копейки. Есть куча всяких панелек, которые не хуже хостерских.
                                                0
                                                Вариант, конечно, но какой-то неполноценный, по-моему. Ставить LAMP через консоль или панельку разницы особо не вижу, и там, и там конфиги дефолтные будут. А на хостингах — хочется надеяться, — тюнят их, причём не «настроили и забыли», а анализируя текущуюобстановку.
                                                  0
                                                  Человеку, которому хватает шаред-хостинга по барабану на конфиги, не?
                                                    0
                                                    Ну, он рассчитывает, что они нормально настроены, особенно лимиты мускула по памяти и прочие буфера. Чтоб и память без дела не стояла и в своп не уходила (если он есть).
                                            –5
                                            WTF! я даже комментировать подробно не буду!
                                              +3
                                              Зачем при подключении файла из $_GET[...] делать switch? o_O. Почему бы не воспользоваться:
                                              if( in_array( $_GET[...], array( 'some', 'other' ), true ) )
                                              {
                                                  include ...;
                                              }

                                              мне кажется тут:
                                              if (!$_POST['secret_key'] OR $_POST['secret_key'] != $secret_key)

                                              Необходимо проверять строго $_POST['secret_key'] !== $secret_key.

                                              Далее, ваша статья рассчитана на новичков, но тем не менее вы используете в качестве ключей такие слова как chislo. Возможно, новичкам _такое_ будет понятнее, но не стоит подавать им столь дурной пример.

                                              По поводу «define ( 'READFILE', true );». Вчера начал изучать Kohana, и там используется такой же подход. С тех пор у меня в голове вертится 1 вопрос — не проще настроить .htaccess?
                                                0
                                                .htaccess, наверное, даже проще, но появляется гипотетическая вероятность его, например, потерять при переезде, или хостер может внезапно его зачем-то переписать — сталкивался с таким на шаред. А тут, вроде как, на уровне приложения контекст вызова проверяется.
                                                В IDE шаблоны прописываются, поэтому меня лично вообще не напрягает.
                                                  0
                                                  А в Kohana и используется .htaccess. Вот прямо выдержка из рекомендуемого:
                                                  RewriteRule ^(?:application|modules|system)\b.* index.php/$0 [L]
                                                    0
                                                    Угу, я видел default.htaccess. Получается, все эти проверки просто на всякий случай, вроде внезапного переезда на неадекватных хостинг, установки nginx без настройки конфига и пр.?
                                                      +1
                                                      Ещё чтобы инклуда не было от «левых» приложений.
                                                  +2
                                                  Как всегда, в комментариях больше информации, чем в самой статье.
                                                    0
                                                    Тут уже на многое указали, но я все же добавлю.
                                                    Получается мы создаем запись в базе, которая совершенно бесполезна нам.

                                                    Это называется «не обеспечена целостность данных». Используйте ограничения на уровне скуля, гуглить «innodb foreign».

                                                    Куки лучше подписывать соленым хешем, при их отправке браузеру. Т.е. если нужно записать в куки значение
                                                    Cookie::getinstance()->set('key', 'value');
                                                    

                                                    то в методе set к value, через разделитель, конкатенировать хеш этого значения, например md5('value'.md5(Cookie::$salt));, а сразу при обработке запроса проверять валидна ли подпись куки, и если нет — тереть такую куку, тогда для всего остального приложения ее просто не будет существовать.
                                                      +2
                                                      Получился какой-то сборник bad practice. Не нужно вводить в заблуждение новичков (аргументации уже более чем достаточно в комментариях к топику выше).
                                                        +2
                                                        foreach ($checkbox as $value)
                                                        {
                                                        	$value = intval($value);
                                                        	if ($value) $new_arr[] = $value;
                                                        }

                                                        В данном случае 0 пофильтруется, хотя является нормальным числовым значением.

                                                        $slovo = strip_tags($_GET['slovo']);
                                                        $slovo = htmlspecailchars($slovo);
                                                        $slovo = mysql_escape_string($slovo);
                                                        

                                                        Зачем здесь strip_tags? htmlspecailchars достаточен, а strip_tags, к примеру, вырежет имейл из такой безвредной строки:
                                                        «Vasya Pupkin» <vasya@pupkin.ru>
                                                        К тому же заменять спецсимволы на сущности лучше на выводе, а не при записи.
                                                          –3
                                                          В данном случае 0 пофильтруется, хотя является нормальным числовым значением.

                                                          Это лишь один из возможных вариантов проверки.
                                                          Ничего не мешает убрать её и поставить свою (на количество значений в массиве, на допустимость тех или иных значений).
                                                          Зачем здесь strip_tags?

                                                          Иногда мне не нужны html теги в переменной и лучше их сразу удалить, чем обходиться одним htmlspecailchars.
                                                          –5
                                                          Кое-что поменял в посте, что всех не много раздражало (я про is_array).
                                                          В остальном, я не вижу ошибок в посте, только советы как тем или иным программерам удобнее/привычнее составлять условия.

                                                          Но пока я не увидел главного — что данный пост не помогает защитить свой скрипт от взлома.
                                                            +4
                                                            Думаю сначала вам самому нужно разобраться в этой теме получше, а потом советовать что-то другим, особенно новичкам.
                                                              –3
                                                              И в чём же мне нужно разобраться?) Хотите сказать, что этот пост никому не поможет?
                                                              Вопросы риторические, понятно, что смысл вашего поста был просто что-то написать, а не дать дельный совет.
                                                                +3
                                                                > И в чём же мне нужно разобраться?) Хотите сказать, что этот пост никому не поможет?

                                                                Использование deprecated функций, дурной тон именования переменных… Продолжить? :)
                                                                  –1
                                                                  Ответ на данный вопрос был где-то выше. Читайте внимательнее )
                                                                  0
                                                                  Вот это:
                                                                  >$slovo = strip_data($_GET['slovo']);
                                                                  >$slovo = htmlspecialchars($slovo);
                                                                  >$slovo = mysql_escape_string($slovo);
                                                                  Отровенный пи*дец.

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

                                                                  И дело даже не в именовании переменных, называйте их как хотите.
                                                                    –1
                                                                    Во первых это мнимая безопасность, так как данные нужно обрабатывать от XSS перед выводом, а не перед вставкой.

                                                                    О каком выводе, о какой вставке говорите?
                                                                    Я показал пример фильтрации данных перед SQL запросом, нигде не написано, что это какой-то вывод.
                                                                    Во вторых вы тупо портите исходные данные.

                                                                    Я показал кусок из своего скрипта, где мне нужно было получить определенные данные, а не 1 в 1 как было передано через ПОСТ или ГЕТ…
                                                                    И дело даже не в именовании переменных, называйте их как хотите.

                                                                    Это ещё тут причём? Или надо было назвать «kojsub_get» ?)
                                                                      0
                                                                      По вашему названия переменных chislo и slovo нормальная практика? Т.е. вы считаете что за такое не надо бить руками и ногами? o_O. Или таки, не всё так плохо, и я просто не правильно вас понял?
                                                                        0
                                                                        Названия переменных я написал для примера, к чему эти придирки?)
                                                                          0
                                                                          Названия переменных я написал для примера, к чему эти придирки?)
                                                                          Очень дурной пример. Очень.
                                                                +2
                                                                if (intval($chislo))

                                                                Ну вы, ребята, даете… :)
                                                                  +1
                                                                  И как бы в продолжение:
                                                                  стринг-переменных
                                                                  –1
                                                                  PDO избавляет от тупых SQL-инъекций в 100% случаев.
                                                                    +1
                                                                    по-моему у Вас еще маловато опыта что бы давать совета другим
                                                                      +1
                                                                      $checkbox = $_POST['checkbox'];
                                                                      $new_arr = array(); // Массив для сохранения отфильтрованных значений
                                                                      if (is_array($checkbox)) // Проверяем, является ли переменная массивом
                                                                      {
                                                                      foreach ($checkbox as $value)
                                                                      {
                                                                      $value = intval($value);
                                                                      if ($value) $new_arr[] = $value; // не допускаем нули
                                                                      }
                                                                      }
                                                                      

                                                                      Можно заменить на
                                                                      $new_arr = array_filter(array_map('intval', $_POST['checkbox']));
                                                                      
                                                                        +2
                                                                        ТС, есть такая фраза, которая мне понравилась: «Прежде, чем что-либо писать — попробуйте сначала прочесть что-либо».
                                                                        А Вам нужно читать, читать, и еще раз читать.
                                                                        Пока что очень слабое понимание принципов эксплуатирования уязвимостей и очень низкое знание синтаксиса php. Получились антисоветы по большей части.
                                                                        Отложите эту статью и вернитесь к ней через год-два. А за это время подтяните знания, и по истечению этого срока Вы сами будете смеяться над этим «произведением».
                                                                          0
                                                                          Дочитал до первого примера:

                                                                          $number = intval($_GET['input_number']);
                                                                          if ($number)
                                                                          {
                                                                          ... выполняем SQL запрос ...
                                                                          }
                                                                          


                                                                          Понял, что раз автор не считает 0 годным числом, то дальше читать смысла нет. А также, тут не учтено, что GET-переменная input_number может быть не установлена.
                                                                            0
                                                                            Это лишь пример.
                                                                            Во многих моих скриптах отсутствует 0, а точнее обозначает ошибку.

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

                                                                          Самое читаемое