20.04.2009 Обновлена: 28.06.2010 #3

Борьба со спамом на сайте: различные подходы.

Последние несколько месяцев мне пришлось серьезно взяться за решение проблемы спама на ряде дружественных мне сайтов.
Здесь я хотел бы поделиться результатами своей работы.

Применяемые методики.

  1. Генерация формы на стороне клиента с помощью JavaScript.
  2. Использование капчи (captcha).
  3. Генерация скрытого поля на стороне клиента с помощью JavaScript.
  4. Проверка на наличие основного поля формы.
  5. Ограничение количества ссылок в сообщении.
  6. Использование пустого поля, скрытого CSS.

Нетерпеливые могут сразу посмотреть на эффективность различных анти-спам фильтров.

1. Генерация формы на стороне клиента с помощью JavaScript.

Впервые я применил этот подход на сайте «Свободна» 3 года назад.
За всё это время на сайте не появилось ни одного спам-сообщения, оставленного роботами. Только троллями. Но тролли — это другая история.

В основе этого метода лежит предположение, что спам-боты: 1) не умеют исполнять JavaScript, 2) даже если и умеют, то не работают со сгенерированным html-кодом.

Механизм работы такой. У вас есть JavaScript функция, которая умеет рисовать форму. Она может вызываться автоматически, например, после загрузки страницы или как реакция на определенные действия пользователя, например, после клика на ссылку «Оставить комментарий».

Простой пример генерации формы:
	//Функция, которая добавляет форму в конец страницы
	function appendForm(){
		var form = '
'+ 'Ваше имя:
'+ '
'+ 'Ваше сообщение:
'+ '
'+ ''+ '
'; document.body.innerHTML+=form; } //Запустить функцию после загрузки документа window.onload = appendForm;

Минусы:

2. Использование капчи (captcha).

Капча представляет собой дополнительное поле в форме, в которое пользователь должен ввести покореженные символы с картинки рядом.

Основывается на предположении, что роботы: 1) не умеют читать с картинок, 2) даже если умеют, то плохо видят и не понимают плохо прорисованные символы.

Капч существует куча разновидностей с разной функциональностью. Последнее время стала довольно популярна reCaptcha.

reCaptcha example

Она работает как с включенным, так и отключенным JavaScript'ом, позволяет менять картинку, может озвучить написанное на картинке, а также помогает оцифровывать книги, за счет вводимых пользователями символов.

Минусы:

3. Генерация скрытого поля на стороне клиента с помощью JavaScript.

Я придумал этот способ (который не есть супер оригинальным), чтобы не использовать капчу и другие подходы. Его просто реализовать и он не отвлекает внимания пользователя при отправке формы.

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

А затем на стороне сервера проверяется было ли это поле среди отправленных, и если нет, то считается, что форма была отправлена роботом.

Пример кода на стороне клиента (JavaScript):
	//Функция, которая добавляет поле _antispam во все формы на странице
	function appendAntiSpamField(){
		var forms = document.getElementsByTagName("form");
		for(var i = 0,l = forms.length;i < l;i++){
			var inp = document.createElement('input');
			inp.setAttribute("type","hidden");
			inp.setAttribute("name","_antispam");
			var d = new Date();
			//Случайное значение
			inp.value = "antispam_"+d.getMilliseconds();
			forms[i].appendChild(inp);
		}
	}

	//Запустить функцию после загрузки документа
	window.onload = appendAntiSpamField;
Пример кода на стороне сервера (PHP):
	if(isset($_POST['_antispam'])){
		//..продолжить обработку формы
		
	}else{
		//..обработка ошибки
		echo "Сработал анти-спам фильтр."
		echo "Включите JavaScript, для того чтобы отправить форму.";
		exit;
	}

Минусы:

4. Проверка на наличие основного поля формы.

Бывает такое, что спаммеры пытаются отсылать информацию не используя формы на ваших страницах, а напрямую вашему серверу.

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

Поэтому есть смысл проверять наличие какого-нибудь важного поля вашей формы среди принимаемой информации.

Пример кода на стороне сервера (PHP):
	if(isset($_POST['text_body'])){
		//..продолжить обработку формы
		
	}else{
		//..обработка ошибки
		echo "Спаммеры! Не балуйтесь!";
		exit;
	}

! Также никогда не забывайте проверять и чистить ВСЮ принимаемую информацию !

5. Ограничение количества ссылок в сообщении.

Это более сложный подход, основывающийся на анализе получаемых данных.

99.9% спаммерских сообщений включают в себя ссылки и адресса сайтов. Часто они пытаются впихнуть в одно сообщение несколько ссылок сразу. Также многие спам-боты знают о существовании различных систем обработки информации на сайтах и могут составлять свои сообщения в виде обычного текста, html, BB-кода и др.

Но в этом и их минус — их можно отсеивать по количеству ссылок в сообщении.

Это может быть сделано, например, так:

Пример простого кода на стороне сервера (PHP):
	//Функция, которая проверяет строку на наличие в ней ссылок
	//и возвращает false, если их число больше лимита.
	//По умолчанию, лимит равен 1
	function fits_limit_links($str, $allowed_links=1){
	
		//Искать http://
		$pattern = '/http:///i'; 
		preg_match_all($pattern, $str, $link_matches);
		
		//Если встречаются совпадения и их больше, чем $allowed_links,
		//то вернуть false, иначе вернуть true
		return ( isset($link_matches[0]) &&
				count($link_matches[0]) > $allowed_links )? false : true;
	}
	
	$allowed_links = 2;
	
	if( fits_limit_links($_POST['text_body'], $allowed_links) ){
		//..продолжить обработку формы
		
	}else{
		//..обработка ошибки
		echo "Сработал анти-спам фильтр."
		echo "Сообщение может содержать не более чем " .$allowed_links ." ссылок";
		exit;
	}

Минусы:

6. Использование пустого поля, скрытого CSS.

Это способ был подсмотрен здесь. Он тоже расчитан на тупость роботов. Его плюсом есть простота использования и то, что он не требует JavaScript.

Заключается он в том, что к вашей форме добавляется пустое поле с каким-нибудь обычным названием, типа lastname, и скрывается от пользователя посредством CSS. Затем на сервере проверяется имеело ли это поле значение, и если да — то считается, что к форму отправил робот.

Поскольку роботы не обрабатывают CSS и обычно пытаются пхать свой спам во все поля формы, то их можно обмануть описаным выше способом.

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

HTML:
	
Если Вы не робот, оставьте это поле пустым:
CSS:
	.lastname {
		visibility: hidden;
		overflow:hidden;
		height:1px;
	}

Проверка на стороне сервера (PHP):
	if( isset($_POST['lastname']) && !strlen($_POST['lastname']) ){
		//..продолжить обработку формы
		
	}else{		
		//..обработка ошибки
		echo "Сработал анти-спам фильтр."
		echo "Если Вы не робот, то оставьте поле lastname пустым";
		exit;
	}

Эффективность анти-спам фильтров.

Эффективность анти-спам фильтров

Метод Эффективность
1. Генерация формы на стороне клиента с помощью JavaScript. 100%
2. Использование капчи (captcha). 96.8%
3. Генерация скрытого поля на стороне клиента с помощью JavaScript. 95%
4. Использование пустого поля, скрытого CSS. 80.4%
5. Ограничение количества ссылок в сообщении. 73.9%
6. Проверка на наличие основного поля формы. 0.8%

Откуда я взял эти цифры

  1. Подход «Генерация формы на стороне клиента с помощью JavaScript» был тестирован мной на нескольких сайтах, например, «Свободна», «Svenska Verb» и других.
    За несколько лет работы ни на одном из этих сайтов спамерами не было опубликовано ни одно сообщение. Поэтому мне он доказал свою 100% эффективность.
  2. Для получения остальных результатов, я провел анализ серверных логов с одного сайта, на который я не хочу здесь ссылаться, на котором были применены оставшиеся пять анти-спам методик.

Исследование:

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

Для исследования я взял лог за период с 2009.03.13 по 2009.04.18 (37 дней), содержащий записи о более чем 16 тысячах спам-атак. Каждая запись лога содержала информацию о том, какой из анти-спам фильтров сработал в этом конкретном случае. Это позволяет составить более-менее объективную картину эффективности подходов блокирования спама, а также дает представление о работе самих спам-ботов.

Надо признаться, что какая-то часть спама все-таки просачивается через все мной поставленые фильтры, как показали результаты — публикуется всего 0.2%. Это победа. Но все же я не знаю каким образом им удается публиковать те свои сообщения. Обычно они состоит из короткого сообщения с одной ссылкой.

Результаты исследования:

Дней: Всего спама: Опубликованный спам: Заблокированный спам: Фильтр 1 Фильтр 2 Фильтр 3 Фильтр 4 Фильтр 5
Всего: 3716827291679816288159781401243413525
Среднее за день: 4550.84544404324336366
Эффективность: 0.2%99.8%96.8%95%0.8%73.9%80.4%

фильтр 1: Использование капчи (captcha).
фильтр 2: Генерация скрытого поля на стороне клиента с помощью JavaScript.
фильтр 3: Проверка на наличие основного поля формы.
фильтр 4: Ограничение количества ссылок в сообщении.
фильтр 5: Использование пустого поля, скрытого CSS.

Показать детальный отчет

Погрешность результатов исследования не составляет более 5%, но думаю, что она не больше 2%. Как блокированный спам могли быть записаны, например, неверные попытки пользователя набрать капчу или написать сообщение с более чем, одной ссылкой. Но поскольку количество «полезных» сообщений составляет всего 1%, то «живые» пользователи просто физически не могли существенно повлиять на статистику.

Итоги

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

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

Перепечатки приветствуются, желательно со ссылкой на источник.

Если будут какие-то вопросы — пишите мне, постараюсь ответить.

No pasaran!

Вы дочитали до самого конца страницы.

comments powered by Disqus