Подтвердить что ты не робот

Как проверить подлинность запроса AJAX

Я разрабатываю веб-сайт, на котором пользователи решают головоломки так быстро, как только могут. JavaScript используется для каждой головоломки, а количество миллисекунд отправляется на сервер через AJAX, когда головоломка завершена. Как я могу гарантировать, что время, полученное сервером, не было подделано пользователем?

Я не думаю, что токен аутентификации на основе сеанса (вид, используемый для форм в Rails) достаточно, потому что мне нужно аутентифицировать источник значения, а не только легитимность запроса.

Есть ли способ криптографически подписать запрос? Я не могу думать ни о чем, что не может быть воспроизведено хакером. Является ли какой-либо JavaScript, по его воздействию, на стороне клиента, подверженным фальсификации? Должен ли я использовать что-то, что компилируется, как Flash? (Yikes.) Или есть какой-то способ скрыть секретный ключ? Или что-то еще, о чем я не думал?

Обновление. Чтобы уточнить, я не хочу наказывать людей медленными сетевыми подключениями (и скорость сети должна считаться несовместимой), поэтому время должно быть 100% на стороне клиента (таймер запускается только тогда, когда мы знаем пользователь может увидеть головоломку). Кроме того, есть деньги, поэтому нет "доверия к пользователю".

4b9b3361

Ответ 1

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

Основное предположение заключается в том, что долговечные HTTP-соединения намного быстрее для передачи данных, даже незначительные в некоторых случаях в зависимости от контекста приложения. Он используется в большинстве онлайн-торговых систем, поскольку цены на акции могут меняться несколько раз за секунду, и это самый быстрый способ передачи текущей цены пользователям. Здесь вы можете подробнее прочитать HTTP Streaming или Comet.

Начните с создания aaax-соединения full-duplex между клиентом и сервером. Сервер имеет выделенную линию, чтобы поговорить с клиентом, и клиент может, очевидно, поговорить с сервером. Сервер отправляет головоломку и другие сообщения клиенту по этой выделенной строке. Клиент должен подтвердить получение каждого сообщения на сервер вместе с его локальной меткой времени.

На сервере генерируются случайные токены (могут быть только отдельные целые числа) после отправки головоломки, записывать время, когда каждый токен был сгенерирован, и передать его клиенту. Клиент видит сообщение и должен немедленно передать этот токен вместе с ним по местному времени получения. Чтобы сделать его непредсказуемым для клиента, генерируйте эти маркеры сервера в произвольные интервалы, скажем, между 1 и n ms.

Будут три типа сообщений, которые клиент отправляет на сервер:

PUZZLE_RECEIVED
TOKEN_RECEIVED
PUZZLE_COMPLETED

И два типа сообщений, которые сервер отправляет клиенту:

PUZZLE_SENT
TOKEN_SENT

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

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

PUZZLE_COMPLETED.time - PUZZLE_RECEIVED.time

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

PUZZLE_RECEIVED.time - PUZZLE_SENT.time
TOKEN_RECEIVED.time - TOKEN_SENT.time

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

Ответ 2

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

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

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

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

Ответ 3

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

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

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

(Рассуждение: 200 мс считается очень плохой лаг, и что среднее время реакции человека. Самая короткая возможная "головоломка" для человека для завершения - это тест скорости визуальной реакции, и в этом случае плохое отставание будет иметь 100% разметки по их результатам, так как решение для синхронизации это 2-OPT. Любая головоломка, более сложная, будет меньше уменьшаться за счет отставания.)

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

Ответ 4

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

Ответ 5

Здесь вы должны использовать серверное время. Вот как я это сделаю:

Сделайте запрос AJAX по готовому документу для проверки сервера. Когда серверный код получает пинг, сохраните время на стороне сервера как переменную сеанса (убедитесь, что переменная еще не существует). Когда они завершат викторину, снова возьмите серверное время и сравните ее с переменной сеанса, чтобы определить их продолжительность. Удалите переменную сеанса.

Почему это работает:

  • Вы не запускаете таймер до того, как увидите викторину
  • Задержка сети учитывается, поскольку таймер не запускается до тех пор, пока не поступит запрос AJAX (если у них медленное соединение, запрос AJAX будет медленным)
  • Ping не подделка, потому что вы убедитесь, что переменная сеанса не существует до сохранения

EDIT: Я хотел добавить, что вы можете продолжать поддерживать время на стороне клиента и включать его в окончательный пост. Затем вы можете сравнить его со своим расчетным временем на стороне сервера. Если они достаточно близки, вы можете доверять времени клиента.

Ответ 6

Невозможно запустить и остановить таймер на стороне клиента, не опасаясь манипуляции...

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

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

Поскольку он связан с деньгами, пользователям нельзя доверять.

Сроки должны быть начать на сервере, а на сервере - остановить.

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

..

Ответ 7

Вы задали несколько вопросов в своем первоначальном вопросе, я только отвечу на один из них:

Мне придется использовать что-то, что компилируется, например Flash? (Хлоп.)

Да. Учитывая ваши критерии: 1) 100% точная и 2) Отсутствие возможности вмешательства пользователя, вы должны использовать скомпилированный двоичный файл.

Не нужно мигать, но я предлагаю java-апплет, если мысль о Flash заставит вас сказать "Yikes".

Ответ 8

- Изменить:

Это решение несколько ошибочно, как указано ZoFrex ниже.

- Старый:

Вот какой способ (но вам нужно сделать некоторый профилирование).

Отправляйте серию "проблем" для решения JavaScript, пока они играют в головоломку. Раньше у меня было достаточно большое число N, так что это результат: prime1 * prime2. Это заставляет клиента учитывать число (вы можете получить код, чтобы сделать это в JavaScript), и это потребует времени (это происходит, когда клиенты профилирования входят и отправляют подходящие размерные числа [очевидно, это открывает вам атаки на деградацию, но тем не менее]).

Затем вы просто отправляете вниз 500, из этих простых проблем (или другого типа), и пусть JavaScript решает их в фоновом режиме. Он будет генерировать список решений, и когда вы отправляете завершенное значение, вы также отправляете этот список. Из общего количества предоставленных ответов вы можете определить, сколько времени они потратили на головоломку.

Минусы:

  • Требуется профилирование для определения возможностей различных клиентов (и, следовательно, сложности проблем).
  • Можно атаковать с понижением рейтинга
  • Немного сложный
  • Вычисление JavaScript может прерывать общее решение головоломок
  • Возможно написать бот для решения проблем быстрее, чем JS

Плюсы:

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

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

В конце концов, однако, вам нужно фактически установить клиентскую систему с немного большей безопасностью. И обратите внимание, что Flash, конечно же, не это; это тривиально декомпилировать. Infact, в Австралии был один тест IQ, и он контролировался с помощью приложения Flash, которое было сделано LIVE на телевидении. Конечно, победитель был программистом, мне интересно, почему: P

- Изменить:

OP. Кроме того, я связал его в комментарии к этому сообщению, но просто запустите его, вы заинтересованы в Hashcash, целью которого является показать, что клиент выполнил некоторую "Работу". Даже если моя реализация не подходит, вы можете найти обзор этого поля плодотворным.

Ответ 9

Это сложная проблема, потому что она принципиально неразрешима, поэтому вам нужно обойти компромиссы, чтобы сделать все возможное. На технической стороне было несколько замечательных моментов, включая: (а) не тратьте время на размышление о компиляции Flash, Windows, Silverlight, JVM или что-то на самом деле поможет, (б) сначала передать зашифрованную реальную полезную нагрузку головоломки, то, поскольку фактическое узкое место передает только один ключ, (c) латентность даже на 56k отправки пары сотен байт пренебрежимо мала по сравнению с временем реакции человека.

Одна вещь, о которой я не упоминал, такова:

Использовать аудит и отслеживание пользователей после факта. Вот как работают настоящие казино. Это, как мне сказали, большая часть того, как PayPal зарабатывала деньги. В обоих случаях, вместо того, чтобы делать много предоперационной безопасности, они очень внимательно следят за всеми своими игроками, используют множество технологий (статистика, обнаружение патчей и т.д.), Чтобы помечать подозрительных игроков, и они исследуют. В обоих казино и PayPal вы не можете сразу получить свои деньги. Вы должны наживать свои фишки или ждать, пока деньги выйдут из системы PayPal в ваш реальный банк. Ваша система должна работать одинаково - они не могут получить деньги в течение как минимум нескольких дней минимум (дольше, если вы не можете создать достаточно быструю систему аудита), давая вам время, чтобы потенциально наложить их выигрыши. У вас есть адвокат, верно? Кроме того, казино и PayPal знают вашу реальную жизненную идентичность (обязательную для работы с деньгами), чтобы они могли идти за вами юридически - или, что более важно, сдерживать потенциальных нападавших, поскольку они могли идти за ними на законных основаниях.

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

Если вы обнаружите, что это не так, сделайте свою цель не полностью устранять обман, а поддерживать приемлемый уровень. Это похоже на время безотказной работы 99,99%. Да, как сказал один из плакатов, если даже один человек может пойти на компромисс, все прикручиваются, но с хорошей системой аудита злоумышленник не сможет последовательно обманывать. Если они могут обмануть 1 в 1000 раз, если им повезет, и они обнаруживают, что они не могут обманывать более одного или двух раз, прежде чем их поймают, это не будет проблемой, так как очень немногие обманут, а любой честный пользователь получит чрезвычайно низкая вероятность того, что на него повлияет чрезвычайно небольшое количество обмана. Это будет незаметно. Если у вас когда-либо будет реальное обманывание, которое причиняет вред честному пользователю, уйдите с вашего пути, чтобы заставить честного пользователя чувствовать удовлетворение результатом до степени, не соответствующей стоимости этого единственного клиента. Таким образом, все будут уверены в вашей безопасности. Они знают, что им не нужно ни о чем беспокоиться.

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

Ответ 10

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

Ответ 11

Как отметили некоторые другие:

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

Ответ на проблему заключается в использовании протокола синхронизации времени между клиентом и сервером, аналогичным протоколу, который использует NTP. Совместно работая клиент и сервер определяют величину задержки, вызванной задержкой в ​​сети. Затем это учитывается во времена, предоставляемые каждому пользователю.

Алгоритмы NTP сложны и были разработаны в течение многих лет. Но простой подход ниже; Я думаю, что протокол должен работать, но вы можете проверить его.

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

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

Ответ 12

существует очень быстрая реализация криптографии в js здесь

http://crypto.stanford.edu/sjcl/

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

вот подробное объяснение, которое вы можете приспособить к вашим потребностям http://crypto.stanford.edu/sjcl/#usage

Ответ 13

Просто подумайте: почему бы вам не использовать iFrame для включения игры и ее javascripts, и пусть они находятся на сервере, на котором выполняется ваша реализация на стороне сервера. Любой запрос ajax затем должен быть отправлен тем же IP-адресом, что и ваш IP-адрес на стороне сервера, который разрешит проблему идентификации источника. Конечно, вы должны принять дальнейшие меры, но уже получили большую уверенность в своих "клиентских" запросах. Помните, что вход в систему windowsLive входит в систему, и многие другие, например, основаны на javascript и использовании iFrames и считаются достаточно безопасными.

Ответ 14

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

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

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

Обратите внимание, что даже в других решениях вы загружаете сервер, загрузку клиента (медленный процессор и т.д.) и т.д., которые влияют на время.

Убедитесь, что у вас есть защита XSRF на странице отправки головоломки:)

Ответ 15

Как я могу это сделать, когда сервер отправляет головоломку клиенту, текущее время сохраняется в сеансе. Это гарантирует, что время начинается сразу после отправки головоломки. После того, как головоломка завершена и отправлена ​​на сервер, чтобы проверить, правильно ли выполнена головоломка, сервер снова проверяет время и делает сравнение.

Очевидно, что медленные интернет-соединения могут сделать это время больше, но вы ничего не можете с этим сделать.