Капча не помогает защите популярных движков: чем больше сайтов на одном движке, тем быстрее защиту взломают (это вопрос времени). Гораздо эффективнее защита от спама с помощью генерации элементов HTML-формы Javascript функциями.

DHTML: защита форума

Как защитить фор(ум|му) от спама?

Форма – это дыра, через которую сообщения пользователя отправляются на сервер. Точнее, несколько дыр: текст сообщения, автор, e-mail...

Форма 1.
Автор: Адрес: Текст сообщения:

Но это только так кажется: ввёл в окошко текст – и он отправился в путешествие. Между этими событиями происходит нечто важное: браузер забирает из окон формы все тексты и составляет из них единое сообщение, в одну строчку. Строчка этого комплексного сообщения может выглядеть так:

addmessage.php?author=Dasha&text=vsem%20privet!

Человек (хотя это большой вопрос, является ли спамер человеком в хорошем смысле этого слова) ищет по всему Интернету такие дыры – формы добавления текстов в базу данных. Потом смотрит на HTML-код формы. Ничто не мешает ему составить правильную строчку сообщения в готовом виде, не заполняя поля формы. Потом он запускает свою гнусную программку-робота и вводит в неё строчку готового сообщения в виде параметра; и робот начинает бесконечно пихать спам на форум. Не обязательно именно в сообщения, он может, например, регистрировать новых пользователей и заполнять их профили своей рекламой.

Хозяин форума замечает это дело, и начинается бесконечная борьба брони и снаряда: проверка адреса страницы, с которой отправлена форма; капча (контрольные цифры на картинке или «сосчитайте 1+1»)... В этой борьбе снаряд всегда побеждает, его удар можно лишь отсрочить на какое-то время.

Если это время увеличить достаточно сильно, спамер уйдёт навсегда. Потому что время спамера – это в очень большой степени его деньги; его заработок ведь зависит от количества рассылаемых сообщений в единицу времени. Здесь важно учитывать именно время спамера, а не его роботов. Времени роботов никому не жалко, к тому же можно одновременно запустить очень много их копий.

Рассмотрим пример с «1+1». Человеческое время тут занимает секунды – один раз взглянуть на страницу и увидеть, что там предлагают заняться сложением. После этого спамер просто нажимает нужную галочку в программе-роботе: «перед отправкой спама открыть страницу с формой, найти там текст /(\d+)\s*\+\s*(\d+)/, сосчитать $1+$2 и занести полученный результат в поле <input name='captcha_response'>». Или даже галочку нажимать не надо, если робот продвинутый (сам проверят такие мелочи). Или можно отметить все такие опции заранее и совсем не заглядывать на страницы с формами. Или, если вариантов «решения примера» не очень много (только двузначные числа), можно даже не утруждать робота вычислениями регулярных выражений, а заставить его тупо перебирать варианты – ну, будет попадать на сервер один текст из ста запросов, ну, запустим ещё 100 роботов...

Пример с чтением цифр с картинки, как ни странно, ещё менее человекоёмкий – ведь картинку заметить легче (а потом всё равно всё делает программа распознавания – более или менее сложная).

Наибольшие неприятности роботу может доставить DHTML – динамическое изменение HTML страницы после её получения клиентом. Если клиент – робот, ему придётся скачивать javascript, связанный со страницей. Ту часть javascript, которая изменяет после открытия HTML форму. Тут тоже задача может быть более или менее сложной.

Во-первых, сам код. Если просто написать внутри HTML формы (или даже во внешнем скрипте, вложенном в форму с помощью атрибута src элемента script): document.write("1 + 2 ="); – результат (по сложности для робота) мало будет отличаться от простого текста HTML страницы. Нужно написать уж хотя бы что-то вроде:

- чтобы роботу пришлось интерпретировать javascript. Вот это уже на порядок сложнее и дороже. Можно ещё навставлять в код нефатальных ошибок (например, не ставить в конце строк точку с запятой).

Во-вторых, код надо спрятать – поместить ссылку на файл js не внутри формы, а где-нибудь в конце страницы. Код тогда, конечно, усложнится – надо будет не только отобразить цифры, но и добавить к форме элемент, в котором будут нарисованы эти цифры:

Теперь внутри HTML-кода формы нет контрольных цифр, их рисует javascript, расположенный в конце страницы. Пользователь видит эти цифры и может их сосчитать. А робот "видит" только HTML, и никаких "1+1". Форма будет выглядеть примерно так:

Форма 2.
Введите вычисленный результат: Автор: Адрес: Текст сообщения:

Разумеется, в этом случае у робота всегда остаётся ultima ratio – тупой и неторопливый перебор значений, которые нужно ввести в поле <input name="captcha" size="6">. Поэтому третья ступень защиты состоит в том, чтобы подрисовывать к форме после открытия не только контрольные цифры, но и сам элемент input, в который нужно вводить цифры. Тогда и робот, и спамер при просмотре кода скачанной страницы вообще не будут видеть элементов защиты, пользователю же на экране они будут видны:

Форма 3.
Автор: ...

Javascript код (который следует помещать на странице ниже формы), разумеется, удлинится, но в нём не будет ничего принципиально нового (просто увеличится количество элементов, динамически добавляемых на страницу):

После такого подлого удара большинство роботов надолго (в наше динамичное время это всё равно что навсегда) впадёт в ступор. Но это ещё не всё. Предложенная схема стопроцентно убьёт робота, если роботу до этого уже удалось хоть раз успешно добавить вам свой спам. После добавления динамического элемента защиты (которого раньше не было на странице), робот будет продолжать считать, что всё идёт как надо (нафиг надо кому-то проверять результаты).

Но если на странице изначально, при первом посещении робота, стоит такая динамическая защита, шансов пробить её у робота будет больше. Ведь робот (или спамер) наверняка после первой отправки сообщения будут проверять, что ответил сервер. А он ответит, как для всех пользователей: «Вы неправильно ввели контрольные цифры». И робот начнёт метаться по HTML странице и искать, кто же там рисует эти цифры. Хотя важнее даже не «кто рисует», а как называется поле, в которое эти цифры надо ввести (хотя бы тупым перебором значений). Для этого не нужно даже нормально интерпретировать javascript, достаточно всё тех же регулярных выражений: где-то ведь в скрипте мы всё равно вынуждены будем написать что-то вроде «Элемент.name=ИМЯ_ЭЛЕМЕНТА_ФОРМЫ» или «Элемент.setAttribute('name', ИМЯ_ЭЛЕМЕНТА_ФОРМЫ)». Ну, а если ИМЯ_ЭЛЕМЕНТА_ФОРМЫ == captcha, то роботу даже и метаться не надо, он в первую очередь будет пробовать использовать это имя.

Таким образом, в-четвёртых, в защиту надо включить такую простую вещь, как случайный подбор наименований (name) для элементов формы. Не надо называть их так, как ожидает робот (особенно элементы защиты). Впрочем, при динамическом добавлении элементов в форму, специальные элементы защиты теряют смысл (ведь как раз их-то, видимых или невидимых, в первую очередь и будет искать робот).

Правильнее выдумать и сделать динамически добавляемым какой-нибудь не очень нужный элемент (например, Город или Страна пользователя) и поставить около него звёздочку, типа он «обязательный». Однако ответ с ошибкой «Не заполнено поле Город» с сервера не возвращать, а предупреждать пользователя о нарушениях в заполнении формы всё тем же javascript'ом, перед отправкой формы на сервер. Тогда робот вообще не будет знать о каком-то элементе, значение которого проверяется на сервере, и будет молотить впустую, получая стандартные ответы: «Спасибо за ваше сообщение! Заходите ещё!». Можно даже заносить такие сообщения роботов (с незаполненным «контрольным» полем) в отдельную таблицу и потом анализировать IP и прочие их особенности.

Пятая ступень защиты – высшая степень коварства, проявляемого нами в отношении роботов. Её можно условно обозначить как «двойное дно». Внешне всё как всегда, форма выглядит «как у всех», и в ней есть стандартный, примитивнейший элемент <input name="captcha" id="captcha">. После открытия страницы в браузере, однако, имя контрольного элемента меняется на совершенно произвольное – с помощью javascript, который генерируется на сервере:

Сервер знает, какое имя он передал через javascript, и будет проверять значение параметра именно с этим именем. А если пришёл параметр с именем captcha, значит сообщение точно писал робот. Ответ будет всегда стандартный – «неправильно набран номер», и робот будет думать, что он где-то ошибся в вычислении регулярных выражений, и будет пытаться подбирать нужное число «вслепую», наугад. Бесконечно будет пытаться, потому что решение находится в другой плоскости.

При массовом применении «пятой ступени защиты», роботов, скорее всего, научат парсить javascript. Ну, тогда мы ещё что-нибудь придумаем. Если, конечно, к тому времени это ещё будет иметь какой-то смысл, и Интернет не загадится окончательно штатным «уникализированным контентом» (от самих веб-мастеров), после чего форумный спам будет вспоминаться как невинная детская забава.

© 2010, «Деловая неделя», Михаил Гутентог

Комментарии

lifephysic 04.02.2011 10:41:27

Развлекаетесь тут смотрю

лесник 31.01.2011 20:22:32

google.bot, не верю!! врёшь, ты не робот!! Гукл не мог так низко пасть...

google.bot 31.01.2011 06:21:09

ads по низким ценам!!!!!! скидки!!!!!!! леучшее продвижение САЙТОВ в СЕТИ!!!!!! http://www.google.ru/ads/