这是网络游戏和竞赛的经典问题。您的 Flash 代码与用户一起决定游戏的分数。但用户不受信任,Flash 代码在用户的计算机上运行。你是索尔。您无法阻止攻击者伪造高分:
对您的系统最简单的攻击是通过代理运行游戏的 HTTP 流量,捕获高分保存,并以更高的分数重播。
您可以尝试通过将每个高分保存绑定到单个游戏实例来阻止此攻击,例如通过在游戏启动时向客户端发送加密令牌,这可能如下所示:
hex-encoding( AES(secret-key-stored-only-on-server, timestamp, user-id, random-number))
(您也可以使用会话 cookie 来达到同样的效果)。
游戏代码通过高分保存将此令牌回显到服务器。但攻击者仍然可以再次启动游戏,获得一个令牌,然后立即将该令牌粘贴到重放的高分存档中。
因此,接下来您不仅要提供令牌或会话 cookie,还要提供高分加密会话密钥。这将是一个 128 位 AES 密钥,它本身使用一个硬编码到 Flash 游戏中的密钥进行加密:
hex-encoding( AES(key-hardcoded-in-flash-game, random-128-bit-key))
现在,在游戏发布高分之前,它会解密高分加密会话密钥,它可以这样做,因为您将高分加密会话密钥解密密钥硬编码到 Flash 二进制文件中。您使用此解密密钥以及高分的 SHA1 哈希来加密高分:
hex-encoding( AES(random-128-bit-key-from-above, high-score, SHA1(high-score)))
服务器上的 PHP 代码检查令牌以确保请求来自有效的游戏实例,然后解密加密的高分,检查以确保高分与高分的 SHA1 匹配(如果您跳过此步骤,解密只会产生随机的,可能非常高的高分)。
因此,现在攻击者反编译了您的 Flash 代码并迅速找到了 AES 代码,它像大拇指一样突出,尽管即使它没有,它也会在 15 分钟内通过内存搜索和跟踪器(“我知道我这个游戏的分数是 666,所以让我们在内存中找到 666,然后捕捉任何触及该值的操作 --- 哦,看,高分加密代码!”)。使用会话密钥,攻击者甚至不必运行 Flash 代码;她抓住一个游戏启动令牌和一个会话密钥,并可以发回任意高分。
您现在正处于大多数开发人员刚刚放弃的地步——通过以下方式与攻击者相处几个月:
使用 XOR 操作加扰 AES 密钥
用计算密钥的函数替换密钥字节数组
在整个二进制文件中散布假密钥加密和高分帖子。
这主要是浪费时间。不用说,SSL 也帮不了你。当两个 SSL 端点之一是邪恶的时,SSL 无法保护您。
以下是一些实际上可以减少高分欺诈的事情:
需要登录才能玩游戏,让登录生成会话 cookie,并且不允许在同一会话上启动多个未完成的游戏,或同一用户的多个并发会话。
拒绝持续时间少于所玩过的最短真实游戏的游戏会话的高分(对于更复杂的方法,请尝试“隔离”持续时间低于平均游戏持续时间 2 个标准差的游戏会话的高分)。确保您在服务器端跟踪游戏持续时间。
拒绝或隔离只玩过一次或两次游戏的登录名的高分,这样攻击者就必须为他们创建的每个登录名生成看起来合理的游戏玩法的“书面记录”。
游戏过程中的“心跳”得分,以便您的服务器在一次游戏的生命周期内看到得分增长。拒绝不遵循合理分数曲线的高分(例如,从 0 跳到 999999)。
游戏过程中的“快照”游戏状态(例如,弹药数量、关卡中的位置等),您可以稍后将其与记录的临时分数进行核对。您甚至不必从一开始就检测此数据中的异常情况;你只需要收集它,然后如果事情看起来可疑,你可以回去分析它。
禁用任何未通过您的一项安全检查的用户的帐户(例如,通过提交未通过验证的加密高分)。
请记住,您只是在这里阻止高分欺诈。没有什么可以阻止如果。如果你的游戏中有钱,那么有人会打败你想出的任何系统。目标不是阻止这种攻击;这是为了让攻击变得更昂贵,而不是仅仅在游戏中表现出色并击败它。