如何检查AJAX请求的真实性

时间:2010-01-06 23:19:54

标签: javascript ajax security language-agnostic encryption

我正在设计一个网站,用户可以尽快解决难题。 JavaScript用于计算每个拼图,并在拼图完成时通过AJAX将毫秒数发送到服务器。如何确保服务器收到的时间不是由用户伪造的?

我不认为基于会话的真实性令牌(Rails中用于表单的那种)就足够了,因为我需要验证值的,而不仅仅是请求的合法性

有没有办法对请求进行加密签名?我想不出黑客无法复制的任何东西。任何JavaScript,由于其暴露的客户端性质,都会受到篡改吗?我是否必须使用像Flash这样的编译器? (Yikes。)或者有什么方法可以隐藏密钥吗?或者其他我没有想过的东西?

更新:为了澄清,我不想惩罚网络连接速度慢的人(网络速度应该被认为是不一致的),所以时间需要100%客户端(只有当我们知道时,计时器才会启动)用户可以看到这个谜题)。此外,还涉及金钱,因此不能接受“信任用户”的数量。

15 个答案:

答案 0 :(得分:12)

您不能以加密方式保证计时的安全性,因为客户端的浏览器无法进行安全计算。可以通过调整实际时间来绕过任何加密到服务器的方法。

服务器上的计时也不起作用 - 如果你没有考虑到往返时间的延迟,那么具有较低延迟连接的用户将具有优势;如果你这样做,用户可以通过在那里增加额外的延迟来阻止补偿阶段,然后再将其删除。

当然,你可以让用户很难对其进行修改,但无论如何,默默无闻的安全措施都是不可持续的政策。

所以它归结为要么在某种程度上信任你的用户(大多数时候都是合理的假设)和设计游戏,所以规避时间并非易事。

答案 1 :(得分:10)

这种方法显然是做出假设而不是立于不败之地。所有计算都在客户端完成,服务器进行一些后台检查以确定请求是否可以伪造。像任何其他基于客户端的方法一样,这不是确定性的,但对于说谎的客户来说非常困难。

主要假设是长期HTTP连接在传输数据方面要快得多,在某些情况下甚至可以忽略不计,具体取决于应用程序上下文。它用于大多数在线交易系统,因为股票价格可以在一秒内多次改变,这是向用户传输当前价格的最快方式。您可以在此处详细了解HTTP Streaming or Comet

首先在客户端和服务器之间创建full-duplex ajax连接。服务器有专用线路与客户端通信,客户端显然可以与服务器通信。服务器在此专用线路上将拼图和其他消息发送到客户端。客户端应该确认每个消息的接收连同其本地时间戳。

在拼图发送后,服务器上生成随机令牌(可能只是不同的整数),记录生成每个令牌的时间,并将其传递给客户端。客户端看到该消息,并且应该立即将该令牌与其本地接收时间一起中继。为了使客户端无法预测,请以随机间隔生成这些服务器令牌,例如1n 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 :(得分:8)

即使是已编译的应用程序也可以伪造。如果用户在计时中途更改了系统时钟,则应用程序将向服务器报告错误的时间。 唯一方式获得准确的上限时间是在给出谜题时在服务器上开始计时,并在他们提供答案时停止计时。

正如其他人所指出的那样,通过使拼图的负荷尽可能小,您可以最大限度地减少连接速度慢的影响。首先加载整个页面和“游戏引擎”,然后使用异步请求加载拼图本身(应该是少量数据),以尽可能地平衡游戏场地。

不幸的是,你不能做延迟补偿,因为这可能会被篡改。然而,在一个没有被用于其他任何东西的连接上,这样一个请求的延迟会因人类解决一个谜题而大大黯然失色,我认为这不会是一件大事。

(推理:200毫秒被认为是非常糟糕的滞后,这是人类平均反应时间。人类完成的最短可能的“难题”是视觉反应速度测试,在这种情况下,坏的延迟将有100%因此,作为时间解决方案,这是2-OPT。任何更复杂的难题都会受到滞后影响。)

我还会在页面上放置一个横幅,说明在播放最佳速度时不要使用互联网连接,可能会链接到速度/延迟测试仪。

答案 3 :(得分:4)

在不担心操作的情况下,无法在客户端启动和停止计时器......

您在客户端执行的任何操作都可以更改/停止/绕过..

在客户端加密/解密也不安全,因为他们可以在加密发生之前改变信息。

由于涉及金钱,用户不可信任。

时间必须开始在服务器上,并且必须停止在服务器上..

如果拼图内容返回ajax调用的结果,则使用ajax在服务器 启动计时器。不要加载拼图,然后发送一个ajax请求,因为这可能会被劫持和延迟,而他们审查拼图...

...

答案 4 :(得分:3)

根据您拥有的服务器端实现,您可以将计时功能放在服务器端。记录网页请求的时间(如果您愿意,可以将其放入数据库中),然后在收到答案时获取当前时间并执行一些算术来获得答案的持续时间。如果你喜欢而不是数据库,你可以将时间存储在会话对象中,虽然我不太了解它的完整性。

答案 5 :(得分:3)

必须在此处使用服务器端时间。我将如何做到这一点:

制作一个AJAX request on document ready来ping服务器。当服务器端代码收到ping时,将服务器端时间存储为会话变量(确保该变量尚不存在)。完成测验后,再次使用服务器端时间并将其与会话变量进行比较以确定其持续时间。删除会话变量。

为什么会这样:

  • 在看到测验
  • 之前,您没有启动计时器
  • 网络延迟被考虑在内,因为定时器在AJAX请求进入之前不会启动(如果它们的连接速度很慢,则AJAX请求会很慢)
  • Ping不是可欺骗的,因为在存储
  • 之前确保会话变量不存在
编辑:我想补充一点,你可以继续保留客户端的时间,并将其包含在最后的帖子中。然后,您可以将其与服务器端计算的时间进行比较。如果他们相当接近,那么你可以相信客户的时间。

答案 6 :(得分:2)

你在原来的问题中问过一堆问题,我只会回答其中一个问题:

  

我是否必须使用像Flash这样的编译器? (让人惊讶。)

是。根据您的标准:1)100%准确,2)没有用户干扰的可能性,您 使用已编译的二进制文件。

不一定要闪存 - 如果想到Flash会让你说“Yikes”,我建议使用java applet。

答案 7 :(得分:2)

- 编辑:

正如下面的ZoFrex所指出的那样,这种解决方案存在一些缺陷。

- 旧:

这是一种方式(但你需要做一些分析)。

发送一系列“问题”供JavaScript解决,同时他们正在玩拼图。以前,我有足够大小的数字N,因此它是:prime1 * prime2的结果。这会强制客户端计算数字(您可以在JavaScript中获取代码)这需要时间(这是分析客户端进入的地方,并发送适当大小的素数[显然,这会打开你的降级攻击,但尽管如此])。

然后,你只需发送500条这些素数问题(或其他类型),让JavaScript在后台解决它们。它将生成一个解决方案列表,当您发送完成的值时,您也会发送此列表。根据提供的答案总数,您可以确定他们花在拼图上的时间。

缺点:

  • 需要进行性能分析以确定各种客户端的功能(以及因此难以解决的问题)
  • 可以降级攻击
  • 稍微复杂
  • JavaScript计算可能会中断一般解谜
  • 可以编写机器人来比JS更快地解决问题

优点:

  • 计算必须才能提交表格
  • 如果正确实施,将阻止所有非平凡的攻击

显然,它是可以攻击的,(所有提议的答案都是),但我认为这是合理的。至少,工作会很有趣:)

但最后,您需要实际安装具有更高安全性的客户端系统。请注意Flash肯定不是这个;反编译是微不足道的。事实上,曾经在澳大利亚进行了一次智商测试,它通过一个在电视上播放的Flash应用程序进行控制。当然,获胜者是计算机程序员,我想知道为什么:P

- 编辑:

OP,此外,我在评论中将其链接到这篇文章,但只是因为你想念它,你对Hashcash感兴趣,这是为了表明客户已经完成了一些金额工作的'。即使我的实施不合适,您也可能会发现对该领域的评论富有成效。

答案 8 :(得分:2)

这是一个棘手的问题,因为它根本无法解决,所以你需要通过权衡来做到最好。在技​​术方面已经提出了几个好点,包括:(a)不要浪费你的时间思考编译到Flash,Windows,Silverlight,JVM或任何实际有用的东西,(b)首先传输加密的真实难题有效载荷然后,由于实际瓶颈单独传输密钥,(c)与人类反应时间相比,即使发送几百字节56k的延迟也可忽略不计。

我没有看到的一件事是:

使用事后审核和跟踪用户。这就是真正的赌场工作方式。据我所知,这是PayPal如何赚钱的重要部分。在这两种情况下,他们不是做很多事前安全,而是密切关注他们玩家的一切,使用大量技术(统计,模式检测等)来标记可疑玩家并进行调查。在赌场和PayPal中,您无法立即获得资金。您必须兑现筹码或等待资金从PayPal系统进入您的真实银行。您的系统应该以相同的方式工作 - 它们实际上至少可以在至少几天内获得金钱(如果您无法建立足够快速的审计系统,则更长时间),给您时间可能会扣留他们的奖金。你有律师,对吗?此外,赌场和PayPal知道你的真实生活身份(处理金钱的必须),这样他们就可以合法地追踪你 - 或者更重要的是,阻止潜在的攻击者,因为他们可以合法地追捕他们。

结合其他提示,这可能足以完全消除作弊行为。

如果你发现它不是,那么你的目标就是不要完全消除作弊行为,而是要将其保持在可接受的水平。有点像99.99%的正常运行时间。是的,正如一张海报所说,即使一个人可以妥协,每个人都被搞砸了,但是通过良好的审计系统,攻击者将无法一直作弊。如果他们幸运并且他们发现在被抓之前不能欺骗超过一次或两次,他们可以骗取1000次,这不会是一个问题,因为很少有人会作弊,任何给定的诚实用户都会有受极少量作弊影响的可能性极低。它将是难以察觉的。如果您有真正的作弊行为会伤害诚实的用户,请尽量让诚实的用户对结果感到满意,其程度与该单个客户的价值不成比例。这样每个人都会对您的安全充满信心。他们知道他们不必担心任何事情。

单靠技术解决方案并不总能解决人们的问题。您有时需要使用人员解决方案。 (该技术可以帮助那些人解决方案更好地工作。)

答案 9 :(得分:1)

对不起,为什么你不能在服务器上使用时间?收到回复的时间将是您用来计算得分的时间。

答案 10 :(得分:1)

正如其他几位人士指出:

  1. 您必须使用服务器时间,因为客户端时间容易受到操纵。
  2. 检查服务器上的时间可能会对网络连接速度较慢的人或距离较远的人造成不利影响。
  3. 问题的答案是在客户端和服务器之间使用类似于NTP使用的协议的时间同步协议。通过协同工作,客户端和服务器确定网络延迟导致的延迟量。然后将其考虑到给每个用户的时间。

    NTP的算法很复杂,并且已经开发了多年。但是下面是一个简单的方法;我认为该协议应该可行,但您可能希望对其进行测试。

    让客户端使用两个连续的HTTP XMLRPC ping来测量往返时间。每个ping返回一个不同的nonce。第二次ping需要第一次ping的nonce,这确保它们是顺序的。拼图时间从客户端发送第二个HTTP ping时开始。服务器为每个请求添加时间戳,并假设拼图在收到第一个请求和第二个请求之间显示为1/2。

    当拼图完成后,客户端再次按照与之前相同的协议再次ping两次。服务器知道它何时收到每个请求并且知道时间增量。现在花费一半时间delta并从收到第二组第一次ping时减去该时间。这可以安全地假设是拼图完成的时间。

答案 11 :(得分:0)

这里有一个非常快速的加密实现

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

它允许在客户端上进行公钥/私钥加密,我认为您可以调整它以加密服务器和客户端浏览器之间的Ajax通信

这里有一个详细的解释,您可以根据自己的需要进行调整 http://crypto.stanford.edu/sjcl/#usage

答案 12 :(得分:0)

只是一个简单的想法:为什么不使用iFrame来包含游戏和它的javascripts,让它们驻留在运行服务器端实现的服务器上。然后,任何ajax请求都应该由与服务器端IP相同的IP发送,这将解决识别源的问题。当然,你必须采取进一步的措施,但已经对你的“客户”方面的要求获得了很大的信心。请记住windowsLive服务登录以及更多类似于基于javascript和iFrames的使用并且被认为足够安全。

答案 13 :(得分:0)

我认为没有一个完美的解决方案。这是一个替代方案,使骗子更难,但同时一个不幸的诚实解决者可能会失败。

根据每个用户与您网站的其他互动,从每个特定设备/位置/其他组合中获取许多往返时间测量样本。您还将为整个人口进行这些测量。当ISP的解析器(随机主机名和您托管该域的权威DNS服务器)发生特定DNS查找时,您也可能非常微妙地获取时间戳。

完成此操作后,在服务器端执行所有测量(返回到用户的难题,收到解决方案),并根据以前的观察结果减去网络时间。

请注意,即使在其他解决方案中,您也会遇到影响时序的服务器负载,客户端负载(慢速处理器等)等。

确保您在拼图提交页面上拥有XSRF保护:)

答案 14 :(得分:-4)

我这样做的方式是当服务器将谜题发送到客户端时,当前时间存储在会话中。这确保了在拼图发送后立即开始计时。拼图完成后,并发送到服务器以检查拼图是否正确完成,服务器再次检查时间并进行比较。

显然,较慢的互联网连接会使这个时间变得更大,但你无能为力。