предотвращение читерства для браузерной игры xmlhttp/js/perl/php

Допустим, в браузерной игре, выполняя какое-то действие (для простоты скажем, кто-то нажимает на ссылку, которая увеличивает его счет на 100), нажимая на эту ссылку, которая будет иметь URL-адрес, например, increase_score.pl?amount=100 какая профилактика существует от кого-то просто отправка запросов на веб-сервер для выполнения этой команды:

  1. Снова и снова, фактически не выполняя задачу нажатия на ссылку и
  2. Отправка ложного запроса на сервер, где для суммы установлено что-то вроде 100000.

Я знаю о проверке HTTP_REFERER, однако я знаю, что люди могут обойти это (не знаю, как именно), и, кроме проверки некоторых границ для второго варианта, я немного в тупике. Кто-нибудь когда-нибудь сталкивался с подобными проблемами? Решения?


person user105033    schedule 16.11.2009    source источник
comment
Ваше приложение должно знать, разрешено ли это действие.   -  person Gumbo    schedule 17.11.2009
comment
Кто-то может просто отправить последовательность запросов на сервер, которая позволит им добраться до точки, где это действие разрешено.   -  person user105033    schedule 17.11.2009
comment
Тогда ваш сервер не должен на самом деле давать очки.   -  person Ben S    schedule 17.11.2009
comment
Комментарий «не уверен, как именно» WRT к тому, почему HTTP_REFERRER является легко обходимой превентивной мерой, указывает на то, что в протоколе HTTP и CGI в целом есть много такого, чего вы не знаете, и это вызовет много проблем в будущем, если вы учитывая безопасность веб-приложения. Очень полезным будет знакомство с HTTP (заголовки, разные версии), прокси, CGI, Javascript, XSS, веб-серверами и т. д.   -  person jsoverson    schedule 17.11.2009


Ответы (10)


Ничто не сможет помешать им сделать это, если вы реализуете свою игру так, как предлагаете.

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

Например: на SO, когда кто-то голосует за ваш вопрос, это не отправляется как команда для повышения вашей репутации. Веб-приложение просто сообщает пользователю сервера X, что он проголосовал за вопрос Y. Затем сервер проверяет данные и присваивает баллы, если все проверено. (Не сказать, что это игра, но требуемая логика похожа.)

person Ben S    schedule 16.11.2009
comment
@JB: Ха-ха-ха, да... и моя оценка более 9000! :D - person Powerlord; 17.11.2009
comment
@JB: Конечно, нет. Это просто сообщество с механизмом для -- эй! Я почти набрал 700 баллов! Давай, еще один голос за большое круглое число, иди к папочке.... - person BlairHippo; 17.11.2009

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

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

НЕПРАВИЛЬНЫЙ ПУТЬ:
Клиент: Игрок Стив говорит дать Игроку Стиву тысячу очков.
Сервер: Хорошо!

ПРАВИЛЬНЫЙ СПОСОБ:
Клиент: Игрок Стив говорит дать Игроку Стиву один миллиард очков.
Сервер: Хорошо, позвольте мне сначала проверить, находится ли Игрок Стив в данный момент в время, позволенное дать себе одну тысячу очков ... ах. Это не так. Пожалуйста, покажите это сообщение «Иди к черту, мошенник» игроку Стиву.

Что касается сообщения о том, кто вошел в систему, это просто вопрос передачи клиенту файла cookie с чертовски почти невозможным для угадывания значением, которое вы отслеживаете на сервере, но я предполагаю, что вы знаете, как с этим бороться с управлением сессиями. :-) (А если нет, Google ждет.)

person BlairHippo    schedule 16.11.2009
comment
Папа, вот твое большое круглое число. - person glenn jackman; 17.11.2009

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

HTTP_REFERER можно подделать с помощью любого веб-клиента.

person Alexandru Luchian    schedule 16.11.2009

Токен с файлом cookie/сеансом.

person Ahmet Kakıcı    schedule 16.11.2009

Вы можете сделать ссылку динамической и изменить хэш в конце. Убедитесь, что хэш правильный с учетом этого периода времени.

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

person sclarson    schedule 16.11.2009

Несколько вещей, на которые следует обратить внимание.

Во-первых, запросы вашего сервера на что-то подобное должны быть POST, а не GET. Только GET-запросы должны быть идемпотентными, и несоблюдение этого фактически является нарушением протокола HTTP. спецификация.

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

Ben S очень хорошо говорит о том, как вы разрабатываете протоколы связи между клиентом и сервером. Разрешить отправку значений точек в качестве доверенных данных, как правило, будет плохой идеей. Предпочтительно указать, что действие имело место, и позволить серверу выяснить, сколько очков должно быть назначено, если вообще. Но иногда вы не можете обойти это. Рассмотрим сценарий гоночной игры. Клиент должен отправить время пользователя, и его нельзя абстрагировать каким-либо другим вызовом, например «completedLevelFour». Так что вы будете делать теперь?

Токеновый подход, предложенный Ахметом и Дином, логичен, но не идеален. Во-первых, токен все еще должен быть передан клиенту, что означает, что он может быть обнаружен потенциальным злоумышленником и может быть использован злонамеренно. Кроме того, что, если ваш игровой API должен быть без сохранения состояния? Это означает, что аутентификация токена на основе сеанса отключена. А теперь вы попадаете в глубокие темные недра проблемы доверия клиентов.

Вы мало что можете сделать, чтобы сделать его на 100% надежным. Но вы можете сделать обман очень неудобным. Рассмотрим модель безопасности Facebook (каждый запрос API подписан). Это очень хорошо и требует, чтобы злоумышленник действительно покопался в коде на стороне вашего клиента, прежде чем он сможет понять, как подделать запрос.

Другой подход — повтор сервера. Как и в гоночной игре, вместо того, чтобы просто отправлять значение «время» на сервер, используйте контрольные точки, которые также записывают время и отправляют их все. Установите реалистичные минимумы для каждого интервала и проверьте на сервере, что все эти данные находятся в установленных границах.

Удачи!

person Peter Bailey    schedule 16.11.2009

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

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

person brian d foy    schedule 16.11.2009

Расширяя ответ Ахмета, каждый раз, когда они загружают страницу, генерируется случайный ключ. Сохраните ключ в сеансе пользователя. Добавьте случайный ключ к каждой ссылке, чтобы новая ссылка для получения этих 100 баллов была следующей:

increase_score.pl?amount=100&token=AF32Z90

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

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

person Dean J    schedule 16.11.2009
comment
Только не баньте людей за это — есть законные причины для перезагрузки страницы, например, попытка посмотреть, не изменилось ли что-нибудь, или перезапустить браузер. - person Roman Starkov; 17.11.2009
comment
То, что вы сделали, усложнило ваше приложение и потребовало соответствующей сложности чит-программы. Это не гонка вооружений, в которую вы хотите ввязываться, поскольку у мошенников практически неограниченное время для изучения вашего Javascript, и вы не можете изменить его в режиме реального времени, чтобы ответить. - person David Thornley; 17.11.2009
comment
На самом деле это может вызвать проблему — если пользователь перейдет на страницу с такой ссылкой и обновится, случайное значение изменится, и ссылка станет недействительной, если по ней ни разу не нажимали. - person Frank DeRosa; 17.11.2009
comment
Это все еще небезопасно, так как вы можете изменить сумму = и сохранить токен. Безопасный способ — сгенерировать токен для каждой ссылки, затем использовать только токен в качестве параметра и искать реальное действие при отправке токена. Таким образом, пользователь может вызвать только то действие, которое действительно было на странице. Конечно, вы аннулируете все токены, как только один токен возвращается, или после тайм-аута... что предотвращает повторные атаки. - person sleske; 17.11.2009
comment
1. Кто сказал что-нибудь о Javascript? 2. При обновлении следует также обновить токены. 3. И да, вы, вероятно, не хотите, чтобы сумма=x использовалась в качестве параметра. - person Dean J; 17.11.2009

Я бы предложил сделать URL-адрес, специфичный для каждого действия. Что-то вроде:

/score/link_88_clicked/
/score/link_69_clicked/
/score/link_42_clicked/

Каждая из этих ссылок может делать две вещи:

  1. Отметьте в сеансе, что ссылка была нажата, чтобы она больше не отслеживала эту ссылку.
  2. Добавьте к их счету.
person Jack M.    schedule 16.11.2009
comment
Это плохо масштабируется и излишне запутывает приложение. - person Ben S; 17.11.2009
comment
Обфускация URL — это то, что мне нужно. Просто усложните для игрока изменение URL-адреса и получите преимущество в счете. Однако мне любопытно, почему это не будет хорошо масштабироваться? Обработчик mod_perl, анализирующий оценки и отправляющий вызов метода, кажется, отлично масштабируется. - person Jack M.; 17.11.2009

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

Это также блокирует большинство трюков CheatEngine.

person Nils Munch    schedule 15.07.2011
comment
Игра (по крайней мере, часть взаимодействия с пользователем) по-прежнему будет работать на стороне клиента, а не на сервере. Я не понимаю, как вы можете заблокировать это. - person Paŭlo Ebermann; 16.07.2011