Jump to content

  • Log In with Google      Sign In   
  • Create Account


hplus' Authentication for Games


Old topic!
Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.

  • You cannot reply to this topic
13 replies to this topic

#1 Sprangle   Members   -  Reputation: 128

Like
0Likes
Like

Posted 07 September 2013 - 01:23 AM

Hi,

 

I am making a persistent online multi-player game and am currently looking at basic security. I have some questions after reading this:

 

http://www.mindcontrol.org/~hplus/authentication.html

 

This is where I'm at so far:

  • By day I'm a .NET web developer and this project is all in C#.
  • Main game communications happen over UDP, provided by lidgren.
  • Lidgren provides per-message encryption options (Xtea, AES, DES, Triple DES, RC2...).
  • I already have Awesomium integrated into my client to provide the user interface.
  • A web service provides the back end for non-action related UI such as mail and trade. It always runs over HTTPS.
  • The web server and game server share a SQL database.
  • Passwords are salted, hashed (bcrypt), and stored in the database.
  • I plan to also use the secure web service as the login server.

All that is reasonably straight forward and I've done most of it before. My questions are when I try and work through the 'sufficient implementation' provided in hplus' conclusion:

  1. Client connects to game server and transmits the auth ticket. Doesn't this already need to be encrypted to prevent against sniffing on open networks? But the server apparently doesn't retrieve the encryption key till later, so what is stopping someone else grabbing the ticket and connecting as you?
  2. Is there any reason not to start the sequence numbers at 0 given we already using a random encryption key?
  3. Aren't sequence numbers going to be fairly useless with UDP unreliable messages?
  4. What is a suitable hash for ongoing messages once authentication has been established? I assume this is really just a checksum to make sure the data hasn't been tempered with.

Also, would you still give the same advice today? Reading the archives here I get the feeling should really be looking at TCP/TLS instead, if at all possible...

 

Thanks for any help you can offer.


Edited by Sprangle, 07 September 2013 - 02:03 AM.


Sponsor:

#2 Sprangle   Members   -  Reputation: 128

Like
0Likes
Like

Posted 07 September 2013 - 01:41 AM

Just a note on goals: I am mostly interested in protecting players accounts from being stolen etc here. Someone reading information in transit is fine, so long as they can't modify it, spoof it or use it to log themselves in etc.



#3 NLScotty   Members   -  Reputation: 398

Like
1Likes
Like

Posted 07 September 2013 - 03:51 AM

1: That is kinda weird, most systems I have seen, first send some kind of 'handshake' with cryption keys. After that the game packets are send.

 

2/3: you can also use seq numbers in a different way than 1-2-3-4, but make a pattern like 1-42-634-7443, or more look-a-like random numbers. This way it is harder for hackers to crack your software, it will never be impossible ofcourse.

 

4: crc32 are widely used.

 

Anyways, remember that there is always a way that people can crack everything. Make sure that you crypt the password and change this over time. It doesn't protect everything, but it is never bad.


Edited by NLScotty, 07 September 2013 - 03:52 AM.


#4 AllEightUp   Moderators   -  Reputation: 4182

Like
1Likes
Like

Posted 07 September 2013 - 04:31 AM

My first thought is why do it this way at all?  If you have Awesomium integrated already, use a secure https connection to setup the initial login.  The fact that it is tcp should not degrade anything and in fact can help with getting initial nat traversals taken care of and other useful items.  Doing the actual security over UDP to me is just risky, there are so many possible edge cases that making it solid is a fairly scary prospect no matter how much you think you have gotten them all.



#5 Sprangle   Members   -  Reputation: 128

Like
0Likes
Like

Posted 07 September 2013 - 05:09 AM

Perhaps it wasn't clear above... the initial log in is already going through the HTTPS connection as you suggest. My questions were around handing off to the actual gameplay which currently runs over UDP.



#6 Sprangle   Members   -  Reputation: 128

Like
0Likes
Like

Posted 07 September 2013 - 05:13 AM

I have just put together a little prototype version using TCP/TLS which was reasonably straight forward. I'll have a think about ditching UDP altogether and whether it will work for the game.



#7 samoth   Crossbones+   -  Reputation: 4682

Like
1Likes
Like

Posted 07 September 2013 - 10:44 AM

Wheter you need UDP depends on whether you must have information as fast as possible (not in terms of speed/bandwidth, this is identical -- but in terms of latency). If your information is "worthless" after some milliseconds so you could as well throw it away, it is better to use UDP. If a packet is lost, screw it.

Otherwise, TCP is what you want anyway. It works just as well and just as fast, and in some cases "better", but overall it's simpler on the library level. Yes, if packets are lost, TCP will resend and wait for them, but then again, this is just what you want.

 

About your questions on sequence numbers, not having sequence numbers start at zero has two advantages. First, if you encrypt the packet including sequence number, you do not introduce known plaintext, which is an attack vector. Second, if you leave the sequence number unencrypted, you have a much lower likelihood that someone is easily able to guess a believeable number and spoof it. So, in either way it's better not to start at zero, and it doesn't cost anything to do otherwise. Sequence numbers are more important for UDP as they are for TCP, since TCP already has its own sequence number implementation.

 

As for what hash to choose, in principle every simple hash that is inside the encrypted part would do. Or, of course, a MAC. Accidential bit flips due to "line noise" are very unlikely, they're discovered by two layers of hardware and protocol checksums and FEC.

The hash is there to ensure that no malicious tampering has happened. Which means that nobody who doesn't know the key must be able to generate (or verify) one. That's more or less what a MAC is, a key-dependent hash. Of course, you can just use a simple normal hash, append it to the other data, and encrypt everything. Now of course, the question is how long should such a hash be (like, 160 or 256 bits, or 512?). Since there'll be one hash in every packet, and since packets are short-lived, I'd say that 32 bits are plenty. As long as someone cannot successfully forge a packet that will pass by flipping bits in less than a few hundred milliseconds, there's not much they can do (apart from sending you with random garbage, but they can always do that).


Edited by samoth, 07 September 2013 - 10:45 AM.


#8 Sprangle   Members   -  Reputation: 128

Like
0Likes
Like

Posted 07 September 2013 - 02:47 PM

I would call the game's pace moderate, it is not a twitch shooter so latency isn't the most critical. There is however quite a lot of information about the world flowing to the user which is updated regularly. I had gone with UDP so this information can be sent on an unreliable channel and dropped without issue.

 

After looking through all the details I think I'd rather have the simplicity of the secure TCP stream and I'll just have to be extra careful about not flooding it with too much information.

 

Thanks for your thoughts everyone smile.png


Edited by Sprangle, 07 September 2013 - 02:48 PM.


#9 hplus0603   Moderators   -  Reputation: 5156

Like
1Likes
Like

Posted 07 September 2013 - 07:45 PM

  1. Client connects to game server and transmits the auth ticket. Doesn't this already need to be encrypted to prevent against sniffing on open networks? But the server apparently doesn't retrieve the encryption key till later, so what is stopping someone else grabbing the ticket and connecting as you?
  2. Is there any reason not to start the sequence numbers at 0 given we already using a random encryption key?
  3. Aren't sequence numbers going to be fairly useless with UDP unreliable messages?
  4. What is a suitable hash for ongoing messages once authentication has been established? I assume this is really just a checksum to make sure the data hasn't been tempered with.

Also, would you still give the same advice today? Reading the archives here I get the feeling should really be looking at TCP/TLS instead, if at all possible...

 

 

1. Unless the player is playing the game on an open WiFi network, it is actually pretty hard to "tap into" the network connection and sniff the ticket. So, the question is whether your attack vector includes those with physical access to the networking infrastructure. If the ticket is tied to a remote IP address, then even stealing the ticket is not good enough unless you can also steal the IP address. It turns out that modern day use cases like the open WiFi on Starbucks and McDonald's and similar places allow you to do both, though (like Firesheep,) so using transport-level encryption is advisable if you want to protect against that.

 

2. If you have some other way to detect replay attacks or blind data injection, then the sequence number can start at 0 every time.

 

3. Sequence numbers are highly useful for UDP, because they let you know which of your packets make it through, and which ones don't.

 

4. If the goal of the "hash" is to protect against network-level hardware corruption, a crc32 would be fine. If the goal is to protect against a determined attacker with the capability of acting as a man-in-the-middle, then a HMAC with a shared secret and a strong algorithm is needed. A straight hash with a shared secret is not good enough, because the attacker can use hash data extension to inject his own data at the end of the message. HMAC fixes this. Btw; using md5 for the HMAC algorithm would let someone inject data as well, because creating 16 bytes at the end of a packet that achieves the HMAC you want with MD5 is no longer a computationally hard problem. I'd suggest sha-1 for now, for games, although if you're all security-minded, by all means use sha-256. And hope the NSA isn't interested in cheating in your game :-)

 

If you're using TCP, then TLS is a fine transport mechanism, but it does not solve the authentication problem by itself.

If you're prepared to set up unique client certificates for each client, you can do that, though. if you want to go that route, that would be a perfectly fine alternative, as far as I know. (I e: it's likely that self-signed self-issued certificates from an audited code base will be secure; it's also likely that pay-for CAs are by now not considered 100% secure.)

IIRC, you also can't really use UDP with the TLS stack as it uses full-stream in-order CBC.

 

All of which goes to the question: What kind of attacks are you *really* trying to defend against? If your game is a valuable target, it's much easier to install malware on your players' computer, than it is to do a cryptographic attack.

http://xkcd.com/538/


enum Bool { True, False, FileNotFound };

#10 Sprangle   Members   -  Reputation: 128

Like
0Likes
Like

Posted 07 September 2013 - 08:56 PM

Can I turn the last question around and ask which types of attacks I should be defending against? Obviously the game is not a high profile target, but I do have concern for users basic privacy and safety. Is there a generally acceptable level of security (you could say standard or best practice) small indie developers should be aiming at? Some things like protecting passwords in storage and transmission are obviously in.

 

The open wifi issue has been kind of a big deal for us in the web space for a few years so it does interest me, perhaps it is less relevant to PC games where users are more likely to be at home though.

 

Let's say I go with the TCP/TLS option. I currently have the following basic prototype set up:

  • I create a self signed certificate.
  • The server has a copy of the public and private keys, the client has public key only.
  • TCP connection is established, SSL stream layered on top.
  • The server authenticates itself using the certificate.
  • The client checks that the provided certificate matches its copy of the public key, nothing else is accepted.
  • The client submits user name and password to the server which checks against its stored hash etc.
  • (login servers, tickets for easy reconnection etc have been ignored for simplicity).

At this point, can the server reasonably (* see below) just store the client ID against the open connection and assume it is good for the life of the connection? As far as I understand it the SSL stream has negotiated session keys, is doing the sequence, hash checks, encryption etc itself, and no one else should be able to interfere.

 

Thank you for your patience helping me think through all this. Most of my knowledge is about protecting web sites from SSL upwards, so I don't know what I'm doing at this level.

 
* Things that are explicitly outside of this projects scope:
  • NSA, or my local version the GCSB.
  • Criminals with drugs and wrenches.
  • Corrupt CAs, ISPs, network admins etc.
  • Client PCs with 10 IE toolbars installed.
  • Users with the password password.

Edited by Sprangle, 07 September 2013 - 09:08 PM.


#11 Bacterius   Crossbones+   -  Reputation: 8494

Like
1Likes
Like

Posted 08 September 2013 - 04:26 AM


Btw; using md5 for the HMAC algorithm would let someone inject data as well, because creating 16 bytes at the end of a packet that achieves the HMAC you want with MD5 is no longer a computationally hard problem

 

Actually, it still is. Using MD5 with HMAC is at present knowledge absolutely fine from a functional point of view, but it's really not something you would want to do anyway because:

 

A) it's bad for PR, because by now the only reaction you will get from people is "why are you using MD5, it's broken" even though in this particular instance none of its effective weaknesses matter

 

B) you can possibly get better performance using a more modern algorithm with less overhead when fingerprinting small messages - such as network packets - repeatedly with the same key (the SHA-3 finalists are pretty good at it since they have built-in HMAC functionality which aims to optimize this kind of processing, but they aren't standardized yet so it's probably best to go with SHA-256 at the moment)

 

C) eventually it will no longer be secure, as attacks only get better

 

So to conclude, HMAC does not rely on collision resistance of the underlying hash function, therefore, as paradoxal as it may seem, using it with MD5 is currently "as secure" as using it with SHA-1 from a technical point of view (ignoring the difference in fingerprint length - 128 bits is enough anyway). But that doesn't mean you should do it.

 

Either way, you need to build a threat model for your application first. Any work done prior to the assessment of what you are trying to protect against is misguided.


The slowsort algorithm is a perfect illustration of the multiply and surrender paradigm, which is perhaps the single most important paradigm in the development of reluctant algorithms. The basic multiply and surrender strategy consists in replacing the problem at hand by two or more subproblems, each slightly simpler than the original, and continue multiplying subproblems and subsubproblems recursively in this fashion as long as possible. At some point the subproblems will all become so simple that their solution can no longer be postponed, and we will have to surrender. Experience shows that, in most cases, by the time this point is reached the total work will be substantially higher than what could have been wasted by a more direct approach.

 

- Pessimal Algorithms and Simplexity Analysis


#12 hplus0603   Moderators   -  Reputation: 5156

Like
1Likes
Like

Posted 08 September 2013 - 01:25 PM

There are two main concerns in the model you suggest:

 

1) How do I prevent users-on-open-WiFi from having their sessions stolen?

2) How do I make sure that a connection that comes back to a different server is in fact the user it claims to be?

 

Implementing the "authentication-for-games" mechanism (which can be summariezed as "a basic ticket mechanism a la Kerberos") on top of TCP/TLS will work just fine for these vectors.

 

So, from clients' point of view:

1) connect with TLS, provide name & password; receive ticket with some lifetime

2) each new connection, still use TLS, provide ticket as proof-of-identity-and-authorization

 

The benefit of using the ticket instead of just keeping name & password around in the client is that:

a) wiping the password in RAM after sending it is somewhat more secure against accidental disclosure on the client machine

b) each server that gets the ticket only needs a copy of the server-side secret, not actually re-do the user database lookups

 

For long-lived TCP connections, b) isn't as important (but a may still be); for UDP connections, b) is a real win!


enum Bool { True, False, FileNotFound };

#13 Sprangle   Members   -  Reputation: 128

Like
0Likes
Like

Posted 08 September 2013 - 03:08 PM

/me nods.

 

OK I'm taking the TCP model from above and adding auth tickets so we can wipe passwords in the client and still handle quick reconnects (connection dropped, server switches etc).

 

I notice this ends up being quite similar to the forms authentication set up in ASP.NET which is probably a good sign. Given they already have the infrastructure for generating and verifying tickets using a cluster secret, expirations etc I'll have to look at whether borrowing some of that makes sense.



#14 hplus0603   Moderators   -  Reputation: 5156

Like
1Likes
Like

Posted 09 September 2013 - 09:50 AM

I'll have to look at whether borrowing some of that makes sense


If there exists working, tested, code, on the platform/language you're already using, I would assume doing so makes a lot of sense :-)
enum Bool { True, False, FileNotFound };




Old topic!
Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.



PARTNERS