Хроники лаборатории
Так ли нужен CAPTCHA?

Статья была написана для HostInfo.ru.

Часто ли вам приходится сталкиваться с работой CAPTCHA-систем? Это такие системы скриптов, задающие загадки и генерирующие трудночитаемые картинки с цифрами, буквами и прочим безобразием, и сверяющие потом то, что вы ввели, с эталоном. В частности, таким образом сайты обороняются от автоматизированной рассылки рекламы по форумам и гостевым, отделяя добропорядочных пользователей от спам-программ. Считается, что автоматический тест Тьюринга крайне осложняет жизнь спам-программам, поэтому CAPTCHA сейчас используется довольно широко, заставляя вглядываться в напрочь зашумленные надписи, гадая, что на этот раз имеется в виду - единичка или латинская строчная «эл».

Но на всякий хитрый «картинкогенератор» рано или поздно находится своя управа, и правильный ответ найдется: либо перебором, либо разбором механизма генерации картинок, либо еще через какое-нибудь «заднее крыльцо». И преграда для автоспамеров становится лишь раздражением для посетителя ресурса. Ухватываете суть проблемы? В погоне за спамоустойчивостью удобство пользователя как-то само собой отошло на второй план. Лично мне не особо по душе лозунг «это для вашей же безопасности», поэтому сегодня я поделюсь с вами устройством более дружелюбного для пользователя механизма.

Для начала давайте немного поразмышляем: в чем отличие программы от настоящего, живого человека?

Проследим поведение обычного пользователя. Человек открывает страницу с формой для добавления какой-либо записи(в гостевой, на форуме и так далее), видит поля (для простоты возьмем самые распространенные) «Имя», «E-mail», «Сообщение». Он вводит в эти поля информацию и нажимает кнопку «Отправить». И все, сообщение появляется там, где пользователь и планировал его добавление(в гостевой, на форуме и так далее).

Что делает спам-программа? Она загружает страницу, определяет, какие механизмы защиты использованы, и делает свое черное дело. Главное отличие программы от человека в том, что она воспринимает страницы как последовательность букв, слов, строк - среди слов она по заранее заданному алгоритму может найти ссылку на заветное «добавить комментарий», пройти по ней и вписать пару фраз рекламы и ссылки в соответствующие поля, так же аккуратно найти на странице кнопку отсылки сообщения и эмулировать ее нажатие. Причем многие программы автоматически находят пригодные для «гнездования» сайты и добавляют их в свою базу - для повторной «кладки».

Итак, поскольку мы задались целью не проверять пользователя на распознавание цветов, цифр и навыки извлечения логарифмов, становится очевидно, что наша основная борьба развернется внутри кода страницы - который пользователю по большому счету глубоко безразличен, а для программы является основным материалом для работы.

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

Ограничение по частоте сообщений.
Самый простой инструмент. Необходимо следить, чтобы с одного и того же IP не было по десятку сообщений в минуту - ясно, что вряд ли человек с такой частотой будет высказывать какие-то умные мысли. Этот прием, конечно, толком не избавляет от спама, но сокращает его поток. Главное тут - правильно подобрать интервал: и большой плохо, и короткий нехорошо. По собственному опыту минуты три - в самый раз.

Блокирование сообщений по ключевым словам.
Тоже довольно простой фильтр: не пропускаются до публикации сообщения, имеющие среди текста слова, которых точно не будет содержать «добропорядочный» текст. Заодно можно отфильтровывать не только рекламу, но и мат.

Замена символов «двойниками».
Случайная замена на странице букв на схожие по написанию символы (для человека все равно, а для разбора и поиска по шаблону - помеха). При этом в ссылках, ведущих на добавление комментариев или на регистрацию, буквы меняются на схожие по написанию, но имеющие другой код. Например, русские «а», «о», «р» на английские «a», «o» и «p» соответственно. Это немного усложняет поиск потенциальных сайтов-жертв.

Изменение имен полей ввода.
Многие программы ищут в странице поля ввода со стандартными именами: «name», «user», «nick», «email», «mail» и так далее. Чтобы доставить программе некоторое неудобство, лучше называть поля как-нибудь нестандартно. Например, «kndfjero».

Замена надписей картинками с текстом.
Если реализован предыдущий шаг, то есть шанс, что программа не сдастся, не найдя привычных имен полей, а попытается проанализировать находящиеся рядом надписи, пытаясь выяснить, к чему какое поле относится. Смена поясняющих надписей на картинки с текстом сильно усложняет эту задачу в плане решения на программном уровне, а уж пиктограммы и вовсе делают ее практически невыполнимой. Визуально, с точки зрения пользователя, на странице ничего не меняется: какая ему разница, как набран текст на сайте, картинкой или текстом? С другой стороны, достаточно спамеру-человеку один раз посетить такую страницу и «врукопашную» посмотреть что где - и все, программе уже задан шаблон для этой страницы, она «знает», куда что писать и куда нажимать для отправки.

Встраивание «полей-приманок».
Раз программа ищет поля «name», «message» и тому подобные, почему бы не «обрадовать» ее этими полями? Это сделать довольно просто, например так:
Имя:
<input type=text name=name style="visibility: hidden; width: 1px;" value="">
<input type=text name=nlconpiqo value="">

E-mail:
<input type=text name=email style="visibility: hidden; width: 1px;" value="">
<input type=text name=ummsklcqu value="">
При отображении такие поля не видны, а программа их находит и обрабатывает. От особенно «умных« программ «visibility: hidden» прячется в CSS:
<style type="text/css">
input.foul {
visibility: hidden;
width: 1px;
height: 1px;
}
</style>

...

Имя:
<input type=text name=name class=foul value="">
<input type=text name=nlconpiqo value="">

E-mail:
<input type=text name=email class=foul value="">
<input type=text name=ummsklcqu value="">

Построение формы с помощью JavaScript.
Этот метод делает анализ формы еще более сложным: программе необходимо найти и выполнить код JavaScript, чтобы получить форму, которую следует заполнить:
<div id=mform> Включите, пожалуйста, поддержку JavaScript в браузере </div>

...

<script language=javascript>
myform=document.getElementById("mform");
mystr="<form method=\"post\" name=\"som";
mystr=mystr+"eform\" action=\"somescript.php\">И";
mystr=mystr+"мя: <input type=text name=ni";
mystr=mystr+"ck value=\"\"><br>E-ma";
mystr=mystr+"il: <input type=text name=ema";
mystr=mystr+"il value=\"\"><br>Сообщение: <texta";
mystr=mystr+"rea cols=35 rows=8 name=ms";
mystr=mystr+"g></textarea><br><input type=bu";
mystr=mystr+"tton value=\"отправить\" onclick=\"somef";
mystr=mystr+"orm.submit()\"><br></form>";
myform.innerHTML=mystr;
</script>
Наличие механизмов обучения и делает автоспамеров особенно «въедливыми»: один раз программе показали, как надо действовать при данной ситуации, она запомнила, и все - разгребай, хозяин, спам на форуме. Значит, надо сделать так, чтобы страница каждый раз была разной, верно?

Отлично, тогда переходим к следующим, более изощренным методам.

Генерирование случайных имен полей ввода.
Это просто усовершенствованный метод изменения имен полей ввода: имена изменяются не один раз (при написании скрипта), а при каждом вызове страницы. Тут есть одна тонкость: поскольку имена раздаются динамически, надо как-то известить получающий данные скрипт, какая переменная за что отвечает. Например, ввести дополнительное скрытое поле, в которое записать шифровку, в которой указать, какие поля обрабатываются:
<form method="post" name="jdfjvb" action="somescript.php">
Имя: <input type=text name=nlconpiqo value="">
E-mail: <input type=text name=ummsklcqu value="">
Сообщение: <textarea cols=35 rows=8 name=thtqnrnee></textarea>
<input type=button value="отправить" onclick="jdfjvb.submit()">
<input type=hidden name=temp value="piqonlconbnhrshelcquummskrneethtqn">
</form>
В somescript.php происходит «разбор» переменной-шифровки temp с именами и выуживание из переданных данных нужной информации:
$war = decrypt_string($temp);
$name = trim($_POST[$war[0]]);
$email = trim($_POST[$war[1]]);
$message = trim($_POST[$war[2]]);
Функция decrypt_string отвечает за расшифровку переданных данных и не ограничена ничем, кроме вашей фантазии. Алгоритм шифрования можно в любой момент изменить, например, если спамер просто использует единожды загруженную страницу для отправки повторных сообщений.

Генерирование принимающего скрипта.
Усложняем предыдущий случай: кроме случайных имен будем создавать на диске и принимающий скрипт:
<form method="post" name="jdfjvb" action="shebnhr.php">
Имя: <input type=text name=nlconpiqo value="">
E-mail: <input type=text name=ummsklcqu value="">
Сообщение: <textarea cols=35 rows=8 name=thtqnrnee></textarea>
<input type=button value="отправить" onclick="jdfjvb.submit()">
<input type=hidden name=temp value="piqonlconbnhrshelcquummskrneethtqn">
</form>
На диске, соответственно, создается shebnhr.php - на этот раз введенные данные отправятся на обработку этому файлу. Таким образом, можно иногда менять поля «Имя», «E-mail» и «Сообщение» местами, (что нанесет ущерб удобству пользователя не в пример меньше, чем корявые буквы на рисунке, но окончательно собьет с толку программу), менять механизм шифрования «на лету» - ведь принимающая часть генерируется специально под данные имена полей, под данную форму. Переданная запись сохраняется в гостевой, а после принимающий скрипт стирает сам себя. Соответственно, использовать для отправки данных вторично невозможно чисто физически: файла, к которому обращались в первый раз, давно нет. Конечно, не знаю, насколько оправдано применение решения для сайта в 3000 уникальных посетителей и 600-700 сообщений в день, ибо получается нагрузка на жесткий диск из-за создания и стирания файлов.

Обработка по билетам.
Вместо формирования индивидуального принимающего скрипта для каждой попытки добавления комментария можно использовать своеобразные кодовые билеты: в форме среди прочих полей указывается скрытое поле с уникальным билетом, кодовой строкой, которая также внесена в базу билетов. После добавления комментария билет удаляется из базы, и повторная отправка данных не пройдет - билет уже отработал, его нет в базе.

Увы, против спамеров, вбивающих обявления вручную, противоядий вовсе нет (кроме, разве что, фильтрования сообщений по содержимому). С другой стороны, целью этой статьи не было выведение универсального оружия против спама. Целью было показать, что тест Тьюринга - не панацея, а иногда - только причина раздражения. И что в большинстве случаев можно запросто обойтись без него, не заставляя пользователя делать лишние операции. Достаточно только хотя бы немного изменить, придать индивидуальности файлам - из-за одного-единственного сайта переделывать ориентированную на типовые решения и распространенные CMS спам-программу никто не будет.


Опубликовано на HostInfo.ru.


RSS HTML рубрики: приемчикиjuick twitter facebook вконтакте

Случайные записи впридачу:
Снова... (стихи)
Посвящение (стихи)
Некрополис (рассказы)

Откуда вы?   

Войти через loginza
Оставлять комментарии могут только
имеющие свой ЖЖ-, ЛИру-аккаунт или
еще какой openID (как так?).
Подписаться


Рубрики:

жизненное
аудио-я
видеомонтаж
фотоохота
ремонт
стихи
рассказы
синематограф
библиотека
фонотека
точка зрения
FAQ
приемчики
придумалось
ожидания-прогнозы
допридумано
рингтоны
это я так шучу
обои
микрозарисовки
опасный Интернет
я в печати
поездки-тусовки
смехоспам
мой код
футболки
игродром
подводная жизнь
сайтоводство
программы
персоны
LI.ru
аватарки
курсоры


Разное:

Полка с фильмами
Книжная полка
Полка с играми
Избранное


Календарь записей

2021 (1)
2020 (7)
2019 (3)
2018 (1)
2017 (10)
2016 (12)
2015 (3)
2014 (12)
2013 (10)
2012 (17)
2011 (84)
2010 (172)
2009 (228)
2008 (263)
2007 (154)
2006 (4)
2005 (1)
2004 (1)
2002 (1)
2001 (9)
2000 (9)
1999 (1)
© сайт разработан и поддерживается мной.