Ralph Posted June 24, 2016 Share Posted June 24, 2016 So, I am currently building a multiplayer game, and havent run into any hackers yet, but need to know what to do in order to protect against them in the future. Basically, what could potential hackers change in the javascript source? I know people can right click and modify the source code then run it again locally, but that wont be connected the server so i dont care, but other than that i dont know what to look out for. Inventory data, locations of players etc are all stored on the server and I dont save anything on the players local side, is that all i really need to do in order to prevent cheaters from some how modifying something important that gives them an advantage, such as speed hacking or changing what they have in there inventory. Is saving important data on the server all i really have to do? This might be a little confusing what im asking but im kinda in a rush and wanted to post this before I left. Thanks for the help in advanced. Link to comment Share on other sites More sharing options...
mattstyles Posted June 25, 2016 Share Posted June 25, 2016 You've pretty much secured yourself against many forms of cheating by storing authoritative state away from the client. You've defined a protocol for clients to make changes to things like inventory though, and, in theory, this can be worked out and mocked so that whatever calls your client makes to update state can be replicated outside of your system, guarding against this is particularly difficult. You can encrypt each packet you send against some sort of key and based on the packet contents, possible also against a timestamp, but it gets complicated and even then it could potentially be reverse engineered if someone was persistent/determined enough. Of course, all this will slow down transmission and interpretation of packets so you might want to pick and choose what to do this with. The thing with inventory cheating is that generally your server should be able to work out what is even possible. For example, if a player is in a certain location that does not contain the Super Uber Sword of Awesomeness, then there is no way that item can pop into their inventory, if it suddenly appears in there then you know something fishy is going on. Removing/banning the player seems like a good way to go but maybe you could be sneakier by replacing the item with a Cursed Sword of Transformation which turns the player into a chicken with each use and can not be unequipped HTTPS should also be used to stop man-in-the-middle attacks but that doesn't really stop cheating, it stops packet sniffing but players will always be able to work out what their own browser is sending anyway. Thinking about it, having some sort of encryption on every packet should make it damn near impossible to work out what messages to send to try and cheat. They'd have the source but unobfuscating it could be very tricky indeed to work out how the encryption works and you could change the encryption strategy with each reload to make it harder to repeat cheat. drhayes 1 Link to comment Share on other sites More sharing options...
Ralph Posted June 25, 2016 Author Share Posted June 25, 2016 14 hours ago, mattstyles said: You've pretty much secured yourself against many forms of cheating by storing authoritative state away from the client. You've defined a protocol for clients to make changes to things like inventory though, and, in theory, this can be worked out and mocked so that whatever calls your client makes to update state can be replicated outside of your system, guarding against this is particularly difficult. You can encrypt each packet you send against some sort of key and based on the packet contents, possible also against a timestamp, but it gets complicated and even then it could potentially be reverse engineered if someone was persistent/determined enough. Of course, all this will slow down transmission and interpretation of packets so you might want to pick and choose what to do this with. The thing with inventory cheating is that generally your server should be able to work out what is even possible. For example, if a player is in a certain location that does not contain the Super Uber Sword of Awesomeness, then there is no way that item can pop into their inventory, if it suddenly appears in there then you know something fishy is going on. Removing/banning the player seems like a good way to go but maybe you could be sneakier by replacing the item with a Cursed Sword of Transformation which turns the player into a chicken with each use and can not be unequipped HTTPS should also be used to stop man-in-the-middle attacks but that doesn't really stop cheating, it stops packet sniffing but players will always be able to work out what their own browser is sending anyway. Thinking about it, having some sort of encryption on every packet should make it damn near impossible to work out what messages to send to try and cheat. They'd have the source but unobfuscating it could be very tricky indeed to work out how the encryption works and you could change the encryption strategy with each reload to make it harder to repeat cheat. Wow great reply! Firstly I didnt even know someone could modify their browser to chose what to send back to the server (Im using socket.io) but the way you put it makes a lot of sense, at the end of the day it is YOUR computer that is sending data back to the server and that can be manipulated. On the encryption thing, the way you are putting it seems very useful to me, but I dont know how i would be able to do that. If they can see my client source then they could reverse engineer how the data was being encrypted and see the format of whats being sent to the server right? Encrypting the data coming from the server seems easy to me but thats not an issue issue because the data coming from the server back to the client is first defined when they say pick up an item and put it in their inventory, which is where I think is the weak link. Edit: Also the location thing would be a great idea, iffff this was an RPG lol its more of a 2d open world survival game, so in theory they could get a certain item anywhere, and items inside a dead player are stored server side so that is covered too I think. Link to comment Share on other sites More sharing options...
mattstyles Posted June 26, 2016 Share Posted June 26, 2016 10 hours ago, Ralph said: Edit: Also the location thing would be a great idea, iffff this was an RPG lol its more of a 2d open world survival game, so in theory they could get a certain item anywhere, and items inside a dead player are stored server side so that is covered too I think. Oh yeah, I didnt really consider items moving around, oops! Still, there might be something in it, you have the entire state in the server so any actions the users perform can be validated i.e. if there is no corpse with a Tin Hammer in it then the player can not suddenly have one in their inventory, unless they have tin and sticks, although maybe this gets more complex as crafting stuff maybe depends on the server i.e. you send a request with the configuration of crafting items and the server sends back a response that instructs the client to delete those crafting items are replaces them with something else. I guess part of it is that if you really want it secure then have multiple disparate systems in place to defer cheating. Sure, someone could, in theory, work out each of them and you'd probably have a hard time working out if anyone was actually cheating, but the point is that, like a locked door, it doesn't make bad stuff™ impossible, just makes it harder to do. 10 hours ago, Ralph said: If they can see my client source then they could reverse engineer how the data was being encrypted and see the format of whats being sent to the server right? Yep, absolutely, but if your code is minified and/or obfuscated then its hard to pick through, you could try unminifying it but I'm not sure that is ever particularly reliable and whilst it might reconstruct syntax in a way that makes more sense for a human it would never restore names so it would still be hard to pick through. Of course, you don't want to make the service that sends requests to be public, it needs to be hidden some interface so that it is not available in the browser globally, you're probably doing this anyway if you're using any sort of module system (even wrapping in closures is a module system of sorts and would do for hiding globals). But, its difficult to do this and by encrypting you at least guard against people tracking their own packets, they could still send the same packet again (maybe to replicate getting an item) but, if that encryption includes a timestamp then the server would know the later request is invalid and respond accordingly. You can send a new encryption policy with each page load, or even more frequently than that if you really wanted to. This would invalidate any clientside code cache though as it would effectively be a new script but you could load the encryption stuff a little later so most of your code is cached on the client to facilitate quicker loading times and its only your sensitive code that comes later. Its a big step to do though. Encryption can be as simple or as difficult as you want. If you're sending JSON than its all text so send the timestamp along with it, then either pop it through an encryption algorithm or roll your own (check out Caesar ciphers, they're always good fun if you like that sort of thing, not completely uncrackable of course, ask the Allies ). The algorithm always takes a key in addition to the instruction set for the encryption, its probably just the key you want to rotate. You could even send several keys to the client and rotate during the session, but then if the internet drops a request or you fire off several quickly and they arrive out of order then you have a problem, only resolvable by sending some of id and then ensuring those id's arrive in order, it gets complex quickly. Just a quick note on rolling your own encryption, don't do this for anything sensitive (cheating is not sensitive), the field of cryptology is a difficult and involved one, always use a well-defined solution for anything that might compromise your users integrity/data. drhayes 1 Link to comment Share on other sites More sharing options...
hexus Posted June 27, 2016 Share Posted June 27, 2016 On 6/24/2016 at 0:50 AM, Ralph said: such as speed hacking On 6/25/2016 at 9:23 AM, mattstyles said: For example, if a player is in a certain location that does not contain the Super Uber Sword of Awesomeness, then there is no way that item can pop into their inventory, if it suddenly appears in there then you know something fishy is going on. I'd like to expand on this for speed hacking, too. You could use a lenient range check on the player to make sure, according to their allowed speed, whether they're moving too quickly. You won't want to be too strict with this though, because latency will most definitely cause some inconsistencies. mattstyles, Ralph and drhayes 3 Link to comment Share on other sites More sharing options...
Ralph Posted July 7, 2016 Author Share Posted July 7, 2016 On 6/26/2016 at 4:16 AM, mattstyles said: Oh yeah, I didnt really consider items moving around, oops! Still, there might be something in it, you have the entire state in the server so any actions the users perform can be validated i.e. if there is no corpse with a Tin Hammer in it then the player can not suddenly have one in their inventory, unless they have tin and sticks, although maybe this gets more complex as crafting stuff maybe depends on the server i.e. you send a request with the configuration of crafting items and the server sends back a response that instructs the client to delete those crafting items are replaces them with something else. I guess part of it is that if you really want it secure then have multiple disparate systems in place to defer cheating. Sure, someone could, in theory, work out each of them and you'd probably have a hard time working out if anyone was actually cheating, but the point is that, like a locked door, it doesn't make bad stuff™ impossible, just makes it harder to do. Yep, absolutely, but if your code is minified and/or obfuscated then its hard to pick through, you could try unminifying it but I'm not sure that is ever particularly reliable and whilst it might reconstruct syntax in a way that makes more sense for a human it would never restore names so it would still be hard to pick through. Of course, you don't want to make the service that sends requests to be public, it needs to be hidden some interface so that it is not available in the browser globally, you're probably doing this anyway if you're using any sort of module system (even wrapping in closures is a module system of sorts and would do for hiding globals). But, its difficult to do this and by encrypting you at least guard against people tracking their own packets, they could still send the same packet again (maybe to replicate getting an item) but, if that encryption includes a timestamp then the server would know the later request is invalid and respond accordingly. You can send a new encryption policy with each page load, or even more frequently than that if you really wanted to. This would invalidate any clientside code cache though as it would effectively be a new script but you could load the encryption stuff a little later so most of your code is cached on the client to facilitate quicker loading times and its only your sensitive code that comes later. Its a big step to do though. Encryption can be as simple or as difficult as you want. If you're sending JSON than its all text so send the timestamp along with it, then either pop it through an encryption algorithm or roll your own (check out Caesar ciphers, they're always good fun if you like that sort of thing, not completely uncrackable of course, ask the Allies ). The algorithm always takes a key in addition to the instruction set for the encryption, its probably just the key you want to rotate. You could even send several keys to the client and rotate during the session, but then if the internet drops a request or you fire off several quickly and they arrive out of order then you have a problem, only resolvable by sending some of id and then ensuring those id's arrive in order, it gets complex quickly. Just a quick note on rolling your own encryption, don't do this for anything sensitive (cheating is not sensitive), the field of cryptology is a difficult and involved one, always use a well-defined solution for anything that might compromise your users integrity/data. Sorry for the late reply I was out of town, thank you again for the great response. Gives me a lot of things to think about. I feel like this is more of a creative kind of thing where it doesnt really matter which approach you take, there are endless ways to make it harder for someone to mess with the game! This should be fun in the near future. Link to comment Share on other sites More sharing options...
waechtertroll Posted July 12, 2016 Share Posted July 12, 2016 I agree on this being a creative task more than a "tech perfect" thing. I would not advise to use any encryption of packages. For one thing it puts more load on the server and slows communication, but secondly, to encrypt you need some kind of encryption key, and as you're planning client side encryption, the client needs to have that key available. Of course, one could request unique encryption keys on login and hold them in memory only, but the whole JS memory is available to any browser dev console (it will be a PITA to reverse engineer, though). I think sanity checks are a much better way to go. Client->server: "pick up item id_12345 at position x=17, y=12, z=-1" Server->client: "you're not even in that level!" or "that can't be reached from your position" (or "error") or "Here, you get the 'half-empty medpack of curing pimples', but for security reasons you can only refer to its usage by my server-side gamestate-id of it" Ralph 1 Link to comment Share on other sites More sharing options...
Skeptron Posted July 13, 2016 Share Posted July 13, 2016 Yeah I also think that encryption is not the way to go. It won't prevent a hacker from seeing what's going on. Encryption should only be used if your players exchange sensitive information, like a chat for example (and even there, not necessarily an obligation). Server-check is the only way to go to prevent cheating. I'd add that you also never want the clients to send anything else than the controls they may press. A player should never send "Go to x:120/y:744" or "Deal 75dmg". They should only send "I pressed Q" or "I clicked at x:120/y:744". The server will know what to do with these actions and can't be cheated into using false coordinates or values. Also, avoid sending useless information. If you're doing an RTS for example, and the enemy of a player is in the fog of war, then just don't send anything about him. You'll save bandwidth and the player won't be able to hack the code to still see his opponent through the fog of war. Ralph 1 Link to comment Share on other sites More sharing options...
stupot Posted July 15, 2016 Share Posted July 15, 2016 Keep the client as dumb as possible, it should be a remote viewer and input device. hexus and Ralph 2 Link to comment Share on other sites More sharing options...
Recommended Posts