安全性:此身份验证/加密方案有多脆弱?

时间:2011-02-16 10:16:54

标签: security authentication encryption cryptography encryption-symmetric

我有一个客户端 - 服务器游戏,客户端连接到服务器并在游戏期间保持连接(大约5-60分钟)。

我希望新客户能够安全注册,并允许现有客户端进行身份验证,而无需担心会泄露登录凭据。

问题在于,出于性能原因,最好在游戏会话中坚持使用像RC4这样简单而廉价的加密,但对称密钥并不能轻松确保注册程序的安全。

因为无论如何我都想保留一个单独的登录服务器,我的想法是这样的:

  1. 客户端使用凭据(或注册信息)向登录服务器发送HTTPS请求
  2. 登录服务器收集用户信息,并生成临时RC4会话加密密钥
  3. 用户信息+ RC4会话+时间戳+摘要(我可以依赖两个服务器在时间上同步)与秘密对称密钥,在游戏服务器和登录服务器之间共享。
  4. 将游戏服务器的打包数据+ RC4会话加密密钥+ IP地址作为对客户端的HTTPS请求的回复发送。
  5. 客户端打开与游戏服务器的连接,发送初始未加密的hello消息,并将加密的用户信息作为有效负载。
  6. 游戏服务器解包(3)中打包的数据。它现在知道用户和它应该使用的RC4加密密钥。
  7. 如果时间戳指示登录凭据已过期,则会向客户端返回错误(然后客户端将检索新信息)。如果无法使用摘要验证解密的用户数据,则返回不同的错误。
  8. 如果一切正常,服务器会发送未加密的LOGIN_OK,并启动RC4加密通信。
  9. 可能的安全问题:

    • 游戏服务器100%信任它已解密的用户信息。这使得服务器完全分离,这很好,但如果密钥被泄露,用户可能会完全伪造他们的用户信息。通过旋转这些键可以稍微减轻这种情况,以便每天或每月都有一个新密钥。游戏和登录服务器都可以从管理其密钥的第三台服务器获得。从以下情况来看可能有点过分:a)如果在服务器上公开源代码的情况下,可以使用新密钥重新启动它们b)足够好的密钥+加密应该使暴力攻击变得困难(算法建议) ?)

    • RC4不是最安全的算法,但我确保丢弃前512个字节左右,并且每个密钥仅在有限的时间内有效,例如: 24小时。

    • 从我看到的内容中看起来并不容易受到影响:SSL保护RC4会话密钥,在(5)中发送到游戏服务器的RC4会话密钥也被加密。所有可能的是DoS并使用户再次请求密钥。如果(2)中的数据被缓存直到它过期,则不应该创建新数据包。

    • 可以通过向密钥添加随机位来改进(3)中的加密。这些随机比特与加密分组一起发送,并在(5)中呈现给游戏服务器。在(6)中,游戏服务器将那些随机位添加到他的密钥并使用结果来解密数据。这种方式和攻击者无法看到打包数据何时发生变化。

    我有什么漏洞可以忽略吗?

    创建的有效负载摘要:

    • 客户端登录凭据(受SSL保护),发送到登录服务器
    • 用户信息+时间戳+临时游戏服务器会话密钥+摘要由登录服务器使用与游戏服务器共享的密钥加密,提供给客户端 - 无需修改 - 将其传递给游戏服务器。应该是脾气暴躁的,因为:a)客户端不知道密钥b)有时间戳以避免重新发送相同的数据c)摘要以验证内容是否被正确加密
    • 登录服务器与加密的有效负载一起发送给客户端的临时游戏服务器会话密钥。受SSL保护。
    • 客户端游戏服务器登录数据包,由登录服务器收到的加密数据包组成。

    加密密钥摘要:

    • 临时游戏服务器会话密钥:由登录服务器为加密的游戏服务器随机生成< - >客户沟通。由登录服务器生成,提供给客户端和游戏服务器。
    • 秘密用户信息加密密钥。在游戏服务器和登录服务器之间共享,使用将用户信息传递给游戏服务器,客户端作为信使。客户不拥有此密钥。

5 个答案:

答案 0 :(得分:2)

首先,我不会使用RC4。有更快和更安全的流密码,所以如果你控制客户端和服务器,那么你可能比RC4做得更好。丢弃只有512个字节对​​于Fluhrer,Mantin和Shamir攻击来说可能还不够,但即使你丢弃了更多的字节,也有Klein的攻击等等。我不知道它是否值得这么麻烦。

其次,确保您生成的密钥是随机的。我知道这似乎很明显但是举个例子看:http://www.debian.org/security/2008/dsa-1571

但真正的问题在于这一部分:“游戏服务器100%信任它已解密的用户信息。这使得服务器完全脱离,这很好,但如果密钥被泄露,用户可能完全伪造他们的用户信息。 “

您必须假设用户知道密钥。他的游戏客户端必须知道密钥才能与服务器通信。如果用户可以使用他的真实数据通过ssl登录,获取流密码的密钥,然后将他想要的任何信息发送到游戏服务器,那么攻击者所要做的只是获得一个帐户并做他想做的任何事情。 / p>

更改密钥的频率并不重要,因为每次更改密钥时,您都必须将其提供给客户端,这样您也可以在每个字节后更改它,这在此处仍无关紧要。

这比使用的密码或密钥生成更重要,因为如果他刚刚获得密钥,就没有人会强行使用密钥。

你永远不应该相信客户。您应该将客户端数据存储在服务器端并将其与密钥匹配或签署数据并对其进行验证或使用HMAC等,因为如果游戏服务器100%信任用户信息,那么您很快就会遇到问题。几乎没有办法解决它。

答案 1 :(得分:2)

听起来你正在尝试重新发明SSL。为什么不向每个客户端颁发证书(由您自己的root权限签名),并通过SSL连接到游戏服务器,并进行相互身份验证?

答案 2 :(得分:1)

我知道你不能在游戏服务器和客户端之间使用SSL,因为你不想再次通过握手。

乍一看协议似乎没问题。由于您确实需要对称会话密钥来执行任何有意义的操作,因此也没有重放攻击。您可以做的最好的事情是切换到AES也非常快速且非常安全。我非常怀疑通过切换到AES会看到任何性能损失。

您提到的第一个安全问题点也不是真正的问题。对于桌面上的所有客户来说,这是一个问题,例如您的浏览器在通过HTTPS进行通信时遇到同样的问题。所以你真的不必解决它。如果您想要主动监控操作尝试,您的游戏逻辑必须以某种方式寻找不良行为。你不能通过重新键入来解决它。

答案 3 :(得分:1)

我最后也发布在sci.crypt上,我会尝试总结一下建议的更改(据我所知),如果感兴趣的话。

步骤1:客户端使用凭据

向登录服务器发送HTTPS请求

假设凭证采用登录令牌的形式,还要添加一个自我分配的唯一ID。

第3步:用户信息+ RC4会话+时间戳+摘要

使用加密算法确保完整性,而不是明确使用摘要。例如。 AES-GCM或AES-CCM。在步骤1中添加额外的id字段。也将ip添加到游戏服务器。

步骤4:将打包数据+ RC4会话加密密钥+到游戏服务器的IP地址作为回复发送。

给客户端提供时间戳将允许客户端知道会话何时到期。这样可以避免使用过期凭据连接到游戏服务器。

步骤5:客户端打开与游戏服务器的连接,发送初始未加密的hello消息,并将加密的用户信息作为有效负载。

将未加密的步骤1中的自我分配的ID添加到有效负载。

步骤6:游戏服务器解包(3)中打包的数据。它现在知道用户和它应该使用的RC4加密密钥。

游戏服务器将自己的ip与加密的ip匹配,以及使用客户端提供的id加密的id。第一个阻止用户使用相同的凭据转到不同的服务器。

步骤8:如果一切正常,服务器会发送未加密的LOGIN_OK,并启动RC4加密通信。

此时游戏服务器无法确定客户端的身份。使用会话密钥并使用AES-GCM / CCM加密nonce +严格增加会话ID +登录成功状态,并将其发送给客户端。

客户端解密并检查登录成功状态。如果这是真的,则客户端知道游戏服务器知道会话密钥(GCM / CCM验证该分组未被篡改)。客户端返回sid + nonce。

服务器验证sid + nonce与发送的值相同。

最后,客户端和服务器通过使用sid + nonce + salt对会话密钥进行散列来创建新的会话密钥,以便为后续通信创建密钥,以防止可能的重放攻击。

关于RC4

RC4存在漏洞,但由于相当激进的密钥重新安排,它可能足以满足此计划。但是,现代密码更安全,更快,如Snow 2.0或Trivium。

答案 4 :(得分:0)

只需将SSL用于游戏服务器即可。现代密码分析已经导致一些更好的加密算法的一些非常快速的实现。例如,优化的AES实现可以在任何远程现代机器上以高于150MB / s的速度轻松加密。虽然AES很受重视,但我确实有两个弱点,但正确使用后,这些弱点变得微不足道。

我注意到你没有提到你将在客户端和游戏服务器之间使用高级密钥调度算法。如果不这样做会使加密算法的弱点更加严重。 SSL / TLS应该为您进行密钥安排。