Javascript – Securing client->database game

htmljavascriptSecurity

OK, I am creating a game using JavaScript and HTML5. The variables such as map, x, y, level, exp, etc are stored in JavaScript to keep track. On my client page, the JavaScript variables are stored to play along with the game. Every 5 seconds, the client page sends a POST AJAX call to the MySQL database and it successfully updates it.

However a user can easily modify the JavaScript variables and cheat their way in the game. Then once they edit the JavaScript variables, the POST grabs that and updates it even though they edited it unethically.

So, how do I prevent this from happening?

Best Answer

Game are really hard to develop, because you'll never be sure that no one will find the way to cheat. But there is some tips you can put in place to try to prevent cheat, in every type of game, whether it's written in Flash, JavaScript ...

The more important thing to think of is : You must never rely on client.

The server must

  • NEVER :

    • rely on datas sent by the client (ids, coordinates, power, prices won.. ).
    • save datas that it has not calculated and checked itself
  • ALWAYS

    • has an up-to-date version of the client's properties. the server must always rely on that properties to allow/disallow any action, calculate new properties, store properties in databases, send to clients
    • check the concordence between clients actions
    • allow or disallow the client to do any action (you want to move left ? I check if you can... Yes you can, your x is now lastx-1 / No you can not, you're at the map limit, your x is now lastx )
    • check if the elapsed time between two actions is possible. ( You asked me to jump. I replied you could, but that would take you 5 seconds before next action. You're asking me, two seconds after, to move right. It's not possible, you're jumping right now !).

The client must

  • ALWAYS
    • verify itself if it can perform an action before asking the server to do it =» less server calls, more security because there is two checks, by the client and by the server
    • rely on server datas. (You sometimes can animate things - like counter - and calculate the animation client-side AND server side. BUT you can have latency client side that makes client datas a little different than server datas.)

Other cheat controls in case of step-by-step game

Server must

  • validate every steps ( you try to do the second step, does your session says that you already performed the first one ? )
  • has a validation datas for every steps ( You sent me that your score for this step was 1200, but the max score is 500, bug or cheat ? redo step please )
  • keep traces of every step to validate/calculate datas at the end ( you send me this score at the first step, this one for the second, this one for the third... )
  • check if the validation of a step is possible in the elapsed time ( you try to send me step 2 result. Step 2 takes at least 18 seconds to perform, you sent me step 1 result 4 secondes ago. Houston, we've got a problem )
  • re-create a validation token for each calls ( ok, next time you call me, send me this token with your message, I want to be sure that we are at the same point )
  • (re)-create the session when the client download the game ( when you send a flash/javascript game file, when the client download the file from your server, make it go through a script that initialize the session, by making the file not cachable by the browser. If a client try to go to step 1 and the session does not exists, either the session is expired, or he tried to modify the flash/javascript file )

Very simple example case :

You have a real-time game with 2 players on the same map

Map properties : 3x3 - Coords {x : 0, y : 0} = corner top left

Server » players : player1 : { x : 0, y : 0, life : 5 }, player2 : { x : 3, y : 3, life : 2 }

Player1 » Server : move right

Server » players : player1 : { x : 1, y : 0, life : 5 }, player2 : { x : 3, y : 3, life : 2 }

Player2 » Server : move left

Server » players : player1 : { x : 1, y : 0, life : 5 }, player2 : { x : 2, y : 3, life : 2 }

Player2 » Server : move left

Server » players : player1 : { x : 1, y : 0, life : 5 }, player2 : { x : 1, y : 3, life : 2 }

Player1 » Server : move up

Server » player1 : you can not move

Server » players : player1 : { x : 1, y : 0, life : 5 }, player2 : { x : 1, y : 3, life : 2 }

Player1 » Server : move down

Server » players : player1 : { x : 1, y : 1, life : 5 }, player2 : { x : 1, y : 3, life : 2 }

Player2 » Server : hit

Server » Player2 : no one to hit

Server » players : player1 : { x : 1, y : 1, life : 5 }, player2 : { x : 1, y : 3, life : 2 }

Player2 » Server : move up

Server » players : player1 : { x : 1, y : 1, life : 5 }, player2 : { x : 1, y : 2, life : 2 }

Player2 » Server : hit

Server » players : player1 : { x : 1, y : 1, life : 3 }, player2 : { x : 1, y : 2, life : 2 }

Player1 » Server : hit

Server » players : player1 : { x : 1, y : 1, life : 3 }, player2 : { x : 1, y : 2, life : 1 }

Player2 » Server : hit

Server » players : fatal, player1 : { x : 1, y : 1, life : 0 }, player2 : { x : 1, y : 2, life : 1 }, player2 win

I'm sure I forgot some tips, and I'll update if it comes back to me, but I think you'll be able to manage your game with these and maybe think by yourself at securities to add.

The more important thing to think of is : You must never rely on client.

Related Topic