<rmcreative>

RSS

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));

Архив с кодом

Живой пример можно увидеть чуть ниже при вводе комментария.

Класс используется

xChip.ru

sitysoft.com

p.s. если кому интересен хелпер капчи для CodeIgniter или общая идея - пишите.

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

  1. №460
    Evgen
    Evgen 18 июля 2008 г., 17:46:33

    Думал над подобными решениями

    только цифры рисовал на CSS

    Цифра "7"

    <div style="border-top: 1px solid #000; border-right: 1px solid #000;"/>
     
    <div border-right: 1px solid #000;"/>
  2. №485
    Денис Радченко
    Денис Радченко 29 июля 2008 г., 0:59:46

    В закладки, однозначно. Где-нибудь применю, спасибо ;)

  3. №527
    DimoninG
    DimoninG 10 авг. 2008 г., 14:51:07

    Задумка интересная в плане реализации. А вот в плане взлома - одна фигня, имхо, что Ваша капча, что какая-то другая.

    Я недавно тоже написал капчу, но там можно просто одним кликом отделить человека от бота. По поводу ее взлома я подумаю в следующей версии. Интересно Ваше мнение, как профи ;)

  4. №513
    Sam
    Sam 11 авг. 2008 г., 12:41:54

    DimoninG

    По ссылке капча проще ломается брутфорсом: всего два варианта для скрытого поля перебрать…

  5. №535
    DimoninG
    DimoninG 12 авг. 2008 г., 22:42:50

    Насколько я могу судить, спам сейчас спамится не так. Выбираются блоги с однотипными капчами, которые спамбот может распознать (или вообще без капчи) и спам сыпится туда.

    У меня она "держит" нестандартностью. Против брута тоже есть варианты, но спамбот, который для каждого блога на ходу придумывает алкгоритм взлома - это уже искуственный интеллект. Так что этого пока бояться не надо.

  6. №537
    Sam
    Sam 13 авг. 2008 г., 12:55:38

    Брутфорсные боты были одними из первых. Сейчас универсальных конечно не много: нерентабельно, WordPress сделал своё дело…

  7. №539
    DeadLy
    DeadLy 13 авг. 2008 г., 12:59:12

    DimoninG, любую собственную капчу (читай самописную) никакой бот не взломает, если его спецально под неё не заточат... =)0

  8. №540
    DeadLy
    DeadLy 13 авг. 2008 г., 13:00:24

    Китайцев много, они всё распознают =)

  9. №541
    Sam
    Sam 13 авг. 2008 г., 13:00:56

    DeadLy

    Не, самые простые как раз брут-боты обходят.

  10. №1273
    CharnaD
    CharnaD 13 февр. 2009 г., 18:54:34

    Уха-ха-ха, я стал 1024-м подписчиком! Извините, что не в тему)

  11. №1440
    BOLK
    BOLK 02 апр. 2009 г., 23:49:12

    Figlet для этого интереснее — там шрифтов много хотя бы. А такая CAPTCHA как тут, распознаётся просто.

  12. №1664
    Jeka
    Jeka 24 июня 2009 г., 22:12:50

    Я вот несколько лет назад создал свою нестандартную каптчу.

    До этого была каптча с циферками, так биологические спамеры просто задрали спамить.

    Но видимо увидев чегото нестандартное, они стараются с этим не сталкиваться и уходят, а для обычных прользователей моя каптча даже более удобна, ненадо ничего вводить.

    Я понимаю что написать специальную распознавалку для нее будет не сложно, но на это придется потратиться время.

    Поэтому для не очень больших сайтов я очень приветствую создание какихто нестандартных решений, пусть даже не стойких к взлому, главное это затрудняет жизнь спамерам. На моем ресурсе спам после введения нестандартного решения, практически совсем перестал появляться.

    Посмотреть можно например здесь http://www.zatup.ru/blog/Destructor/5753 , в самом низу страницы.

  13. №1797
    Сергей
    Сергей 19 авг. 2009 г., 0:34:11

    подскажите как подробно установить ее для html? Сайт весь на html, форма обратной связи на php, кка мне установить вручную эту капчу?

  14. №1798
    Sam
    Sam 19 авг. 2009 г., 12:18:03

    В архиве исключительно генератор циферок. Код для проверки правильности ввода придётся написать самому.

  15. №2512
    Guest
    Guest 05 мая 2010 г., 14:55:55

    Отличный метод!Большое спасибо!

  16. №25
    SHAman
    SHAman 03 сент. 2010 г., 3:42:56

    Вообще круто:) Молодец. И большое спасибо за библиотечку. Теперь, если буду делать капчу, то такую.

  17. №27
    Igor
    Igor 03 сент. 2010 г., 3:42:58

    а можно заготовить элементов-картинок как те из которых состоят цифры в часах например их будет всего семь и генерировать от 2 до 7 вложенных дивов на 1 цифру, не уверен правда что это будет легче :)

  18. №28
    Igor
    Igor 03 сент. 2010 г., 3:42:58

    В догонку - элементов картинок достаточно 2 :)

  19. №29
    mdinc
    mdinc 03 сент. 2010 г., 3:42:59

    Это не капча а пародия на нее

  20. №30
    Steward
    Steward 03 сент. 2010 г., 3:42:59

    офигеть какая лажа :) - вы же за бота сделали 99% работы - создали матрицу пикселей.... эту капчу обойти 10 минут работы.. если с изображеними надо ещё возится.. распознавать.. повороты там всякие, деформации, шум - тут же всё готовое и на блюдечке....

    Офигеть :) - готовая матрица!!!!!!

  21. №31
    Виктор
    Виктор 03 сент. 2010 г., 3:42:59

    Кстати да, такие капчи боты легче всего обходят.

  22. №32
    Виктор
    Виктор 03 сент. 2010 г., 3:43:00

    Ой, извиняюсь, затупил...

  23. №33
    Sam
    Sam 03 сент. 2010 г., 3:43:00

    Steward

    На написание распознавалки надо потратить время. Причём распознавалка будет неуниверсальная: достаточно переименовать тэг или чуть изменить разметку - и опять можно жить спокойно.

    Про матрицу комментария не понял. Она на стороне сервера и на клиенте никаким боком не видна, да и меняется за пару минут до неузнаваемости.

    mdinc

    Почему же? Да, обойти её легко, но только написав конкретно под неё распознавалку.

  24. №35
    Алексей
    Алексей 03 сент. 2010 г., 3:43:01

    Вот у коллег увидел разбор капчи: http://www.simplecoding.org/dobavlyaem-captcha-k-forme.html

    На мой взгляд более подходящая чем предлагаемая...

  25. №36
    DeadLy
    DeadLy 03 сент. 2010 г., 3:43:01

    А мне понравилось, может она и легко распознаётся, но зато без всяких там картинок. супер!

  26. №3587
    Александр
    Александр 21 дек. 2010 г., 23:22:05

    Нашел как интегрировать капчу w3captha используя при этом form validation, раньше ее использовал, до CI. omelniz.wordpress.com

  27. №10052
    Мастер
    Мастер 12 нояб. 2015 г., 20:07:06

    А как сменить шрифт (нужен в стиле сайта) в каптче?

  28. №10056
    Sam
    Sam 17 нояб. 2015 г., 3:05:06

    Никак. Это не шрифт.

  29. №11308
    Baby
    Baby 30 авг. 2018 г., 12:03:04

    Ищу что то простое без мудреных искаженных картинок с которых и самому иногда сложно понять что на них выведено. Ваша идея понравилась своей простотой и гибкостью. Специально под мой не большой сайт никто не станет заморачиваться с обходом такой капчи, та и действительно в случае чего легко поправить код html на другой. А для посетителя это всего одна-две цифры ввести, красота. Но у меня возник вопрос, какой механизм передачи скрипту проверяющему введенность капчи, какой вопрос был задан посетителю? У Вас в форме только одно скрытое поле ХЭШ, но оно не меняется при клике "Щёлкните, чтобы получить другую задачу." Более того, в установленной куке также подобное поле хэш не изменяется. Как Вы тогда учитываете какой кому арифметический вопрос был задан?

  30. №11309
    Baby
    Baby 30 авг. 2018 г., 12:04:39

    Ищу что то простое без мудреных искаженных картинок с которых и самому иногда сложно понять что на них выведено. Ваша идея понравилась своей простотой и гибкостью. Специально под мой не большой сайт никто не станет заморачиваться с обходом такой капчи, та и действительно в случае чего легко поправить код html на другой. А для посетителя это всего одна-две цифры ввести, красота. Но у меня возник вопрос, какой механизм передачи скрипту проверяющему введенность капчи, какой вопрос был задан посетителю? У Вас в форме только одно скрытое поле ХЭШ, но оно не меняется при клике "Щёлкните, чтобы получить другую задачу." Более того, в установленной куке также подобное поле хэш не изменяется. Как Вы тогда учитываете какой кому арифметический вопрос был задан?

  31. №12254
    WWW
    WWW 05 янв. 2022 г., 16:59:59

    А где код валидации?

  1. Почта опубликована не будет.

  2. Можно использовать синтаксис Markdown или HTML.

  3. Введите ответ в поле. Щёлкните, чтобы получить другую задачу.