这是互联网游戏和竞赛中的一个经典问题。你的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无法保护您。
以下是一些真正可以减少高分欺诈的方法:
拒绝或隔离那些只玩过一两次游戏的登录帐户的高分记录,这样攻击者就必须为每个登录创建一个看起来合理的游戏过程“纸质记录”。
在游戏过程中进行“心跳”得分(例如,在一次游戏过程中查看得分增长情况),因此您的服务器可以拒绝不遵循合理得分曲线(例如从0跳到999999)的高分记录。
在游戏过程中捕捉“快照”游戏状态(例如弹药量、关卡位置等),以便稍后与记录的中间得分进行对比。即使一开始没有检测这些数据的异常方法,您只需收集它们,如果出现问题,则可以回头分析它们。
禁用任何未通过安全检查的用户帐户(例如提交未经验证的加密高分记录)。
请记住,这里只是在阻止高分欺诈。你无法完全防范它。如果你的游戏中涉及到金钱,有人将会打败你设计出的任何系统。目标不是停止这种攻击,而是让攻击的代价大于仅仅成为游戏高手并赢得胜利。