views:

1883

answers:

8

...I have read a few threads on here that have discussed various methods and was just looking for some feedback on a proposed solution we came up with. In one of the threads a comment was posted recommending a public/private key which sounded great, this is what we were thinking...

Client Side - 1. Key is stored inside of Flash swf which is encrypted using 3rd party tool. 2. High score is hashed along with high-score value (EX: md5 ('ourSecretKey' + 200)) 3. This value is sent via AMF to a PHP script on the server, along with the high-score (200)

Server Side - 1. Server receives data and hashes the passed high-score (200) + secret key ('ourSecretKey' stored on the server as well as in Flash) and checks against the passed hash if the value is a match it allows the high-score to be entered, else FAIL.

I know this isn't a foolproof solution but would this be acceptable? I mean would this be sufficient security on a high-score form for a simple online Flash game? Thoughts?

Thank you in advance!

+4  A: 

For a ridiculously short value ( Ie: values < 64 characters ), MD5 as a hash becomes ineffective due to rainbow table attacks, and as the value you're sending will be shared over the wire, all they have to do is brute force the shared secret ( and they have a known product to work with )

As such, thats not public key private key. its mererly shared secret.

Also, keep in mind this shared secret will be in your flash file you send to the user, which these days and be trivially disassembled and then your "secret" is not a secret any more.

You want a more challenge-response mechanism with proper crypto signing, where a new sign key is assigned for every game from the server, and multiple scores cannot be submitted with the same sign key. ( For extra protection ;) )

  1. User starts game. Sign key is requested. ( the sign key is produced from another key which they cant access ).
  2. Score is signed with sign key, and then sent
  3. You verify the value of the sign with the key you sent them.
  4. You discard the sign key you sent them.

However, you still have the problem where you have no way to prevent the actual scoring system being tampered with. Somebody smart enough could just reverse engineer your SWF object and inject new code that just sets the score to their chosen value.

Kent Fredric
+1  A: 

The answer to your question is, it depends. It depends mainly of the estimated popularity of your game.

From a security perspective, your solution is about as secure as sending the highscore in cleartext. What you're doing here is called security by obscurity, which, according to who you listen to may have its benefits in some cases. In this case it's probably that Joe the average user would not likely be able to crack it himself. For anyone with some l33t h4xxor skillz you might as well send it all in cleartext. If all you want is to stop Joe, then it's probably enough, at least until someone creates a fake client for Joe to download (which depending on the popularity of your game could take anything from a couple of days to never (or faster if it's WoW)).

A better solution is the one given by @Kent Fredric. However as it says it doesn't solve the problem of someone creating a fake client. A solution to that might be something like this:

  1. Give every action a player can perform an id.
  2. Store every action the player performs in a list of ids.
  3. When the game is over hash the score, the list of actions and encrypt it with the public key received from the server. (see Kent Fredric's post for details on this)
  4. Send the encrypted hash (more commonly called digital signature) to the server together with the score and the list of actions performed.
  5. Let the server "play" the game according to the actions in the list.
  6. Verify that the same score was attained.
  7. Verify that the digital signature is correct.
  8. Update server highscore list.

This will guarantee two things:

  1. The score comes from the correct client.
  2. The score is correct in regards to the game played.

But there's still one serious flaw to this scheme. There's no way of knowing that the game was in fact actually played. If the client is compromised, the list could just be a prefab of a "prefect game" that is sent to the server. It's not possible to directly tamper with the scoring system, but with enough effort someone will most likely be able to create a list of actions that comprise a "perfect game".

However it gives a little bit stronger guarantee than just using the solution in Kent Fredric's post. To solve the whole problem would mean that you must validate the client somehow. This is very difficult since most ways of doing this are easily circumvented.

Finally I just had to comment on your choice of hash algorithm: MD5 is a great hash algorithm for those still living in the nineties. For the rest of us I recommend SHA-2 or at least SHA-1.

Andreas Magnusson
+1  A: 

Blockquote Finally I just had to comment on your choice of hash algorithm: MD5 is a great hash algorithm for those still living in the nineties. For the rest of us I recommend SHA-2 or at least SHA-1.

Bah I knew I should have mentioned SHA instead :)

If I do use something like a swf encrypter application to encrypt the swf code wouldn't that at least make it quite a bit more difficult to get at the key stored in Flash? I would think that without that key (or at least without getting to it easily) it would be a huge pain to figure out what was being used to generate the hash that is sent off to the server.

Something like this is what I was thinking of: SWF Encrypt

Thank you all again for these answers, this is amazingly helpful. Oh and this will just be a simple Flash game sent out by a client to customers, something fun to pass time at work over the holidays.

A: 

If the distribution of your game is limited and there's no real money/bounty involved for the players to win, your original scheme is probably enough.

Using SWF Encrypt will likely make it a little bit more difficult to extract the key, and it could be a good tool to use even in a more advanced system as well. But if you have a real public/private key scheme (e.g. RSA), it's really a moot point since the public key isn't a secret, it's not supposed to be. Still to prevent most people from editing the code and tamper with the scoring system, SWF Encrypt is probably a good enough choice.


Just to make you a bit more paranoid I wrote the following as well:

The problem with SWF Encrypt, as with most other similar tools, is that it must still be possible to execute the script on a (possibly compromised) machine. So all information must be available on said machine. Compare that with a classic use of cryptography, sending messages:

When you send an encrypted message, you typically trust the source and the destination, so both of these have the key to decrypt the message. What you don't trust is the courier, or at least not that your enemies will not intercept the courier. So the courier does not have they key and your message is safe.

Your problem is instead that in your case you trust the destination (you) but not the source (the client) or vice versa. Still you need the source to be able to encrypt the message since you trust the courier even less. So the source needs to have all information to encrypt and decrypt messages in order to function. Your problem is that you cannot see the difference between a "good" source and a "bad" source.

What I mean is that since the code must still be possible to run on a client, the information to do so must be fully available, albeit possibly in obscured form. A hacker could for instance create her own ActionScript compiler that transform the obfuscated ActionScript code into something readable and make appropriate changes. Difficult but definitely doable.

Yet this level of sophisticated attacks will most likely not be a problem for you, if you have a limited distribution and no real bounty to win.

Andreas Magnusson
A: 

I don't see any advantage of using the solution, Kent mentioned. As a client, I can request that server side created key. Ok I can't use it more than one time, but i don't have to ... every time I need one i just request it.

  1. So i request the key.
  2. Make my own highscore
  3. Hash the highscore with the key.
  4. Send the highscore to server
  5. The server use the submitted key to get the highscore back.
A: 

I'm not sure which ones you've read, but this one has a top answer:

http://stackoverflow.com/questions/73947/what-is-the-best-way-to-stop-people-hacking-the-php-based-highscore-table-of-a-f

HTH

Zárate
A: 

Wow

Pretty hard solutions 8).

I implemented system like this once. Although it won`t work for every game out there...

You should replay the game on server. When user play -- you store "state changes" and then simply feed it to you game in some kind of "replay" mode.