Main
Use SSL

Preventing cheats on game servers

29 November 2007


Seems that I forgot about this blog for more than a month now, and without any good reason. Anyway, I'll try to point out some ideas in this post, things that I've been dealing with lately. (Note that this post is in no sense a practical example of anything, but just a compilation of some theoretical points)

I'm currently finishing up a little project of mine, that just happens to be a multilayer poker game for cellphones. The client is written for Java MIDP, and the server is a standard multi-threaded Java application (running on a remote server). While working on this game I've encountered many security aspects that are worth sharing, so read on.

Game servers aren't exactly perceived as "web applications" in the standard sense, i.e. they do not utilize the HTTP protocol, use CGI, or depend on web browsers. And yet, they surely are web applications in every sense. They are very processor intense applications, and the developers usually focus on efficiency rather than security - in a classical trade-off.

There are a few core security mistakes that can be embedded deep inside the application design and render the whole game vulnerable to cheats and hacks. Here are a few:

1) Trusting the client-side for any calculations.

This an absolute NO-NO when it comes to game servers, or any multi-client servers in general. In my poker game the client has a state variable that says whether it's the players turn right now. This affects the menu options and the messages that will be sent to the server (on KeyPress events).

If the server just listens to incoming packets and handles each one without verifying their validity, it would be possible to make game actions before getting the "right" to do them. The server must hold all state variables and verify every action that the user takes.

In more complicated games "taking the client for granted" could result in things like speed-hacks, walking through walls, or worse. Never rely on timing or game logic to be made on the client side.


2) Sending all game information to everyone.

As a rule of thumb, no client should receive any information that isn't going to be used by it. Not only will such information give an unfair advantage to cheaters, but it will also utilize unnecessary bandwidth, that is already scarce.

My poker game has a few objects that represent the current game-state. One Game object and many Player objects. The Game object describes a poker table, and everything on it (including references to the Players). The player object contains all information about a single player.

When an event occurs, all the clients should be informed about the change. Now, I could just serialize all objects, pack them, and send them to every client. The clients will just take whatever they should, and leave all the unnecessary data untouched.

This is fundamentally not-okay. A cheater could tap into the incoming packets, and get all the "unnecessary" data just as well. In my case, this data would contain the other players cards. In poker, this is the ultimate cheat.

In order to avoid such situations, I didn't program the server to simply multi-cast everything. Each client has a separate TCP stream, and a separate thread. Every Player object has 2 serialization methods. One for public access, and one for private. A client that owns the current Player object will get all the data the object contains, while everyone else will only get the public data.


3) Be careful with persistent data storage, especially SQL.

Even in a simple poker game, persistent storage is necessary. My game has an "Accounts" table that contains login details, and various game data (like the amount of money a user has).

I refer to the database in 3 different "places" (per client thread):
A) Login attempts
B) After every turn (to update the stats and money)
C) When the user quits the game.

This is enough to prevent any "money loss" even when the server shuts down in the middle of a round, and far from enough to cause any serious server stress.

This approach is fine, unless you forget a very basic thing. Your server can be prone to SQL Injections just as the next php script. You have to filter everything you receive from the clients (strings, commands, etc). Whatever you intend to put in a query, has to be filtered.

Try to make less SQL queries, and more handling within the classes and objects. All the queries should be simple SELECTS or UPDATES, but nothing too fancy. This will save you CPU cycles, and leave your code less database dependent.

4) Multi-threaded is good, if you synchronize correctly.

Yeah, a basic thing like thread synchronization becomes a major security threat in applications such as game servers. Synchronization is made for the case in which the same data can be accessed from 2 threads simultaneously. When this happens, the results can be unpredictable. Or rather predictable, but very much un-intended.

Just as a single example, let's say that Thread 1 reads the variable "Money" and stores it. At this instant, Thread 2 does the same thing, and changes the value of "Money". When Thread 1 continues, the "Money" it stored will have the old value. If Thread 1 saves the value to the original "Money" variable, it will appear as if Thread 2 didn't run at all.

This can happen even with code that executes "instantly". It all depends on how loaded the server is, and the sheer probability of those 2 actions happening at once. This probability is especially high when the server is over-loaded, meaning that when the game "lags" it's the best time to cheat.

If the variable "Money" was locked properly, none of this would happen. However there is no simple "fix" to this. Synchronization is the essence of multi-threaded programming, and it's something you'll just have to deal with in your code.

------

There are more points to write about, but I will do so in another post. Meanwhile, it's sure visible that game servers are very challenging security-wise. The trade-off between efficiency and security has tremendous impact on them, and this makes them especially interesting applications.

I will write about this as I gain more experience in the field. Expect an update soon.

Posted by: kGen | In category: Webappsec | Comments (0)