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

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

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

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

Обновление: Для разъяснения я не хочу штрафовать людей с медленными сетевыми соединениями (и скорость сети нужно считать непоследовательной), таким образом, синхронизация должна быть на 100% клиентской (таймер запускается только, когда мы знаем, что пользователь видит загадку). Кроме того, существуют деньги, включенные так никакой объем "доверия, что пользователь" приемлем.

34
задан Alex Reisner 16 January 2010 в 03:23
поделиться

15 ответов

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

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

Начните с создания Full-Duplex соединение AJAX между клиентом и сервером. Сервер имеет выделенную линию, чтобы поговорить с клиентом, и клиент может, очевидно, разговаривать с сервером. Сервер отправляет головоломку и другие сообщения клиенту на эту выделенную строку. Предполагается, что клиент подтверждает получение каждого сообщения на сервер вместе со своим локальным временем.

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

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

PUZZLE_RECEIVED
TOKEN_RECEIVED
PUZZLE_COMPLETED

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

PUZZLE_SENT
TOKEN_SENT

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

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

PUZZLE_COMPLETED.time - PUZZLE_RECEIVED.time

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

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

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

10
ответ дан 27 November 2019 в 17:04
поделиться

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

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

.
-4
ответ дан 27 November 2019 в 17:04
поделиться

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

3
ответ дан 27 November 2019 в 17:04
поделиться

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

1
ответ дан 27 November 2019 в 17:04
поделиться

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

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

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

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

12
ответ дан 27 November 2019 в 17:04
поделиться

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

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

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

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

РЕДАКТИРОВАТЬ: Я хотел добавить, что вы можете продолжать поддерживать клиента- время в сторону, и включите его в последний пост. Затем вы можете сравнить его с расчетным временем на стороне сервера. Если они достаточно близки, то клиенту можно доверять.

3
ответ дан 27 November 2019 в 17:04
поделиться

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

Это немного неинтуитивно и запутанно, но это имеет тенденцию происходить с большинством мета-программирования, особенно в такой системе, как PHP.

-121--1493510-

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

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

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

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

Синхронизация должна запускаться на сервере и останавливаться на сервере.

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

..

4
ответ дан 27 November 2019 в 17:04
поделиться

Как отметили несколько других:

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

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

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

Попросите клиента измерить время турнира с двумя последовательными привязками HTTP XMLRPC. Каждый пинг возвращает другой нон. Второй пинг требует нон из первого пинга, что гарантирует, что они являются последовательными. Время головоломки начинается, когда вторая HTTP PING отправляется с клиента. The Server Timestamps каждый запрос и предполагает, что головоломка отображается 1/2 способа между получением первого и второго запроса.

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

1
ответ дан 27 November 2019 в 17:04
поделиться

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

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

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

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

0
ответ дан 27 November 2019 в 17:04
поделиться

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

Я собираюсь использовать что-то, что скомпилируется, как Flash? (Yikes.)

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

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

2
ответ дан 27 November 2019 в 17:04
поделиться

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

0
ответ дан 27 November 2019 в 17:04
поделиться

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

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

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

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

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

8
ответ дан 27 November 2019 в 17:04
поделиться

-- Правка:

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

-- Старое:

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

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

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

Против:

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

Плюсы:

  • Расчеты должны быть выполнены для того, чтобы отправить форму
  • Если она корректно реализована, то предотвратит все нетривиальные атаки

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

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

-- Edit:

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

2
ответ дан 27 November 2019 в 17:04
поделиться

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

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

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

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

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

0
ответ дан 27 November 2019 в 17:04
поделиться

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

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

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

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

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

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

2
ответ дан 27 November 2019 в 17:04
поделиться
Другие вопросы по тегам:

Похожие вопросы: