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

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

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

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