Wednesday, March 5, 2014

Designing a secure gaming network

What does secure mean? For most people this means that a site or server that cannot be hacked.

In May 2013, one of the largest Banks in America (Bank of America) with the one of the most secure banking systems in the US was hacked. The hackers took over ATMs in NYC and in just 4 hours withdrew 20 million dollars from user accounts. This is just a few months ago... this is supposed to be security at its best. In July 2013, Apple was hacked and their developer accounts were compromised possibly exposing all developer accounts. Their email (which I received) said that all developer accounts were encrypted but that they were going to reset all developer accounts "just in case."

For the BofA atack, there are some minor caveats like the hackers had internal information, but that hardly matters... how did the hackers get in? The hackers having internal info should not have allowed this. At Apple, no excuse was offered but how did this happen? This is a huge deal but what about that encryption... does it matter?

The big boys who have enormous resources and fabulous teams of anti-hacker developers still manage to be hacked. If they are hacked, what can a lowly game developer hope to do against the onslaught of hackers out there. So, before you get upset, there is a ton that you can do to prevent the very thing that caused so many problems for Apple and BofA. It comes down to architecture. 


Before I begin, let me say for the record: you must make an effort to thwart hackers to prevent the casual hacker or lazy programmer from getting into your system. That said, I promise you: you cannot build a better security system than BofA. The trick is to limit the damage and to detect the intrusion. The rule is: Build the best system possible but also realize that hackers will break into your system eventually. This is where a good architecture matters.

Any place where external users can attack your systems, or just use your systems, you have a potential threat and a vulnerability. Most people look at game network systems as being something like this:

Each part of this diagram has a ton of vulnerabilities. The phone or PC can be hacked, the users can snoop on their PC and then replay the data traffic to the server, a man-in-the-middle can listen to someone's network traffic and try to pretend that they are making purchases, someone can attack the server directly sending bad packets or good-looking data that is meant to take over your sever and give them access to your database... and on and on. Where do we server programmers have any control? Only at the server level? Not so fast... we have far more control than that.

We can control the client app, we can hash passwords before they are sent and never store passwords on the server (you store the hash so if hackers get the DB, they still can't use the stolen accounts ), the communications can be controlled and if at any time we detect abuse, we can shut down an abusive connection, etc. All of these are potential places to prevent hacking (and optimize).

The biggest problem with the above diagram? The direct access of the server to the DB. In fact, this is so flawed, that you are practically giving hackers free access to the db and you will never detect an intrusion when it happens because most likely, they hackers will take over the server using buffer overflow and then simply copy everything on your server so that they can look at it during leisure time. They tend to target specific database items but when they don't know what they are doing, they may just copy everything.

The communication protocol should be small and will be the topic of another blog post.

For any internet facing process, I prefer to store nothing like a password file with the exe. My type of security is to write an exe that:

1) Can be launched remotely
2) Can be isolated in a VM or on it's own hardware
3) Has no DB access

4) Opens a socket on launch and takes commands like "listen on port 3400" and "forward all packets to ipaddress 10.1.34.192".
5) Isolate that machine/VM in such a way that when hackers break into it (they always do) that they have no configuration data, no local files, no db access, etc. This prevents them from knowing anything about your systems.
6) Keep a monitor application that checks to make sure your app is still running and when you app comes down, relaunch, send parameters for configuration to your app, and no worries...

They hacked your system, but you can rest assured that even with buffer overflow and if they manage to send your exe back to themselves, they won't know anything about the internal configuration of your systems since you app doesn't know those things.

No system is perfect, but this type of system is extremely difficult to take over the server, and when they do, this "gateway" type of app knows nothing so hackers don't get anything and they certainly have no access to user accounts.



Storing anything in a local directory leaves you vulnerable. If you want to do this, then unix/linux is the best way because you can lock down the file system to prevent hackers from looking at your files (Windows can be configured this way, but it's a lot harder to do).

So, for a local file, limit it's access to read only (you won't believe what they can do if they can overwrite your password file... it's a backend buffer-overflow where they overwrite it and when you decrypt it, your app crashes). Then put your app deep in a separate subdirectory that can access from your file. Then give your app limited permissions (definitely not root). Deep directories make it harder to get to /etc and other directories. Here is some good advice (jail kit stuff):
http://stackoverflow.com/questions/527876/how-to-restrict-a-linux-user-to-be-only-able-to-read-home-user-and-nothing-else

When they take over your server (and they will, make no mistake), make it very difficult to change directories, grep, etc. You don't want them to find anything. Anything that they find could become a vulnerability. Its best to start with a fresh install on a clean box and not install anything on it that isn't absolutely necessary. A VM is great for this because it's just a file. When you finish configuring the VM the way that you want... copy the VM file and expect some hacker to get into your system and completely destroy your VM. Then you can simply restore from backup (file copy... really). Should take about 30 seconds to bring your server back up.
Whatever you do... do NOT store a list of ip connections, ports, or access to your DB. Never, never, never let your internet facing gateway process have access to the DB. Don't even include the DB Connector code and do not install the ODBC on that computer either. You do not to give hackers even a small chance of figuring out that you use SQL Server (MySql, Oracle, whatever) so the less info you have on that internet-facing box, the less damage they can do.


This is the current server architecture that I have built (a diagram I use internally) and the gateways run in a completely different VM. All of the games run on another box and cannot be accessed from the gateways except through internal routing. When someone hacks the gateway, user info is never exposed.

Another critical piece is the trapezoid that reads "Is user permitted". This is in the gateway, but for malformed packets, too many packets in a short time, buffer overflow, etc, I shut down the connection. Because we want hackers to think that they are being successful and not know that we spotted them, we put the socket on "ignore-mode" which means that it continues to receive and will shut down the socket after 30-130 packets later. That way, this increase the amount of work that a hacker has to do by at least an order of magnitude.

The other systems have a distinct protocol for talking to the gateway which is highly specific. This protocol is different than the protocol for talking to the client. When hackers do take over the gateway, they have no way to talk to the game servers, they have no access to the DB, they can only talk on specific ports and IP Addresses. This system is not unbeatable, but based on 20 years of networking security design, this is my latest and most secure.

Splitting your DB into sensitive data and common data can help too. If a hacker has to go to different DBs (schemas) to try and get user account info, this begins to become too hard to make things worth it. Splitting user account info (credit cards) and purchases is trivial in the DB World, but piecing those back together is very hard. Using an 'd' field is often trivial to replicate so I bind them using a "UUID" so that putting it all back together is next to undecipherable.

One last step I do is never, ever, send user db indices (id) back to the client. Way too many flaws in security are based on handing back to the user their DB index (e.g. user_id=42336). If a hacker gets a hold of your db through SQL injection, we don't want him to dump the user table by knowing the structure or using simple indices. For each user, I generate a unique identifier (UUID) that is sent back to the client. When they get a list of friends or other things, you only see these impossible to hack UUIDs. Hackers would have no idea how to use that information to look up user info. The gateway knows nothing about UUIDs either and so hacking our gateway reveals no user info at all.

Encrypting packets will come next