Чистка читеров

MySQL, PostgreSQL, MSSQL, Oracle и т.д. Диалекты SQL, формирование запросов, хранимые процедуры, тригерры, транзакции и многое другое

Чистка читеров

Сообщение xdsl 06 май 2009, 14:40

Проблема читерства - одна из самых серьезных в использовании различных систем электронного голосования. Мы столкнулись с ней при организации конкурсов рисунков и фотографий (http://shgpi.edu.ru/contests/). Со своей (программистской) стороны я постарался с ней разобраться, но все решения наталкиваются на все возрастающую изобретательность читеров. Рассмотрим одно из последних решений проблемы (наверняка - временное). Дано - таблица голосов пользователей. Ее структура:
Код: Выделить всё
  CREATE TABLE  `shgpi`.`gallery_foto_votes_3` (
  `id` bigint(20) NOT NULL auto_increment,
  `toUser` bigint(20) NOT NULL default '0',
  `vote_date` datetime NOT NULL default '0000-00-00 00:00:00',
  `REMOTE_ADDR` varchar(30) NOT NULL default '',
  `REMOTE_PORT` varchar(10) NOT NULL default '',
  `HTTP_COOKIE` varchar(2500) NOT NULL default '',
  `HTTP_VIA` varchar(250) NOT NULL default '',
  `HTTP_X_FORWARDED_FOR` varchar(250) NOT NULL default '',
  `HTTP_USER_AGENT` varchar(255) NOT NULL default '',
  `HTTP_ACCEPT` varchar(50) NOT NULL default '',
  `HTTP_ACCEPT_LANGUAGE` varchar(50) NOT NULL default '',
  `HTTP_ACCEPT_ENCODING` varchar(50) NOT NULL default '',
  `HTTP_ACCEPT_CHARSET` varchar(50) NOT NULL default '',
  `HTTP_KEEP_ALIVE` varchar(10) NOT NULL default '',
  `HTTP_CACHE_CONTROL` varchar(10) NOT NULL default '',
  `HTTP_CONNECTION` varchar(20) NOT NULL default '',
  PRIMARY KEY  (`id`),
  KEY `toUser` (`toUser`)
)
Как видно, чтобы особо не мудрствовать, в записях хранятся сохраняются id - уникальный идентификатор, toUser - идентификатор фото или рисунка пользователя (столь странное название - по историческим причинам: первые галлереи имели один рисунок на одного пользователя), vote_date - дата-время подачи голоса. Остальные поля - полная информация об удаленном пользователе.

Казалось-бы, пускать голосовать по уникальному IP-адресу (REMOTE_ADDR) и все. Однако не все так просто. Во первых, хотелось бы пускать с одного компьютера не единожды, а как минимум - раз в час (пусть проголосует вся семья!). Во вторых, IP-адрес - вещь на самом деле крайне не уникальная. Достаточно обеспечить выход в интернет через прокси-сервер или NAT и вот уже на IP адрес положиться нельзя. К счастью, есть еще несколько параметров, по которым с большой вероятностью можно судить об уникальности компьютера.

Во первых, проблему с прокси частично решает поле HTTP_X_FORWARDED_FOR (конечно - если это "честный" прокси, а не анонимный крякерский). В нем сохраняются адреса всех прокси, через которые прошел запрос, в начале списка - адрес отправителя. Значит с большой вероятностью HTTP_X_FORWARDED_FOR обеспечит нам уникальный адрес пользователя прокси.

Теперь о проблеме NAT. С первого взгляда проблема нерешаемая, ведь адрес, с которого пришел запрос - это адрес шлюза, а не клиента. К счастью, при использовании NAT работают обычно с пулом адресов, что повышает вероятность корректного голосования нескольких различных юзеров. Если в дополнение применять HTTP_USER_AGENT - идентификацию, посылаемую браузером, и HTTP_COOKIE - отправляемые куки, то можем получить вполне приемлимый результат, а именно - комбинацию HTTP_USER_AGENT и HTTP_X_FORWARDED_FOR (последний удается использовать в любом случае, т.к. наш сервер находится за обратным прокси) для идентификации компьютера, а добавив HTTP_COOKIE - для идентификации сеанса.

Хороша система, да одна проблема - читеры ее взламывают на раз-два-три.

Продолжение следует ...
xdsl
 
Сообщения: 1233
Зарегистрирован: 09 дек 2008, 05:16
Откуда: ВЦ ШГПИ
Полное имя: Слинкин Д.А.

Re: Чистка читеров

Сообщение xdsl 07 май 2009, 10:24

Продолжение первое.

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

Итак, на стороне сервера проверяем HTTP_USER_AGENT и HTTP_X_FORWARDED_FOR запроса, смотрим, есть ли базе такие пользователи за последний час. Если есть - отвергаем голос, сообщаем читеру, что его попытка неудачна. Если нет - сохраняем голос в базе.

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

Во первых - используют разные браузеры, каждый из которых высылает свои, уникальные данные в HTTP_USER_AGENT. Плюс некоторые браузеры позволяют менять содержимое HTTP_USER_AGENT. Способ не слишком эффективный, т.к. плохо автоматизируется, однако лишние 5-7 голосов на час набрать позволяет. При очень большой работоспособности и ослином упрямстве можно достичь неплохих результатов.
Способы противодействия: практически никаких. Хоть HTTP_X_FORWARDED_FOR один и тот-же, это вполне может быть NAT-шлюз, заблокировав который мы ограничим всех остальных юзеров, выходящих через него в интернет. Статистические методы стопроцентного результата тоже не дадут, а обычных юзеров могут заблокировать.

Во вторых, при домашнем подключении к инету (напр., через ADSL) юзер часто получает IP-адрес из определенного диапазона (пула адресов), причем чаще всего - каждый раз разный. На этом читеры и играют. Механизм прост как три копейки и неплохо автоматизируется. Его суть: подключаемся к инету, голосуем, отключаемся от инета ... подключаемся к инету, голосуем, отключаемся от инета ... подключаемся к инету, голосуем, отключаемся от инета ... и так сколько хватит терпения.
Способы противодействия: практически никаких. Каждый раз HTTP_X_FORWARDED_FOR разный, а то что HTTP_USER_AGENT одинаков означать может и то, что один и тот же браузер используют разные юзера на разных компьютерах.

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

Теперь перейдем к реальным вещам, а именно - к системе голосования на конкурсе цифровых фото http://shgpi.edu.ru/contests/gallery_foto_3/. Общее кол-во голосов - 9716, после обработки базы античитерским скриптом - 6955. Результат - смена лидеров. Подробно рассмотрим исходные и результирующие данные, статистику по предыдущим и текущим лидерам, проанализируем античитерский скрипт.

Продолжение следует ...
xdsl
 
Сообщения: 1233
Зарегистрирован: 09 дек 2008, 05:16
Откуда: ВЦ ШГПИ
Полное имя: Слинкин Д.А.

Re: Чистка читеров

Сообщение xdsl 13 май 2009, 10:12

Продолжение второе

Итак, система голосования на конкурсе цифровых фото.

Вариант со слабой античитерской защитой содержит 9716 голосов и находится по адресу
http://shgpi.edu.ru/contests/gallery_foto_3_chiters.
Лидеры -
1. фото 4038 (http://shgpi.edu.ru/contests/gallery_foto_3_chiters/?bigshow=4038), 1009 голосов, МОУ Межборская СОШ, Притобольный район
2. фото 4032 (http://shgpi.edu.ru/contests/gallery_foto_3_chiters/?bigshow=4032), 861 голос, МОУ Межборская СОШ, Притобольный район
3. фото 1009 (http://shgpi.edu.ru/contests/gallery_foto_3_chiters/?bigshow=1009), 800 голосов, МОУ СОШ N4, г. Шумиха

Вариант с удаленными голосами читеров содержит 6955 голосов и находится по адресу
http://shgpi.edu.ru/contests/gallery_foto_3_chiters
Новые лидеры -
1. фото 2022 (http://shgpi.edu.ru/contests/gallery_foto_3/?bigshow=2022), 450 голосов, МОУ Заманилкинская СОШ, Целинный район
2. фото 2025 (http://shgpi.edu.ru/contests/gallery_foto_3/?bigshow=2025), 450 голосов, МОУ Заманилкинская СОШ, Целинный район
3. фото 1032 (http://shgpi.edu.ru/contests/gallery_foto_3/?bigshow=1032), 449 голосов, МОУ Заманилкинская СОШ, Целинный район

Похоже, произошла не только смена лидеров, но и смена читеров, что мы также проверим, но несколько позднее.

Рассмотрим, в чем была слабость используемой античитерской защиты. Проблема заключалась в отсутствии сессионной проверки, т.е. идентификатор сессии, хранимый в поле http_cookie не проверялся вообще. Таким образом юзер, не очищая куки браузера и не перезагружая браузер, многократно переподключался к провайдеру, получая новый ip-адрес и снова голосовал. Для очистки таких читеров достаточно проверить поле http_cookie и почистить все голоса, с одинаковым значением данного поля, поданные в течение одного часа. Однако хотелось-бы получить более универсальный алгоритм, подходящий в будущем для очистки любых читерских голосов, даже если они были поданы вообще без всякой античитерской защиты и в результате - размещены в базе данных. Тогда задача заключается в определении уникальности каждого клиента. На основе всего вышесказанного видим, что уникальность клиента обеспечивается ЛИБО http_cookie, ЛИБО (если http_cookie содержит различные значения) комбинацией полей http_x_forwarded_for и http_user_agent. Вычислив уникальных клиентов, оставим в базе по одному их голосу на один час.

Теперь - о реализации. Очень хотелось справиться с задачей, не привлекая сторонние языки, обойдясь одним SQL, причем линейно, без циклов и условий, т.е. без расширений типа PL/SQL и т.п. Решение оказалась не совсем тривиальным.

На входе задачи имеем таблицу gallery_foto_votes_3 (ее структура - см. https://shgpi.edu.ru/forum/viewtopic.php?p=953#p953). На выходе хочется иметь таблицу gallery_foto_votes_3_nochit с такой-же структурой, но без читерских голосов. Вот что в результате получилось ...

Продолжение следует ...
xdsl
 
Сообщения: 1233
Зарегистрирован: 09 дек 2008, 05:16
Откуда: ВЦ ШГПИ
Полное имя: Слинкин Д.А.

Re: Чистка читеров

Сообщение xdsl 13 май 2009, 11:39

Продолжение третье

Создаем копию таблицы голосов gallery_foto_votes_3_nochit
Код: Выделить всё
drop table if exists gallery_foto_votes_3_nochit;
create table gallery_foto_votes_3_nochit select * from gallery_foto_votes_3;
ALTER TABLE gallery_foto_votes_3_nochit ADD PRIMARY KEY (id), ADD INDEX toUser(toUser);

Создаем временную таблицу votes - копию таблицы голосов с дополнительным полем compid (уникальным идентификатором клиента, сформированным по либо из http_cookie, либо из комбинации http_x_forwarded_for и http_user_agent)
Код: Выделить всё
create temporary table votes
SELECT distinct g.http_cookie as compid, g.* FROM gallery_foto_votes_3 g, gallery_foto_votes_3 g2
where g.id!=g2.id and g.http_cookie=g2.http_cookie
union
SELECT concat(http_x_forwarded_for,http_user_agent)as compid,g.* FROM gallery_foto_votes_3 g
group by http_cookie
having count(http_cookie)=1
order by touser, compid, vote_date;

На основе таблицы votes создаем временную таблицу chiters, содержащую идентификаторы читерских голосов. По окончании - уничтожаем временную таблицу votes
Код: Выделить всё
set @chiter=0,@prev_user=0,@prev_compid="";
create temporary table chiters
select id from
(
  select id
       ,touser
       , vote_date   
       ,if ((convert(@prev_user,unsigned)=convert(touser,unsigned))
             and (convert(@prev_compid,char)=convert(compid,char))
             and (TIMESTAMPDIFF(HOUR , vote_date, @chiter)=0),0,@chiter:=vote_date) as chiter
       , @prev_user:=touser
       , @prev_compid:=compid           
  from
  votes
)g
where chiter = 0;
drop table votes;

И, наконец, удаляем из таблицы gallery_foto_votes_3_nochit все голоса, отмеченные как читерские в таблице chiters. По окончании - уничтожаем временную таблицу chiters
Код: Выделить всё
delete gallery_foto_votes_3_nochit from gallery_foto_votes_3_nochit, chiters
where gallery_foto_votes_3_nochit.id=chiters.id;
drop table chiters;

Вот таким образом удалось избавится от особо настырных читеров. Однако очень интересно узнать, какими способами новые лидеры ухитрились набрать по полтыщи голосов. Но об этом - чуть позднее ...

Продолжение следует ...
xdsl
 
Сообщения: 1233
Зарегистрирован: 09 дек 2008, 05:16
Откуда: ВЦ ШГПИ
Полное имя: Слинкин Д.А.

Re: Чистка читеров

Сообщение alekam 19 авг 2010, 13:17

Взяв за основу структуру из первого поста xdsl, сделал голосование для городского конкурса детского рисунка http://www.shadrinsk.info/gallery/gorod ... ya-kunica/
По условиям конкурса должна быть одна кнопка, позволяющая проголосовать за одну работу любому анонимному пользователю, в течении конкурса результаты недоступны.
Сейчас идет накопление данных.

Некоторые замечания отностельно структуры таблицы:
- REMOTE_PORT - бесполезен. Браузер Chrom например для каждого соединения использует разные значения.
- для HTTP_ACCEPT varchar(50) слишком мало. Например, IE отправляет все поддерживаемые форматы, в том числе форматы офисных документов
alekam
 
Сообщения: 46
Зарегистрирован: 23 дек 2008, 14:36
Полное имя: A.K.

Re: Чистка читеров

Сообщение xdsl 23 авг 2010, 09:44

alekam писал(а):- REMOTE_PORT - бесполезен. Браузер Chrom например для каждого соединения использует разные значения.
- для HTTP_ACCEPT varchar(50) слишком мало. Например, IE отправляет все поддерживаемые форматы, в том числе форматы офисных документов

Согласен. Но эти поля (и многие другие) висят в базе "мертвым грузом", т.е. в системе не используются вообще. Этакий плюшкинизм (авось когда-нибудь пригодится ;))
xdsl
 
Сообщения: 1233
Зарегистрирован: 09 дек 2008, 05:16
Откуда: ВЦ ШГПИ
Полное имя: Слинкин Д.А.

Re: Чистка читеров

Сообщение Pavel 02 мар 2011, 20:38

прочитав тему, понял что без мак адреса(в большинстве случаев не обойтись), опять же у нас есть прокси сервер
на форумеhttp://forum.php.su/topic.php?forum=35&topic=60 предложена идея отслеживания, но так же там написаны и недостатки.
ИМХО кто хочет "читерить" тот найдёт как, но от простых юзеров можно избавиться
Аватара пользователя
Pavel
Elite
 
Сообщения: 46
Зарегистрирован: 10 фев 2009, 07:58
Откуда: ПСТ
Полное имя: Колесов Павел

Re: Чистка читеров

Сообщение Vladislav_133 02 мар 2011, 22:09

Ну и как вы его будете искать? мак-адрес,т.е.

Я уточню вопрос. Как вы найдете мой мак-адрес, если я сижу в сети Курьер, а вы в сети ШГПИ?
Аватара пользователя
Vladislav_133
Elite
 
Сообщения: 1322
Зарегистрирован: 13 дек 2008, 18:08
Полное имя: П.В.Ю.

Re: Чистка читеров

Сообщение xdsl 04 мар 2011, 08:42

А вот никак его не определить, если клиенты в различных физических сетях. Для сети Интернет он вообще - вещь безосмысленная. MAC - он верен в одной физической сети, до ближайшего маршрутизатора, а потом маршрутизатор, разобрав и проанализировав IP-пакет, вставляет туда MAC одного из своих портов (какой по результатам анализа дает ближайший путь до приемника), собирает пакет и отправляет его дальше через соответствующий порт. Прокси-сервера работают аналогично, только разбор у них на уровне IP не останавливается, дальше идет, плюс еще и IP-адрес подменяется. NAT - посрединке между двумя этими технологиями, но и тут MAC+IP гарантированно заменяются.

Вообщем MAC полезен только в рамках коммутируемого соединения (компьютер+компьютер или компьютер+свич+...+свич+компьютер).
xdsl
 
Сообщения: 1233
Зарегистрирован: 09 дек 2008, 05:16
Откуда: ВЦ ШГПИ
Полное имя: Слинкин Д.А.


Вернуться в Базы данных

Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 1

cron