Advertisement

[Javascript] Securing properties from client-side tampering

Started by July 19, 2015 04:37 PM
3 comments, last by hplus0603 9 years, 4 months ago

What are some methods for preventing users from tampering with game properties (i.e. hacking the game) in Javascript based games?

Consider the game to be a Javascript-based (MEAN stack) multiplayer RPG where you can walk around a map, open chests, etc.

Properties are stored server-side. These properties include things about a character's state such as: current position, current HP, items in inventory, etc. Updates to the server are performed to save client property changes (i.e. character position changed, picked up an item, etc).

As a game hacker, I could modify the properties on the client side so that when the game saves to the server, it saves my modified properties (i.e. set game.player.hp = 99999). Btw, I don't believe that using things like revealing module pattern could prevent access to 'private' properties, it would just make it a bit more difficult as it could be re-instantiated by the hacker.

How can this be prevented? What are the best practices?

I have read that server-side validation is required to prevent forgery. This might require recording a "transaction tape" of commands since the last update, then simulating these commands and assessing their validity against the game's rules. This validation seems like it would be extremely difficult to perfect.

I wonder if there could be some sort of token service that is passed from the server to the client to guarantee that an update is coming from an authorized source. However I feel like this would have enough client-side interaction that would allow a hacker to emulate this process and circumvent it.

The other option would be to leave every single property update to the server on every single modification (no timed polling or anything). For example, not just upon opening a treasure chest, but even on player movement. If the player presses 'W' to move forward, it would execute a function playerMove('forward') which sends up to the server for validation/storage. Infrequent changes like opening a chest would be simple in this model, but frequent changes, like player movement, don't seem feasible.

Never trust a client. The server must be the single authoritative entity at all times. You can think about insanely complex measures to prevent client side cheating but in the end hackers will always find a way around that,

So basically what you are writing in your last paragraph is how it should be done. The client only sends its intention to do something to the server which in turn changes the game state after checking the validity of the player's requests.

In order to get around the problem of latency (player presses key but only starts to move after the server has sent a response) you can employ client side prediction techniques to mask the delay. Since you are building an RPG you can also think about game design changes that mask the delay. e.g: Show "progress bars" before executing a spell so the player just thinks the delay is actually part of the game. ;)

Advertisement

What are some methods for preventing users from tampering with game properties (i.e. hacking the game) in Javascript based games?


The *only* mechanism that works us running a trusted server, and putting all "important" gameplay decisions on the server, not the client.
enum Bool { True, False, FileNotFound };

Never trust a client. The server must be the single authoritative entity at all times. You can think about insanely complex measures to prevent client side cheating but in the end hackers will always find a way around that,

So basically what you are writing in your last paragraph is how it should be done. The client only sends its intention to do something to the server which in turn changes the game state after checking the validity of the player's requests.

In order to get around the problem of latency (player presses key but only starts to move after the server has sent a response) you can employ client side prediction techniques to mask the delay. Since you are building an RPG you can also think about game design changes that mask the delay. e.g: Show "progress bars" before executing a spell so the player just thinks the delay is actually part of the game. ;)

Well, I'm sold on client-side/server-side prediction/assumptions.

And I guess the server doesn't need to know that the client is holding down 'W', it just needs to know that it was pressed, and can assume that it is still pressed until it receives an update for onKeyUp event/etc or some other method to cancel the 'W' action. So it will therefore not be bombarded with updates of "user is pressing W". May as well just send a playerMoved('forward') each time though.

the server doesn't need to know that the client is holding down 'W', it just needs to know that it was pressed, and can assume that it is still pressed until it receives an update for onKeyUp event/etc or some other method to cancel the 'W' action


Unless the single event that says "W was released" was accidentally lost, and then the server believes it's pressed forever :-)

Generally, when doing "server receives client inputs," the kind of "inputs" that the server receives is parsed, post-device, semantic inputs. For example, there might be a four-bit value that contains whether the client wants to move/strafe forward/backward/left/right -- if the user re-maps "forward" to the space bar, the same bit is still sent to the server.

And, because input is typically tiny, you can send a copy of the input state for each simulation tick. And, because it changes slower than your simulation tick on average, it will likely also RLE compress really well, so you can send the last 60 ticks worth of input in each packet, at whatever rate you use (say, 20 Hz networking, 60 Hz simulation.)
enum Bool { True, False, FileNotFound };

This topic is closed to new replies.

Advertisement