jpcsupplies / Economy_mod

Basic Economy System for Space Engineers
13 stars 12 forks source link

Security, player handshake on connection. #101

Open midspace opened 8 years ago

midspace commented 8 years ago

Currently the level of security in sending messages around in the mod is really insecure. I'd like to establish a handshake between the server and connecting client, that sees the server send a private key to the client on the specified Steam Id, to confirm it's identit. There after the client should always use that key when communicating with the server to prove itself.

There are a couple of issues with this. There is no reliable method of determining whena player disconnects to clear the key cache. Alternatively we could have the server recheck the client periodically and remove the key if there is no response. (Feels a little klike punk buster).

The other part is, the SteamId should be part of the core message, which I have asked Keen to add to make use of the message more trusted.

jpcsupplies commented 8 years ago

you can request a list of players yes? Create two arrays. Store the player list in array 1, wait 30 seconds then store the player list in array 2. Use a compare operation between the two arrays if there is a difference we know the player missing from array 2 recently disconnected.

Rough logic -

on server start - clear key list

store players in array 1. Toggle a bool to true.

repeat (Wait 30 seconds.)

if true compare array 2 with array 1. anything in array 2 that is not in array 1 is a new player, anything in array 1 that is not in array 2 recently disconnected. else compare array 1 with array 2, anything in array 1 that is not in array 2 is a new players, anything in array 2 that is not in array 1 recently disconnected.

if new player generate id code, add to key list if player disconnected, remove id code from key list

Check bool, if true store players in array 2, and set bool false, else store players in array 1, and set bool true

until (server shuts down)

jpcsupplies commented 8 years ago

This side is probably more your department,

For the key itself how do we make it unhackable? People may be able to spoof one if they know how we make them.

So we need a server side only code that is generated semi randomly, and a client side that is different to server side.

Both of these keys need to be stored server side. The server side key is never exposed client side. The client key is never exposed to other players.

When communicating with server, the server needs to take the client key and use or compare it somehow against the server side key. The result (perhaps some calculation) tells the server if it is a legitimate request.

The key could be periodically randomised again both client and server side, but if they have a method to sniff this may be ineffective.

If we add a 3rd per transaction ID we can also authenticate player to player transactions

If we change the key for every authenticated event, this makes hacking too hard basket for hackers

Weak points:
if a client id is sniffed, it overcomes the security.- so a client can mess with their own transactions it may make it quite difficult for me to add features to the mod :P sim speed implications major overkill for a monopoly money mod

Strong points: prevents a 3rd party spoofing transactions on another player since they will not see another players client or server ID, unless they rooted a router in use by that player useful proof of concept exercise, which could be applied to other mods or later features requiring integrity checks (eg crypto, web front end, real world cash shop etc)

Conclusion: might suit later milestones of mod where things like selling ships or stations, spawning ships etc make the need for a way to prevent trolls spawning or changing ownership with hacks impossible

jpcsupplies commented 8 years ago

Another approach - if we want a more banking flavor - each player bank account is allocated a unique code, (crude private key) server side. client side each player records their own unique code (crude public key) client side

This client side is only stored on each individual players computer, and is not saved on other players computers. When interacting with server this public key is used to authenticate transactions that effect the players bank or possessions. Other functions work as normal.

This key would need to be generated on connect and only be valid the current gaming session.

It would also only be generated server side, and handed off to the client.

The security front end could be a single authentication module that all secure transactions must pass through. Once authenticated, an additional server side only internal key is used to pass the command to a second module. This module then passes the command as normal to our current messaging system which is designed to ignore everything but commands issued from the second module.. Basically we replace the chat line return true/false logic with our authenticator. Commands that filter through both of these pass as normal to our command processing engine - which works identically to how our current chat system works, but it would be getting its split[]'s from the command passing module, instead of game chat.

That means from my perspective, there are no great leaps of understanding needed if me or anyone else adds commands, and the security module doesn't need to be touched.

ie. Current system chat->split[]->regex/if/case list->individual commands->message modules

Proposed system chat->stage 1 filter->authenticated command written to split array->regex/if/case list->individual commands->message modules

Advantages: we only need to alter private void GotMessage to add our auth code we only need minor tweak to start of private bool ProcessMessage to confirm authenticity before continuing

Disadvantages: Commands will not immediately execute, there will be a delay as we authenticate Everything a player types will be evaluated. We need a way to block calling message modules directly client side working unauthenticated, to prevent players just going around authentication by hacking the "hot" scripts in their temp folder, to allow them to call the message module procedures directly. They may still call - but execution should detect no authentication and halt. (doing this is entirely outside my capabilities) Spoofed commands using their current public key may still work.

Workarounds: In GotMessage we should first immediately ignore anything that does not begin with "/" to weed out wasted processing so chat has negligible impact on sim. We may need an extra select case list to pass safe commands (seen, help etc) immediately to our ProcessMessage unmolested, and only do extra security on things like /pay/buy/sell/admin commands etc

Things to watch: This approach most likely breaks isadmin() since processmessage is called by the server internally. We may need a way to record admin keys and create a module to replace isadmin() anywhere we use it. Eg isadminKey()

Tampering with scripts in client temp folder may still look legit server side. But should be limited to tampering with their OWN transactions since they should not be exposed to other clients current public key.

There is a 30 second window before we detect a player has left, this potentially is exploitable if a player was disconnected deliberately by the hacker. I assume client IPs are not whitelisted so we cant compare public keys with matching client IP?

jpcsupplies commented 7 years ago

this would probably compliment #133 too actually