За последние 24 часа нас посетили 22649 программистов и 1281 робот. Сейчас ищут 959 программистов ...

Теория: Фильтрация пользовательского ввода

Тема в разделе "Решения, алгоритмы", создана пользователем Gl00mY ZeiZ, 6 мар 2007.

  1. Gl00mY ZeiZ

    Gl00mY ZeiZ Активный пользователь

    С нами с:
    6 мар 2007
    Сообщения:
    6
    Симпатии:
    0
    Адрес:
    Москва
    Доброе время суток всем гуру и новичкам PHP.
    Сама по себе тема далеко не уникальная и наверняка уже не один раз была на страницах этого сайта, но я решил немного обобщить знания, полученные за годы изучения и выложить их здесь. Тем самым хочу убить 2 зайцев: помочь новичкам с ЧЗВ по этой теме и послушать критику профи.
    Сам сабж на мой взгляд – утопия, но защитить html-форму на достойном уровне – хороший пример программирования.
    Идея написать сей топик, родилась сегодня, когда я чуть под стол не упал и от смеха и от наглости фрилансеров. Через какие-то дальние ICQ контакты на меня вышел парень, который заплатил 10$ за скрипт отправки e-mail через html-форму. Когда я увидел это чудо я долго не верил своим глазам: весь скрипт представлял собой нечто следующее:
    Код (Text):
    1.  
    2. if (!$mail)
    3. {mail(…);}
    4. else
    5. {include(“form.htm”);}
    как говорится // no comments

    Итак, всю защиту html-формы можно разделить на 4 глобальных задачи:
    1) Защита полей формы от механического изменения, JS-включений, SQL-инъекций и прочей дряни.
    2) Защита от spamer=off, flooder=off и их robot=off :)
    3) Устойчивый код ко всем переменным получаемых из формы (за примером далеко бежать не надо: раздел HUMOR есть ссылочка на замечательный магазин :) )
    4) При всей вышесказанной защите код должен быть быстрым, а форма сохранить свою юзабилити.
    Теперь по каждому пункту подробнее:
    0) Предположим, что у нас 3 файла: форма, обработчик и файл-сборочка, который в зависимости от условия выводит либо форму либо оброботчик.
    Код (Text):
    1.  
    2. // если кнопульку не жали или в форме есть ошибки
    3. if ($_POST['Submit'] != "Добавить" || isset($form_err))
    4. {include ("form.php");} // файл-форма
    5. else
    6. {include ("check.php");} // файл-обработчик
    ПУНКТ№1
    1) Узнаем откуда пришла форма (с нашего сервера или с другой машины):
    Код (Text):
    1.  
    2. $page = $PHP_SELF;
    3. // кусок пути к нашему файлу-обработчику
    4. if (strpos("$page","site/addform.php") == false) {
    5. include ("antihack.php");
    6. exit;
    7. }
    2) Во всех полях формы должен быть атрибут maxchar, причем его желательно сделать как можно меньше, но не забыв про п.4. (ИМХО я ещё не встречал браузеры, которые игнорируют этот параметр) Если введенная информация длинее поля, то значит это хак:
    Код (Text):
    1.  
    2. if (
    3. strlen($_POST['mail']) > 32 ||
    4. strlen($_POST['tel']) > 32 ||
    5. strlen($_POST['info']) > 64
    6. )
    7.     {
    8.     include ("antihack.php");
    9.     exit;
    10.     }
    3) Теперь можно найти обычные ошибки формы (которые приведут к возврату формы + ошибки)
    Код (Text):
    1.  
    2. // регуляркой проверяем формат E-mail (с)перта из учебника
    3. if (!eregi("^([a-zA-Z0-9_\-\.]+)@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.)|(([a-zA-Z0-9\-]+\.)+))([a-zA-Z]{2,4}|[0-9]{1,3})(\]?)$",$_POST['mail']))
    4.     {$form_err = "".$form_err."E-mail не введен или имеет неправильный формат";}
    5. // поля типа textfield проверяем на макс. допустимое кол-во символов:
    6. if (strlen($_POST['msgtext']) > 1024)
    7.     {$form_err = "".$form_err."Текст объявления слишком длинный";}
    4) Формируем переменные для дальнейшей работы с ними:
    Код (Text):
    1.  
    2. $sqladd_info = htmlspecialchars(trim(strip_tags(stripslashes($_POST['info']))));
    3. $sqladd_msgtext = htmlspecialchars(trim(strip_tags(stripslashes($_POST['msgtext']))));
    4. // чтоб нормально распознавался переход на новую строку
    5. // для этого есть какая-то встроенная функция но я ее не помню
    6. $sqladd_msgtext = str_replace("\n","<br>",$sqladd_msgtext);
    5) и наконец работа с загрузкой файлов:
    здесь представлен цикл добавления 4 изображений со следующими ограничениями:
    файл формата jpeg или gif, не менее 320х240пкс., соотношение сторон не более, чем 1 к 2 или 1 к 0,5 и размер файла не больше max_upload_size.
    Код (Text):
    1.  
    2. for ($f=1; $f<=4; $f++)
    3. {
    4. // загружено ли вообще
    5.     if (is_uploaded_file($_FILES["file".$f.""]['tmp_name']))
    6.         {
    7. // формат загруженного файла
    8.         if (strpos($HTTP_POST_FILES["file".$f.""]["type"],"jpeg") !== false ||
    9.         strpos($HTTP_POST_FILES["file".$f.""]["type"],"gif") !== false)
    10.             {
    11.             $picsize = getimagesize($_FILES["file".$f.""]['tmp_name']);
    12.             if($picsize[0] > 319 && $picsize[1] > 239)
    13.             {
    14. // проверка соотношения сторон
    15.             if (($picsize[0]/ $picsize[1])< 2)
    16.                 {
    17. copy($_FILES["file".$f.""]['tmp_name'], "pics/".$dir."/".$_FILES["file".$f.""]["name"]."");
    18.                 }
    19.             }
    20.             }
    21.         }
    22. }
    !!! Ни в коем случае не делайте никаких манипуляций с картинками во время оброботки формы (уменьшение, добавление водяного знака и пр.) так как это ОЧЕНЬ нагрузит сервер и в случае flood’a, может получится банальный DOS !!!
    ПУНКТ№2
    На мой взгляд самый интересный момент. Защита от тех самых.
    Многие считают, что установив в форму CAPTCHA – картинку, которую может прочитать человек, но не может распознать компьютер, решает все проблемы. Но не надо забывать про 4 примера из реальной жизни:
    1) хакерами, спамерами, флудерами (нужное подчеркнуть) уже как минимум 3 командами разработаны универсальные(!) программы для ORC (оптическое распознавание текста) captcha. Эффективность 80-90%(!)
    2) множество сайтов (rapidshare.com) имеют captcha с трудночитаемыми для пользователей символами, а это противоречит нашему 4п.
    3) недавний взлом securitylab.ru как раз из-за глупого использования captcha
    4) взлом mail.yahoo.com с помоom. бесплатного порносайта, где для перехода к следующей картинке пользователю необходимо ввести captcha стянутую с регистрационной формы mail.yahoo.com таким образом одна картинка – 1 аккаунт.
    Но captcha это не обязательно картинка с кривыми буквами и цифрами.
    К captcha относится, например, скрывание полей с помошью css, но при такой технологии можно забыть про автозаполнение, а это п.4.
    Звуковые отрезки содержащие некое слово и сложно реализовать и не дружелюбно к пользователям.
    Ещё одна технология captcha – вам показывают 4 картинки чего-то, и надо вписать что на них изображено. Но для этого надо подгружать 4картинки – трафик - п.4., иметь большую базу этих картинок и из-за нашего богатого языка ещё базу ответов-синонимов.
    Ну и последняя технология – это большое изображение содержащее в себе несколько «плавующих» слов, и вам предлагается вписать любые 3 из них.
    Но это опять п.4. т.к. здоровая картинка и трата времени на заполнение 3 полей не несущих никакой информационной нагрузки для конечного пользователя.
    И на последок скажу, что многие крупные компании промышляющие spam’ом начали платить китайцам «по баксу в час», за такие регистрации.
    Поэтому какую защиту ставить Вам, решайте сами, но это должен быть некий компромисс между п.2 и п.4.
    Могу лишь подсказать
    1) www.captcha.ru (по их заверению, да и по моему опыту самый устойчивый, самый читаемый, простой в установке и бесплатный)
    2) не давать возможности совершать 2 регистрации с одного IP/USER_AGENT подряд (в теч $time секунд)
    3) чаще проверять все глазиками и ручками, создать быстрый способ забанить хулигана.
    ПУНКТ№3
    Здесь ещё раз следует проверить негативные последствия при вводе «левой» инфы.
    Подскажу лишь html атрибуты, которые часто забывают при верстки самой формы.
    Для того, чтобы пользователь мог вводить в поле только цифры от 0 до 9 можно к атрибутам поля добавить:
    onkeypress="if(event.keyCode<48 || event.keyCode>57)return false"
    для загрузки файлов (поле file), не забудеи про атрибут accept:
    например: accept=”image/*”
    Это все повысит юзабилити, но вряд ли сильно обезопасит Вашу форму от злоумышленника, так, что экспериментируйте со значентями полей и смотрите, как будет вести себя код.
    Для этого даже желательно привлечь знакомых, пусть поиздеваются над формой это лучше, чем, когда Вас будет иметь непонятно кто, а Вы будете прыгать, дергаться и не знать где оказалась дырочка.
    ПУНКТ№4
    Про этот пункт уже много говорилось выше, но пожалуй самое главное я оставил на сладкое. Как сделать так, чтобы при возврате вашей формы обратно, в случае обнаружения ошибок, поля заполненные по всем правилам оставались такими же заполненными, и пользователю пришлось бы всего лишь исправить «ошибочные поля» с точки зрения нашего обработчика? Часто, особенно, когда форма очень большая, пользователи плюют на нее и уходят, так как заполнять ее по новой в случае всего одного-двух «ошибочных полей», очень не приятно. А что тут такого сложного? поставить в полях text атрибут $_POST[‘var’], а в textfield – тоже но между тегами. Но, что делать с остальными полями?
    В качестве примера приведу кусок формы содержащий поля типа: text, select, checkbox
    Код (Text):
    1.  
    2. $addform[4] = "
    3. <tr>
    4. <td colspan=\"2\" class=\"menu_text\" align=\"left\">Цена:
    5. <input name=\"price\" type=\"text\" class=\"input\" size=\"16\" maxlength=\"16\" value=\"".$_POST['price']."\" onkeypress=\"if(event.keyCode<48 || event.keyCode>57)return false\"> <span class=\"star\">*  </span>
    6. <select name=\"cur\" class=\"input\">
    7. <option value=\"1\">РУБ.</option>
    8. <option value=\"2\">USD</option>
    9. <option value=\"3\">EURO</option>
    10. </select>
    11. <input name=\"torg\" type=\"checkbox\" value=\"1\"> торг
    12. </td>
    13. </tr>
    14. ";
    15. if ($_POST['cur'] != "")
    16. {$addform[4] = str_replace("value=\"".$_POST['cur']."\"","value=\"".$_POST['cur']."\" selected",$addform[4]);}
    17. if ($_POST['torg'] =="1")
    18. {$addform[4] = str_replace("value=\"".$_POST['torg']."\"","value=\"".$_POST['torg']."\" checked",$addform[4]);}
    =========
    Это пожалуй не все, что я хотел с Вами обсудить, но я думаю по мере вопросов, обсуждений и споров, я вспомню то, что не написал.

    Всем спасибо за внимание
    (с) ZeiZ lab. 2007
     
  2. Anonymous

    Anonymous Guest

    Статью оцениваю на 7 из 10.
    Явные недостатки: Информация несколько свалена в кучу, некоторые вещи заявлены без обьяснений.
    SQL-иньекции НЕ должны обрабатыватся в форме!! Это задача обертки для БД. HTML-теги тоже не всегда должны конвертироватся.
    Автору советую ознакомится с библиотекой HTML_MetaForm.
     
  3. Gl00mY ZeiZ

    Gl00mY ZeiZ Активный пользователь

    С нами с:
    6 мар 2007
    Сообщения:
    6
    Симпатии:
    0
    Адрес:
    Москва
    Спасибо за 7-ку, но большее за ссылочку....
    буду изучать.
    Согласен..... На время поста посмотрите (по Москве).... :roll:
    Так, что если надо могу разъяснить и попонятнее написать. позже... Надеюсь оно лишнем не будет.
    На самом деле я хотел чисто теоретическую тему замутить, а получилось даже с примерами небольшими. :)
    А пока буду разбираться в METAForm,
    можно обсудить ЭТАП№2.
    Может кто-то знает ещё какие способы защиты от spam и flood, кроме вышеописанных captcha, IP/USER_Agent - timeblock.
     
  4. Anonymous

    Anonymous Guest

    Gl00mY ZeiZ, влет приходят на ум только HoneyPots, это поля, скрытые через CSS от пользователя(т.е. он не может ввести в них значение, так как не знает, что они есть) — это НЕ hidden поля(!), их просто не видно. Но имеющие внятный name, например <input type="text" style="display:none" name="email" value="" /> — робот заполнит это поле и поймается на этом =). Неплохо защищает от унивесальных рег.ботов. Естественно, заточенные под конкретный сайт, будут нечувствительны к этому. =)
    Так же неплохи небольшие JS-скрипты, которые например, спрашивают, «Добавить комментарий?» И по нажатию «Да» — субмитят данные на адрес, ОТЛИЧНЫЙ от поля action у формы. Прочие, опять таки падают на модерацию.(Вдруг JS отключен?)
    Еще можно проверку header-ов делать — не все боты посылают такие вещи, как Accept-language и т.п. Я обычно еще пробегаю по тексту регулярками на предмет частоты встречи http:// — если много, то коммент падает на модерацию.
    Вариантов достаточно много, и многое зависит от конкретного случая.
     
  5. Anonymous

    Anonymous Guest

    PS. Тему перенес и переименовал, закрепил, ибо обсуждение интересное.
    Если не сложно, автору советую разделить написанное хотя бы на следующие части: Введение, постановка проблемы, возможные решения, примеры кода, вопросы для обсуждения.
     
  6. Gl00mY ZeiZ

    Gl00mY ZeiZ Активный пользователь

    С нами с:
    6 мар 2007
    Сообщения:
    6
    Симпатии:
    0
    Адрес:
    Москва
    я писал уже....

    Обязательно как только будет часок-другой свободный
     
  7. vb

    vb Активный пользователь

    С нами с:
    6 июн 2006
    Сообщения:
    911
    Симпатии:
    0
    Адрес:
    Saint-Petersburg
    Если аффтор переработает статью, авансом 6 из 10 :).

    Инициатива - хорошо, про китайцев тоже хорошо :) много написал - тоже вроде хорошо.

    Плохо:
    много слитно непонятно, мысли у автора обрываются и не все раскрываются, проверка на тип вводимых данных при помощи JS - это не защита, а декорации, не упомянут метод о подмене имен полей формы.
    PHP:
    1. <?php
    2. if (
    3. strlen($_POST['mail']) > 32 ||
    4. strlen($_POST['tel']) > 32 ||
    5. strlen($_POST['info']) > 64
    6. )
    7.    {
    8.    include ("antihack.php");
    9.    exit;
    10.    }
    11.  
    такими вещами будут заморачиваться скорее безумцы или те кому очень надо :).

    ИМХО большая часть сводится к решениям направленным на усложнение жизни не спамеру/взломщику, а программисту.
    Аффтар проанализируй все хорошенько. Напиши лучше меньше но по делу - про инъекции про "межсайтовый скриптинг", про то что капча+динамическое изменение имен полей - это хорошо :).

    vb
     
  8. dark-demon

    dark-demon Активный пользователь

    С нами с:
    16 фев 2007
    Сообщения:
    1.920
    Симпатии:
    1
    Адрес:
    леноград
    маловато. знаю людей у которых имя-фамилия в качестве мыла...

    можно сократить раза в три. к тому же лучше юзать preg, ибо сильно быстрей...
     
  9. Anonymous

    Anonymous Guest

    =) Я например =)))
    «Критикуя, предлагайте.» © ;)
     
  10. 440Hz

    440Hz Старожил
    Команда форума Модератор

    С нами с:
    21 дек 2012
    Сообщения:
    8.003
    Симпатии:
    1
    Адрес:
    Оттуда
  11. Anonymous

    Anonymous Guest

    440Hz, WTF ??? %)
     
  12. Gl00mY ZeiZ

    Gl00mY ZeiZ Активный пользователь

    С нами с:
    6 мар 2007
    Сообщения:
    6
    Симпатии:
    0
    Адрес:
    Москва
    5+

    написано - (с)перто из учебника
    предложите короче.

    тоже пять
     
  13. 440Hz

    440Hz Старожил
    Команда форума Модератор

    С нами с:
    21 дек 2012
    Сообщения:
    8.003
    Симпатии:
    1
    Адрес:
    Оттуда
    ты о чем?
     
  14. DarkElf

    DarkElf Активный пользователь

    С нами с:
    22 окт 2006
    Сообщения:
    1.632
    Симпатии:
    0
    440Hz

    на сленге Lineage2 - предложение обмена:)
     
  15. 440Hz

    440Hz Старожил
    Команда форума Модератор

    С нами с:
    21 дек 2012
    Сообщения:
    8.003
    Симпатии:
    1
    Адрес:
    Оттуда
    DarkElf

    чем меняться-то? я и так все что есть раздаю.
     
  16. DarkElf

    DarkElf Активный пользователь

    С нами с:
    22 окт 2006
    Сообщения:
    1.632
    Симпатии:
    0
    ИМХО, не ко мне вопрос:)
     
  17. dark-demon

    dark-demon Активный пользователь

    С нами с:
    16 фев 2007
    Сообщения:
    1.920
    Симпатии:
    1
    Адрес:
    леноград
    http://php.ru/forum/viewtopic.php?t=4364&highlight=
     
  18. Vladson

    Vladson Старожил

    С нами с:
    4 фев 2006
    Сообщения:
    4.040
    Симпатии:
    26
    Адрес:
    Estonia, Tallinn
    Очередной бред сивой кобылы
    Нужно знать что есть язык HTML | SQL и простой TXT и есть данные из формы (magic_quotes)

    Дыры не от недостатка фильтрации а от тупых програмеров которые пихают данные из формы в HTML и SQL
     
  19. Luge

    Luge Старожил

    С нами с:
    2 фев 2007
    Сообщения:
    4.680
    Симпатии:
    1
    Адрес:
    Минск
    а у dar'a инересней сообщения :D
     
  20. pr0

    pr0 Активный пользователь

    С нами с:
    29 янв 2007
    Сообщения:
    6
    Симпатии:
    0
    А что если обработчик и форма в одном файле? Как тогда распознать откуда пришли данные?