开发者

Security: How vulnerable is this authentication/encryption scheme?

开发者 https://www.devze.com 2023-02-11 13:47 出处:网络
I have a client-server game, where the client connects to a server and stays connected during the game (approx 5-60 min).

I have a client-server game, where the client connects to a server and stays connected during the game (approx 5-60 min).

I want new clients to be able to register securely, as well as allowing existing clients to authenticate with no worries that the login credentials are exposed.

The thing is that for performance reasons it would be best to stick with a simple and cheap encryption like RC4 for the game session, but a symmetric key does not make it easy to secure the registration procedure.

Since I will want to keep a separate login server anyway, my idea is like this:

  1. Client sends a HTTPS request to the login server with credentials (or registration information)
  2. The login server collects the user information, and generates a temporary RC4 session encryption key
  3. The user information + RC4 session + timestamp + digest (I can rely on both servers to be synchronized timewise) with a secret symmetric key, shared between game server and login server.
  4. The packaged data + RC4 session encryption key + ip address to the game server is sent as a reply to the HTTPS request to the client.
  5. The client opens a connection to the game server, sends an initial unencrypted hello message with the encrypted user information as a payload.
  6. The game server unpacks the data packaged in (3). It now knows the user and the RC4 encryption key it is supposed to use.
  7. If the timestamp indicates that the login credentials has expired, an error is returned to the client (who is then to retrieve new information). If the decrypted user data cannot be verified with the digest a different error is returned.
  8. If everything checks ok, the server sends an unencrypted LOGIN_OK, and the RC4 encrypted communication starts.

Possible security concerns:

  • The game server 100% trusts the user info it has decrypted. This makes the servers completely decoupled which is nice, but if the key is compromised, users could completely fake their user info. This could be alleviated somewhat by rotating these keys, so that every day or month has a new key. Both game and login servers could get this from a third server that manages their keys. It might be overkill since: a) in case of a break-in where source code is exposed on the servers, they can be restarted with a new key b) a good enough key + encryption should make brute force attacks hard (suggestions on algorithm?)

  • RC4 isn't the most secure algorithm, but I make sure to throw away the first 512 bytes or so and each key is only valid for a limited time, e.g. 24h.

  • Doesn't seem susceptible to man-in-the middle from what I can see: SSL secures the RC4 session key, in (5) the RC4 session key sent to the game server is encrypted as well. All that is possible is DoS and to cause the user request a key again. If the data in (2) is cached until it expires, this should not create a new packet.

  • The encryption in (3) could be improved by adding random bits to the key. Those random bits are sent together with the encrypted packet, and presented to the game server in (5). In (6) the game server adds those random bits to his key and uses the result to decrypt the data. This way and attacker cannot see when the packed data changes.

Are there any vulnerabilities I'm overlooking here?

A summary of payloads created:

  • Client login-credentials (protected by SSL), sent to login server
  • User info + timestamp + temporary game server session key + digest encrypted by login server using a secret key shared with game server, given to the client that - without modifying it - passes it to the game server. Ought to be temper resistant because: a) client does not know the secret key b) has timestamp to avoid resending same data c) digest to verify content was encrypted correctly
  • temporary game server session key sent by the login server to the client together with the encrypted payload. Protected by SSL.
  • Client game server login packet, consists of encrypted packet received by login server.

A summary of encryption keys:

    开发者_JS百科
  • Temporary game server session key: randomly generated by login server for encrypted game server <-> client communication. Generated by login server, given to client and game server.
  • Secret user info encryption key. Shared between game server and login server, used pass user info to game server with client as messenger. Client does not possess this key.


First of all I wouldn't use RC4. There are both faster and more secure stream ciphers around so if you control both client and server then you can probably do better than RC4. Discarding only 512 bytes may not be enough for the Fluhrer, Mantin and Shamir attack, but even if you discard more bytes there's also the Klein's attack etc. I don't know if it's worth the trouble.

Second, make sure that the keys you generate are random. I know it seems obvious but for an example see: http://www.debian.org/security/2008/dsa-1571

But the real problem is this part: "The game server 100% trusts the user info it has decrypted. This makes the servers completely decoupled which is nice, but if the key is compromised, users could completely fake their user info."

You have to assume that the user knows the key. His game client has to know the key so it can communicate with the server. If the user can use his real data to log in via ssl, get a key for stream cipher and then send whatever info he wants to the game server then all the attacker has to do is just get an account and do whatever he wants.

It doesn't matter how often you change the key because every time you change it you have to still give it to the client so you might as well change it after every byte and it still wouldn't matter here.

This is more important than the cipher used or the key generation because no one will brute force the key if he just gets it.

You should never trust the client. You should store the client data on the server side and match it with the key or sign the data and verify it or use HMAC etc. because if the game server 100% trusts the user info then you will have problems sooner o later. There is pretty much no way around it.


It sounds like you're trying to reinvent SSL. Why not issue each client a certificate (signed by your own root authority), and have them connect to the game server over SSL, with mutual authentication?


I understand you cannot use SSL between the game server and the client as you don't want to go through the handshake again.

The protocol seems ok from a first glance. There is no replay attack also as you really need the symmetric session key to do anything meaningful. The best thing you can do is switch to AES is also very fast and very secure. I highly doubt you will see any performance hit by switching to AES.

Also the first security concern bullet point you mentioned is not really a concern. Well it is a concern for all clients on the desktop, for example your browser has the same problem talking over HTTPS. So you don't really have to solve it. Your game logic somehow has to look for bad behavior if you want to actively monitor manipulation attempts. You cannot solve it by re-keying.


I ended up also posting on sci.crypt and I'll try to summarize the suggested changes (as far as I understand them) below in case it might be of interest.

Step 1: Client sends a HTTPS request to the login server with credentials

Assuming that the credentials take the form of a login token, also add a self-assigned unique id.

Step 3: The user information + RC4 session + timestamp + digest

Use an encryption algorithm that ensures integrity, instead of using a digest explicitly. E.g. AES-GCM or AES-CCM. Add the extra id field in step 1. Add the ip to the game server as well.

Step 4: The packaged data + RC4 session encryption key + ip address to the game server is sent as a reply.

Giving the timestamp to the client will allow the client to know when the session has expired. This avoids unnecessary connects to the game server with expired credentials.

Step 5: The client opens a connection to the game server, sends an initial unencrypted hello message with the encrypted user information as a payload.

Add the self-assigned id in step 1 unencrypted to the payload.

Step 6: The game server unpacks the data packaged in (3). It now knows the user and the RC4 encryption key it is supposed to use.

The game server matches both its own ip with the encrypted ip, as well as the encrypted id with the id given by the client. The first prevents the user from going to a different server with the same credentials.

Step 8: If everything checks ok, the server sends an unencrypted LOGIN_OK, and the RC4 encrypted communication starts.

At this point the game server cannot be sure of the client's identity. Use the session key and encrypt nonce + strictly increasing session id + login success state using AES-GCM/CCM and send it to the client.

The client decrypts and checks the login success state. If this is true, then the client knows that the game server knows the session key (GCM/CCM verifies that the packet has not been tampered with). The client returns sid + nonce.

The server verifies sid + nonce is the same as the values sent.

Finally the client and server creates new session keys by hash-ing the session key with sid + nonce + salt to create the key for the consequent communication, to prevent a possible replay attack.

Regarding RC4

There are vulnerabilities in RC4, but it probably would suffice for this scheme because of the rather aggressive key rescheduling. However, there are modern ciphers which are more secure and faster, such as Snow 2.0 or Trivium.


Just use SSL to the game server. Modern cryptanalysis has resulted in a few very fast implementations of some of the better encryption algorithms. For example, well optimized AES implementations can easily encrypt at better than 150MB/s on any remotely modern machine. Also while AES is held with high regard, it does have two weaknesses that I know of, but when used correctly those weaknesses become insignificant.

I noticed that you failed to mention that you would be using an advanced key scheduling algorithm between the client and the game server. Failing to do so would make the weaknesses of the encryption algorithm much more severe. SSL/TLS should do the key scheduling for you.

0

精彩评论

暂无评论...
验证码 换一张
取 消