HTML-капча
7 марта 2008
Давно я не писал о защите от спама. Прошлая моя задумка хоть и является до сих пор достаточно эффективной, но особо активные боты её всё-таки обходят. Где-то в начале прошлого месяца у меня появилась идея нестандартной капчи: ASCII-капча, но в процессе реализации она как-то очень плавно перетекла в HTML-капчу.
О ботах и человеке
Задача капчи - как можно более усложнить автоматизированное замусоривание через открытые части сайта: комментарии, гостевые книги и т.д. в то же время для человека пройти тест в идеале очень легко.
Современные боты стали довольно навороченными: во-первых у них есть жёстко забитые алгоритмы для обхода защит популярных движков блогов и форумов, во-вторых, есть некий эвристичексий алгоритм. В том числе некоторые боты сгружают все картинки и пытаются распознать и ввести всё, что на них написано.
Также были замечена печальная тенденция, когда народ работает вбивая спам в блоги и на форумы. Досадно, но от этого капча не поможет.
Идея
Итак, идея. Рисуем картинку с циферками HTML+CSS кодом. Человеку будет всё-равно как оно там внутри устроено, а вот боту придётся либо скриншотить весь сайт (что накладно при распознавании). Есть ещё возможность того, что автор бота потратит своё время и напишет специализированный алгоритм распознавания кода именно для такой капчи. Об этом я тоже позаботился: выходной HTML довольно легко изменить.
Реализация
Для рисования циферок был создан массив матриц пикселей. Фактически шрифт. Записывается он в довольно наглядном виде прямо в коде.
Потом на основании этого шрифта строятся таблицы, где некоторые ячейки имеют отдельный класс, обозначающий, что ячейка закрашена.
Код генератора циферок
class AsciiGen { //Шрифт. Может быть дополнен по аналогии. private $map = array( 0 => array( array(1, 1, 1), array(1, 0, 1), array(1, 0, 1), array(1, 0, 1), array(1, 1, 1), ), 1 => array( array(0, 0, 1), array(0, 1, 1), array(1, 0, 1), array(0, 0, 1), array(0, 0, 1), ), 2 => array( array(1, 1, 1), array(0, 0, 1), array(1, 1, 1), array(1, 0, 0), array(1, 1, 1), ), 3 => array( array(1, 1, 1), array(0, 0, 1), array(1, 1, 1), array(0, 0, 1), array(1, 1, 1), ), 4 => array( array(1, 0, 1), array(1, 0, 1), array(1, 1, 1), array(0, 0, 1), array(0, 0, 1), ), 5 => array( array(1, 1, 1), array(1, 0, 0), array(1, 1, 1), array(0, 0, 1), array(1, 1, 1), ), 6 => array( array(1, 1, 1), array(1, 0, 0), array(1, 1, 1), array(1, 0, 1), array(1, 1, 1), ), 7 => array( array(1, 1, 1), array(0, 0, 1), array(0, 1, 0), array(1, 0, 0), array(1, 0, 0), ), 8 => array( array(1, 1, 1), array(1, 0, 1), array(1, 1, 1), array(1, 0, 1), array(1, 1, 1), ), 9 => array( array(1, 1, 1), array(1, 0, 1), array(1, 1, 1), array(0, 0, 1), array(1, 1, 1), ), '.' => array( array(0, 0, 0), array(0, 0, 0), array(0, 0, 0), array(0, 0, 0), array(0, 1, 0), ), ); //css находится в файле asciigen.css в той же папке, что и asciigen.php (этот код). private function getStyle(){ return '<style type="text/css">'.file_get_contents(dirname(__FILE__).'/asciigen.css').'</style>'; } //Генерирует html-код для одного символа. private function generate($symbol){ if(!isset($this->map[$symbol])) return false; $map = $this->map[$symbol]; $buf = '<table class="chr">'; foreach ($map as $row){ $buf.='<tr>'; foreach ($row as $is_filled){ if($is_filled){ $buf.='<td class="fld"/>'; } else{ $buf.='<td/>'; } } $buf.='</tr>'; } $buf.='</table>'; return $buf; } //Основной метод. Генерирует html из строки символов или числа. function generateLine($symbols){ $symbols = (string)$symbols; $buf=$this->getStyle(); $len = strlen($symbols); for($i=0; $i<$len; $i++){ $buf.=$this->generate($symbols{$i}); } $buf.='<br style="clear: left"/>'; return $buf; } }
asciigen.css
.fld { background: #000; } .chr { border-collapse: collapse; float: left; margin: 2px; } .chr td { width: 2px; height: 4px; /*border: 1px solid #efefef;*/ }
Пример использования
$ag = new AsciiGen(); $ag->generateLine(rand(11, 99));
Живой пример можно увидеть чуть ниже при вводе комментария.
Класс используется
p.s. если кому интересен хелпер капчи для CodeIgniter или общая идея - пишите.
Комментарии RSS по email OK
Думал над подобными решениями
только цифры рисовал на CSS
Цифра "7"
В закладки, однозначно. Где-нибудь применю, спасибо ;)
Задумка интересная в плане реализации. А вот в плане взлома - одна фигня, имхо, что Ваша капча, что какая-то другая.
Я недавно тоже написал капчу, но там можно просто одним кликом отделить человека от бота. По поводу ее взлома я подумаю в следующей версии. Интересно Ваше мнение, как профи ;)
DimoninG
По ссылке капча проще ломается брутфорсом: всего два варианта для скрытого поля перебрать…
Насколько я могу судить, спам сейчас спамится не так. Выбираются блоги с однотипными капчами, которые спамбот может распознать (или вообще без капчи) и спам сыпится туда.
У меня она "держит" нестандартностью. Против брута тоже есть варианты, но спамбот, который для каждого блога на ходу придумывает алкгоритм взлома - это уже искуственный интеллект. Так что этого пока бояться не надо.
Брутфорсные боты были одними из первых. Сейчас универсальных конечно не много: нерентабельно, WordPress сделал своё дело…
DimoninG, любую собственную капчу (читай самописную) никакой бот не взломает, если его спецально под неё не заточат... =)0
Китайцев много, они всё распознают =)
DeadLy
Не, самые простые как раз брут-боты обходят.
Уха-ха-ха, я стал 1024-м подписчиком! Извините, что не в тему)
Figlet для этого интереснее — там шрифтов много хотя бы. А такая CAPTCHA как тут, распознаётся просто.
Я вот несколько лет назад создал свою нестандартную каптчу.
До этого была каптча с циферками, так биологические спамеры просто задрали спамить.
Но видимо увидев чегото нестандартное, они стараются с этим не сталкиваться и уходят, а для обычных прользователей моя каптча даже более удобна, ненадо ничего вводить.
Я понимаю что написать специальную распознавалку для нее будет не сложно, но на это придется потратиться время.
Поэтому для не очень больших сайтов я очень приветствую создание какихто нестандартных решений, пусть даже не стойких к взлому, главное это затрудняет жизнь спамерам. На моем ресурсе спам после введения нестандартного решения, практически совсем перестал появляться.
Посмотреть можно например здесь http://www.zatup.ru/blog/Destructor/5753 , в самом низу страницы.
подскажите как подробно установить ее для html? Сайт весь на html, форма обратной связи на php, кка мне установить вручную эту капчу?
В архиве исключительно генератор циферок. Код для проверки правильности ввода придётся написать самому.
Отличный метод!Большое спасибо!
Вообще круто:) Молодец. И большое спасибо за библиотечку. Теперь, если буду делать капчу, то такую.
а можно заготовить элементов-картинок как те из которых состоят цифры в часах например их будет всего семь и генерировать от 2 до 7 вложенных дивов на 1 цифру, не уверен правда что это будет легче :)
В догонку - элементов картинок достаточно 2 :)
Это не капча а пародия на нее
офигеть какая лажа :) - вы же за бота сделали 99% работы - создали матрицу пикселей.... эту капчу обойти 10 минут работы.. если с изображеними надо ещё возится.. распознавать.. повороты там всякие, деформации, шум - тут же всё готовое и на блюдечке....
Офигеть :) - готовая матрица!!!!!!
Кстати да, такие капчи боты легче всего обходят.
Ой, извиняюсь, затупил...
Steward
На написание распознавалки надо потратить время. Причём распознавалка будет неуниверсальная: достаточно переименовать тэг или чуть изменить разметку - и опять можно жить спокойно.
Про матрицу комментария не понял. Она на стороне сервера и на клиенте никаким боком не видна, да и меняется за пару минут до неузнаваемости.
mdinc
Почему же? Да, обойти её легко, но только написав конкретно под неё распознавалку.
Вот у коллег увидел разбор капчи: http://www.simplecoding.org/dobavlyaem-captcha-k-forme.html
На мой взгляд более подходящая чем предлагаемая...
А мне понравилось, может она и легко распознаётся, но зато без всяких там картинок. супер!
Нашел как интегрировать капчу w3captha используя при этом form validation, раньше ее использовал, до CI. omelniz.wordpress.com
А как сменить шрифт (нужен в стиле сайта) в каптче?
Никак. Это не шрифт.
Ищу что то простое без мудреных искаженных картинок с которых и самому иногда сложно понять что на них выведено. Ваша идея понравилась своей простотой и гибкостью. Специально под мой не большой сайт никто не станет заморачиваться с обходом такой капчи, та и действительно в случае чего легко поправить код html на другой. А для посетителя это всего одна-две цифры ввести, красота. Но у меня возник вопрос, какой механизм передачи скрипту проверяющему введенность капчи, какой вопрос был задан посетителю? У Вас в форме только одно скрытое поле ХЭШ, но оно не меняется при клике "Щёлкните, чтобы получить другую задачу." Более того, в установленной куке также подобное поле хэш не изменяется. Как Вы тогда учитываете какой кому арифметический вопрос был задан?
Ищу что то простое без мудреных искаженных картинок с которых и самому иногда сложно понять что на них выведено. Ваша идея понравилась своей простотой и гибкостью. Специально под мой не большой сайт никто не станет заморачиваться с обходом такой капчи, та и действительно в случае чего легко поправить код html на другой. А для посетителя это всего одна-две цифры ввести, красота. Но у меня возник вопрос, какой механизм передачи скрипту проверяющему введенность капчи, какой вопрос был задан посетителю? У Вас в форме только одно скрытое поле ХЭШ, но оно не меняется при клике "Щёлкните, чтобы получить другую задачу." Более того, в установленной куке также подобное поле хэш не изменяется. Как Вы тогда учитываете какой кому арифметический вопрос был задан?
А где код валидации?