Доброе время суток всем гуру и новичкам PHP. Сама по себе тема далеко не уникальная и наверняка уже не один раз была на страницах этого сайта, но я решил немного обобщить знания, полученные за годы изучения и выложить их здесь. Тем самым хочу убить 2 зайцев: помочь новичкам с ЧЗВ по этой теме и послушать критику профи. Сам сабж на мой взгляд – утопия, но защитить html-форму на достойном уровне – хороший пример программирования. Идея написать сей топик, родилась сегодня, когда я чуть под стол не упал и от смеха и от наглости фрилансеров. Через какие-то дальние ICQ контакты на меня вышел парень, который заплатил 10$ за скрипт отправки e-mail через html-форму. Когда я увидел это чудо я долго не верил своим глазам: весь скрипт представлял собой нечто следующее: Код (Text): if (!$mail) {mail(…);} else {include(“form.htm”);} как говорится // no comments Итак, всю защиту html-формы можно разделить на 4 глобальных задачи: 1) Защита полей формы от механического изменения, JS-включений, SQL-инъекций и прочей дряни. 2) Защита от spamer=off, flooder=off и их robot=off 3) Устойчивый код ко всем переменным получаемых из формы (за примером далеко бежать не надо: раздел HUMOR есть ссылочка на замечательный магазин ) 4) При всей вышесказанной защите код должен быть быстрым, а форма сохранить свою юзабилити. Теперь по каждому пункту подробнее: 0) Предположим, что у нас 3 файла: форма, обработчик и файл-сборочка, который в зависимости от условия выводит либо форму либо оброботчик. Код (Text): // если кнопульку не жали или в форме есть ошибки if ($_POST['Submit'] != "Добавить" || isset($form_err)) {include ("form.php");} // файл-форма else {include ("check.php");} // файл-обработчик ПУНКТ№1 1) Узнаем откуда пришла форма (с нашего сервера или с другой машины): Код (Text): $page = $PHP_SELF; // кусок пути к нашему файлу-обработчику if (strpos("$page","site/addform.php") == false) { include ("antihack.php"); exit; } 2) Во всех полях формы должен быть атрибут maxchar, причем его желательно сделать как можно меньше, но не забыв про п.4. (ИМХО я ещё не встречал браузеры, которые игнорируют этот параметр) Если введенная информация длинее поля, то значит это хак: Код (Text): if ( strlen($_POST['mail']) > 32 || strlen($_POST['tel']) > 32 || strlen($_POST['info']) > 64 ) { include ("antihack.php"); exit; } 3) Теперь можно найти обычные ошибки формы (которые приведут к возврату формы + ошибки) Код (Text): // регуляркой проверяем формат E-mail (с)перта из учебника 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'])) {$form_err = "".$form_err."E-mail не введен или имеет неправильный формат";} // поля типа textfield проверяем на макс. допустимое кол-во символов: if (strlen($_POST['msgtext']) > 1024) {$form_err = "".$form_err."Текст объявления слишком длинный";} 4) Формируем переменные для дальнейшей работы с ними: Код (Text): $sqladd_info = htmlspecialchars(trim(strip_tags(stripslashes($_POST['info'])))); $sqladd_msgtext = htmlspecialchars(trim(strip_tags(stripslashes($_POST['msgtext'])))); // чтоб нормально распознавался переход на новую строку // для этого есть какая-то встроенная функция но я ее не помню $sqladd_msgtext = str_replace("\n","<br>",$sqladd_msgtext); 5) и наконец работа с загрузкой файлов: здесь представлен цикл добавления 4 изображений со следующими ограничениями: файл формата jpeg или gif, не менее 320х240пкс., соотношение сторон не более, чем 1 к 2 или 1 к 0,5 и размер файла не больше max_upload_size. Код (Text): for ($f=1; $f<=4; $f++) { // загружено ли вообще if (is_uploaded_file($_FILES["file".$f.""]['tmp_name'])) { // формат загруженного файла if (strpos($HTTP_POST_FILES["file".$f.""]["type"],"jpeg") !== false || strpos($HTTP_POST_FILES["file".$f.""]["type"],"gif") !== false) { $picsize = getimagesize($_FILES["file".$f.""]['tmp_name']); if($picsize[0] > 319 && $picsize[1] > 239) { // проверка соотношения сторон if (($picsize[0]/ $picsize[1])< 2) { copy($_FILES["file".$f.""]['tmp_name'], "pics/".$dir."/".$_FILES["file".$f.""]["name"].""); } } } } } !!! Ни в коем случае не делайте никаких манипуляций с картинками во время оброботки формы (уменьшение, добавление водяного знака и пр.) так как это ОЧЕНЬ нагрузит сервер и в случае 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): $addform[4] = " <tr> <td colspan=\"2\" class=\"menu_text\" align=\"left\">Цена: <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> <select name=\"cur\" class=\"input\"> <option value=\"1\">РУБ.</option> <option value=\"2\">USD</option> <option value=\"3\">EURO</option> </select> <input name=\"torg\" type=\"checkbox\" value=\"1\"> торг </td> </tr> "; if ($_POST['cur'] != "") {$addform[4] = str_replace("value=\"".$_POST['cur']."\"","value=\"".$_POST['cur']."\" selected",$addform[4]);} if ($_POST['torg'] =="1") {$addform[4] = str_replace("value=\"".$_POST['torg']."\"","value=\"".$_POST['torg']."\" checked",$addform[4]);} ========= Это пожалуй не все, что я хотел с Вами обсудить, но я думаю по мере вопросов, обсуждений и споров, я вспомню то, что не написал. Всем спасибо за внимание (с) ZeiZ lab. 2007
Статью оцениваю на 7 из 10. Явные недостатки: Информация несколько свалена в кучу, некоторые вещи заявлены без обьяснений. SQL-иньекции НЕ должны обрабатыватся в форме!! Это задача обертки для БД. HTML-теги тоже не всегда должны конвертироватся. Автору советую ознакомится с библиотекой HTML_MetaForm.
Спасибо за 7-ку, но большее за ссылочку.... буду изучать. Согласен..... На время поста посмотрите (по Москве).... :roll: Так, что если надо могу разъяснить и попонятнее написать. позже... Надеюсь оно лишнем не будет. На самом деле я хотел чисто теоретическую тему замутить, а получилось даже с примерами небольшими. А пока буду разбираться в METAForm, можно обсудить ЭТАП№2. Может кто-то знает ещё какие способы защиты от spam и flood, кроме вышеописанных captcha, IP/USER_Agent - timeblock.
Gl00mY ZeiZ, влет приходят на ум только HoneyPots, это поля, скрытые через CSS от пользователя(т.е. он не может ввести в них значение, так как не знает, что они есть) — это НЕ hidden поля(!), их просто не видно. Но имеющие внятный name, например <input type="text" style="display:none" name="email" value="" /> — робот заполнит это поле и поймается на этом =). Неплохо защищает от унивесальных рег.ботов. Естественно, заточенные под конкретный сайт, будут нечувствительны к этому. =) Так же неплохи небольшие JS-скрипты, которые например, спрашивают, «Добавить комментарий?» И по нажатию «Да» — субмитят данные на адрес, ОТЛИЧНЫЙ от поля action у формы. Прочие, опять таки падают на модерацию.(Вдруг JS отключен?) Еще можно проверку header-ов делать — не все боты посылают такие вещи, как Accept-language и т.п. Я обычно еще пробегаю по тексту регулярками на предмет частоты встречи http:// — если много, то коммент падает на модерацию. Вариантов достаточно много, и многое зависит от конкретного случая.
PS. Тему перенес и переименовал, закрепил, ибо обсуждение интересное. Если не сложно, автору советую разделить написанное хотя бы на следующие части: Введение, постановка проблемы, возможные решения, примеры кода, вопросы для обсуждения.
Если аффтор переработает статью, авансом 6 из 10 . Инициатива - хорошо, про китайцев тоже хорошо много написал - тоже вроде хорошо. Плохо: много слитно непонятно, мысли у автора обрываются и не все раскрываются, проверка на тип вводимых данных при помощи JS - это не защита, а декорации, не упомянут метод о подмене имен полей формы. PHP: <?php if ( strlen($_POST['mail']) > 32 || strlen($_POST['tel']) > 32 || strlen($_POST['info']) > 64 ) { include ("antihack.php"); exit; } такими вещами будут заморачиваться скорее безумцы или те кому очень надо . ИМХО большая часть сводится к решениям направленным на усложнение жизни не спамеру/взломщику, а программисту. Аффтар проанализируй все хорошенько. Напиши лучше меньше но по делу - про инъекции про "межсайтовый скриптинг", про то что капча+динамическое изменение имен полей - это хорошо . vb
маловато. знаю людей у которых имя-фамилия в качестве мыла... можно сократить раза в три. к тому же лучше юзать preg, ибо сильно быстрей...
Очередной бред сивой кобылы Нужно знать что есть язык HTML | SQL и простой TXT и есть данные из формы (magic_quotes) Дыры не от недостатка фильтрации а от тупых програмеров которые пихают данные из формы в HTML и SQL