如何安全地从客户端更新游戏分数到服务器数据库?Javascript

14
我有一个完全在客户端运行的游戏,除了下载游戏的初始脚本之外,没有与服务器的任何交互。无论如何,在游戏结束时,我希望客户端将分数发送回服务器数据库并更新。现在我已经接受这样一个事实:我无法阻止黑客篡改并发送修改后的分数。但是我想知道,在哪个层面上我可以修改整个过程,以使黑客操纵正在发送的数据变得非常困难。我当然不想让分数以明文形式从客户端机器发送,并且我也不想让我的服务器执行复杂的解密算法。因此,最好的方法是什么,可以实现相当大的安全性,以防止任何人都可以轻而易举地破解分数... 我希望有人能提供一种好的方法,我可以继续开发... :)谢谢
所以,我的理想结果应该是 - > 由不可信任的一方(玩家)进行计算(分数),得出可信任的结果!
编辑-
有人告诉我一些关于隐藏数据在图片get请求中的内容。就像,我在Canvas(HTML5)上实现了这个游戏。所以他要求我在游戏结束时从我的服务器获取一个Game Over图像,并且请求应包含散列分数。我没有完全理解整个过程,但如果你能解释一下,我会非常高兴! :)
coda ^ 所以你可以很好地掩盖请求。 shouvik 怎么做?! coda ^ 您可以组合要提交的校验和。就像 12312312a12313a232 是您包含得分的md5。将一个资产带入画布中,例如 coda ^ server.com/images/md5_hash_of_score/congratulations.png coda ^ 它可以通过htaccess在服务器端重新编写。

这个问题与https://dev59.com/IkrSa4cB1Zd3GeqPZdG-基本相同。 - Quentin
@David,不,这很不一样!他一个人玩我的游戏时,我没有问题让他试图搞砸它。所以让他想干什么就干什么吧。如果他搞乱了得分,我在服务器上有一个自适应算法,检查得分是否可以合理实现,如果不能,用户将被禁止!但我不希望它太容易,比如只是修改ajax post... - Shouvik
5个回答

6

您似乎已经知道这一点,但要强调的是:您无法阻止其他人这样做;您只能尽可能地增加难度!

假设您当前提交的分数如下:

/submit_score.php?score=5

有人在Firebug中观察时很容易区分得分提交的位置并进行更改。文件submit_score.php和参数名称都暴露了它。得分是一个容易识别的整数。

  1. 改变终点:/interaction.php?score=5
  2. 改变参数名称:/interaction.php?a=5

这样用户就会更难理解发生了什么。

现在你可以让得分更难(再次强调,更难而不是不可能)更改。首先,你可以加密它(显然之后需要解密)。

  1. Base 64编码。
  2. 数字->字母(1=a,2=b等)。
  3. 颠倒得分表示顺序。

你想怎么做就怎么做。因此,现在你有了interaction.php?a=e

下一步可以将得分与其他内容一起哈希。发送哈希和得分,然后在服务器上重新计算。例如,使用随机字符串对得分进行md5()哈希,然后在请求中发送得分(已编码)、字符串和哈希:

/interaction.php?a=e&str=abcde&hash=123456789abcefbc

当请求到达服务器时,请执行以下操作:
if (md5($_GET['a'] . $_GET['str']) !== $_GET['hash']) exit;

显然,人们可以(相对容易地)查看您的JavaScript代码,并了解其中的情况;因此,请让他们变得更加困难。最小化和混淆代码。

如果你让某个人感到足够困难,他们会尝试理解你的JavaScript,尝试使用Firebug,不理解发生了什么,并且不会麻烦;为了获取一些额外的游戏分数。


谢谢你的回答。是的,我对你提到的东西非常了解。 :) 我显然会混淆代码,使其无法被识别 :D 但我更感兴趣的是知道一种基本的躲猫猫模式,以至于让玩计分机制的人感到非常恼怒,甚至变得不可行。我在这里发布这个问题,希望能够从这里积累各种想法,然后将它们混合起来,烹制出自己的答案,尽管@ypercube给出的论文链接似乎会对我有很大帮助:) 再次感谢! - Shouvik

2

使用类似OAuth的方式来授权客户端到服务器的请求。请求头包含一个令牌,该令牌与请求体匹配。如果这两者不匹配,则丢弃请求。无需在服务器端解密,而是加密请求体并检查服务器端获得的结果和令牌是否匹配,以确定请求体是否被修改。


1
“现在我已经接受了这个事实,地球上没有办法让我隐藏这个并将分数不变地发送给黑客。”
“哦,是有的!”
您可以使用RSA或任何其他公钥加密方法(也称为非对称加密)。
为服务器创建一组(公共和私有)密钥。 让您的客户端代码包括您的服务器的公钥。
在游戏结束时,客户端代码使用此密钥加密得分,并将两者(明文得分和加密得分)发送到服务器。
服务器解密并检查明文得分和解密得分是否相同。 如果是,则接受得分。 如果不是,则拒绝(中间存在黑客或网络错误)。
-------更新-----------更正--------------
正如Ambrosia所指出的那样,我的方法在这种攻击中完全失败了。
实际上,您想要的是从不受信任的方(玩家)进行计算(得分)获得可信结果。没有简单的方法来实现这一点。

看这个:http://coltrane.wiwi.hu-berlin.de/~fis/texts/2003-profit-untrust.pdf

还有这个:http://www.cse.psu.edu/~snarayan/publications/securecomputation.pdf

以及这个(需要订阅ACM数字图书馆):http://portal.acm.org/citation.cfm?id=643477.643479


我不需要支付钱来使用RSA吗?我以为你需要购买那些密钥? - Shouvik
3
一个人仍然可以查看公钥并生成自己的加密版本的分数,然后将其与明文分数一起发送,这将完全匹配,对吗? 可以考虑使用代码映射得分的方法,例如南瓜= 1分,西红柿= 2分,等等,只有服务器拥有这些映射来确定得分。当然,如果您仍然向用户显示分数,并且他们可以在firebug中看到ajax,则可以确定哪些单词(或代码)映射到哪些值。 - AmbrosiaDevelopments
安博罗斯,再次思考,是的,你是正确的。我必须修改我的答案,它根本无法防止这种攻击。 - ypercubeᵀᴹ
@ypercube - Ambrosia 是对的!黑客可以修改我输入到加密算法中的值!如果攻击如此简单,为什么要费那么大劲去进行如此复杂的过程呢...?? - Shouvik
RSA比其他算法更安全,因为私钥只在一个人手中!但它仍然严重依赖于接收到的数据的真实性以及您是否信任数据提供者!在这种情况下,我不信任...!!! - Shouvik
显示剩余10条评论

0
你能使用ajax将分数(和任何标识符)发送到服务器吗?除非他们打开了类似firebug的工具,否则他们不会看到它发生。
var url = '/savescores.asp?userID=fredsmith&score=1098';
createRequest();
request.open('GET', url, true);
etc

是的,我明白了ajax部分。但我假设他们已经打开了控制台。只需要在更新得分时从控制台更改URL参数,所以我不希望这变得太容易让黑客入侵。也许可以更复杂一些,比如使用某种不太过程密集的操纵策略,基本上是可以由服务器轻松解决的初级难题。 - Shouvik

0

让客户端通过SSL(https)向您发送凭据(或某种会话信息,以防您没有登录凭据)。这样,您就可以同时进行身份验证和完整性控制。对于服务器和客户端来说,非常简单且极其轻量级。


也许我错过了添加,但最终这将会出现在Facebook上 :) - Shouvik
他们得到了这个地址https://ssl.facebook.com/,但我对此毫无经验。如果SSL在Facebook上不起作用,我不会感到惊讶。这反过来让我非常生气,因为他们传输所有的个人信息却从不关心保护它,真是气死我了! - Ilya Saunkin
我实际上是在谈论玩家本身。把自己放在那个位置上:你试图向服务器发送一个随机分数,但你意识到有一个你不知道的会话令牌,所以你基本上要做的就是拦截消息,修改它并发送。 - Ilya Saunkin
@Elijah 对不起,我不明白! =S 你说的会话令牌是什么意思?我没有在我的应用程序中添加任何内容,如果有会话令牌,客户端不应该能够访问它,因为没有中介服务器将客户端数据转发给我。客户端机器直接将其发送到我的服务器... =/ - Shouvik
如果你能给我一些发送者攻击的文档,那会很有帮助。以前没听说过这个,谷歌也没有出现有趣的结果... - Shouvik
显示剩余4条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接