Jump to content

  • Log In with Google      Sign In   
  • Create Account

FREE SOFTWARE GIVEAWAY

We have 4 x Pro Licences (valued at $59 each) for 2d modular animation software Spriter to give away in this Thursday's GDNet Direct email newsletter.


Read more in this forum topic or make sure you're signed up (from the right-hand sidebar on the homepage) and read Thursday's newsletter to get in the running!


Game Server security


Old topic!
Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.

  • You cannot reply to this topic
11 replies to this topic

#1 IceBreaker23   Members   -  Reputation: 618

Like
0Likes
Like

Posted 01 April 2013 - 04:34 PM

Hello guys!

 

Right now I am developing a game consisting of a server made in C# .NET with database and a client for mobile devices in Unity3D.

I am using my own networking library with TCP.

 

The problem is: I am really afraid of people exploiting my networking code. So I know I can solve problems with the client by testing, testing, testing.

But what if someone writes their own client and doesnt keep my protocol? Right now I have a protocol which contains ( length of message | type of message | data ). What should I do if someone sends a request with a wrong length? Should I catch this case and just close the connection?

 

I think there are many cases my game server could crash. Is there any way of making sure someone can't crash my game server?

Maybe you guys can help me or point me to a paper which has this issue as a subject.

 

Thanks in advance!



Sponsor:

#2 swiftcoder   Senior Moderators   -  Reputation: 10430

Like
4Likes
Like

Posted 01 April 2013 - 05:54 PM

There is only one rule in networking: never trust the client.

 

When you are going to receive a packet from the client:

  • Figure out the maximum size a packet should ever be, and read only that much.
  • Check the message header to ensure it is the right type of packet.
  • Check the message length to ensure it makes sense for the packet type.
  • Explicitly null-terminate any strings received from the client.
  • Check the range of any numbers received from the client.
  • Check the rate of change of consecutive values received from the client.

Tristam MacDonald - Software Engineer @Amazon - [swiftcoding]


#3 Servant of the Lord   Crossbones+   -  Reputation: 21187

Like
0Likes
Like

Posted 01 April 2013 - 08:19 PM

Check the rate of change of consecutive values received from the client.

 

Which values are you talking about?


It's perfectly fine to abbreviate my username to 'Servant' rather than copy+pasting it all the time.
All glory be to the Man at the right hand... On David's throne the King will reign, and the Government will rest upon His shoulders. All the earth will see the salvation of God.
Of Stranger Flames - [indie turn-based rpg set in a para-historical French colony] | Indie RPG development journal

[Fly with me on Twitter] [Google+] [My broken website]

[Need web hosting? I personally like A Small Orange]


#4 hplus0603   Moderators   -  Reputation: 5725

Like
3Likes
Like

Posted 01 April 2013 - 08:36 PM

Should I catch this case and just close the connection?

Yes. As soon as something is not right, close the connection. Also, log this to some counter, perhaps correlated with client version reported on connection, so that you can tell if you have a bug that causes users to get disconnected because the client sends bad data :-)

Also, put a stringent max size on EVERYTHING. A maximum size on the message type. A maximum size on files downloaded or uploaded. A maximum size on strings. A maximum item count in arrays. And make those limits be fairly limited. This will avoid someone doing things like sending a "valid" packet that claims to have 2,000,000,000 items in it, and thus tying up your sever just receiving and dealing with that packet.

Another popular attack is sending malformed inner data. Say you have a "login" packet that looks something like: name:string, password:string, clientversion:varint.
Now, if strings are zero terminated, then someone can send a valid outer packet (type: login, length: whatever) but then not include a zero byte in the payload. Your decoding function may at that point run past the end of the packet, and read random memory. Don't do that! (Better is to length-prefix strings, and automatically cut them off at 255 bytes max.)

Even if you fix the string, someone might send a badly encoded varint. For example, let's say that varints are encoded with the high bit set when there's a continuation byte, and the high bit clear for the last byte; each lower 7 bits are data, little-endian. For example, the value 0xAA55 would be sent as:
(0xAA55 & 0x7f) | 0x80, ((0xAA55 >> 7) & 0x7f) | 0x80, ((0xAA55 >> 14) & 0x7f)
Now, someone could send a packet that contains the value 0x80 over and over again, causing your decoding logic to never break out of the varint decoding loop. Always establish a maximum length for a varint, or any data type, on the wire.

Once you have the serialization/de-serialization dealt with, the semantics of the packets matter. Don't treat something as "known good." For example, if an entity ID is in the packet, look up that entity ID in a hash table each time you see it. If it's not there, disconnect the player. If a property ID is in the packet, make sure it's valid, and if it's not, disconnect the player. If a floating point value is in the packet, make sure it's not NaN or Inf or denormal -- if it is, disconnect the player.

Edited by hplus0603, 01 April 2013 - 08:37 PM.

enum Bool { True, False, FileNotFound };

#5 swiftcoder   Senior Moderators   -  Reputation: 10430

Like
0Likes
Like

Posted 02 April 2013 - 06:44 AM

Which values are you talking about?

Assuming UDP networking, any sequence ids you are using to identify packets. It's ok to have a packet that is, say, 1-50 packets out of sequence, but if someone hands you a packet with a sequence number that is hundreds out, either someone is mucking with the packets, or you are experiencing massive packet loss, and might as well toss the client anyway.

You can of course also extend this to numeric values that change over time within the payload of the packet. But in general, I'd say that the client shouldn't be authoritative for any continuous values...

Tristam MacDonald - Software Engineer @Amazon - [swiftcoding]


#6 hplus0603   Moderators   -  Reputation: 5725

Like
1Likes
Like

Posted 02 April 2013 - 12:13 PM

You can of course also extend this to numeric values that change over time within the payload of the packet. But in general, I'd say that the client shouldn't be authoritative for any continuous values...

I would argue that clients are authoritative over the mouse position/movement, and mouse movement translates into camera/aim orientation (assuming FPS-style controls) and thus the client is authoritative for aim. While this makes aimbots easier to write, it's a necessary trade-off (and even without it, aimbots are entirely possible.)
enum Bool { True, False, FileNotFound };

#7 Xanather   Members   -  Reputation: 712

Like
0Likes
Like

Posted 02 April 2013 - 10:09 PM

Just create a series of checks which may reveal that the client is not a legitimate client or hacked client (i.e. detecting if the client is flying on the map - and not allowing that). Once that happens just remove them from the client list.

 

Making the connection-establish code as advanced as possible to verify the client can almost always be reverse engineered, so I wouldn't worry about that to much.



#8 frob   Moderators   -  Reputation: 22787

Like
2Likes
Like

Posted 03 April 2013 - 12:54 AM

The problem is: I am really afraid of people exploiting my networking code. So I know I can solve problems with the client by testing, testing, testing.


When you start talking about exploits and security, you need to change your mindset into one of risk management and risk mitigation.

The two big questions are: Who are you afraid of? What are the costs of a successful exploit?

A small market hobby game really doesn't need to be worried about major groups. Maybe a few programmer-types will poke and prod at it a little bit. Maybe some people will attach a debugger or a network probe. This is very different from a mainstream game that can expect major attacks from organized attackers for an extended period of time.

You need to figure out the maximum costs of an exploit. Would a successful attack take down one game, or an entire server? Would a successful attack have any high profile targets, such as a public leaderboard that they want to climb, or externally-visible achievements? Does it take down financial information, or even allow an attacker to make real cash transactions or expose financial information?



If you are a small project with a low likelyhood of skilled attackers, and the reasonable risk is that an attacker's game will crash and possibly a server needs to be restarted, that is one thing.

If you have a low likelyhood of skilled attackers, and your biggest risk is that your accounts database could be corrupted or damaged but otherwise individual games would be unchanged, that is another.

If you are a larger project with a high likelyhood of skilled attackers, with risks of highly public exploits including potential financial concerns, that is something altogether different.


Rolling back a leaderboard and tracking down the bad accounts is easy.
Rolling back a server's account database to a known good state is hard, but possible.
Having millions of customer financial records exported is impossible to roll back.

Spend your resources based on a careful risk assessment. If the stakes are low, it probably isn't worth much effort.

Check out my book, Game Development with Unity, aimed at beginners who want to build fun games fast.

Also check out my personal website at bryanwagstaff.com, where I write about assorted stuff.


#9 IceBreaker23   Members   -  Reputation: 618

Like
0Likes
Like

Posted 03 April 2013 - 04:40 AM

Thank you for all your replies.

 

So this game is a MMO. Its not exactly a mainstream game, but players will access one server. I dont trust the client so far as that he cannot really cheat in my game or so.

The thing I am really worried about is that someone sends a bad package and this raises an exception on the server(ArrayOutOfBounds, InvalidMemory etc.).

 

I don't need to worry about really proffesional attackers, but if someone attempts to hack the server and the server crashes, all players will be kicked and this will be really annoying for them. 

 

So my game is a combination of turnbased combat and trading card games for mobile plattforms. How likely is this to be hacked if it reaches 1 million downloads(really optimistic thinking, but for security issues the worst case)?

 

I think I'll think my networking lib through and check on how it could be hacked and catch those cases. Then it'll hopefully be enough.


Edited by IceBreaker23, 03 April 2013 - 04:40 AM.


#10 Kylotan   Moderators   -  Reputation: 3338

Like
3Likes
Like

Posted 03 April 2013 - 09:39 AM

The thing I am really worried about is that someone sends a bad package and this raises an exception on the server(ArrayOutOfBounds, InvalidMemory etc.).

 

So check the data when you read it. Validating input is not a difficult problem.

  • Length of message is too long? Log the event, drop the connection.
  • Type of message isn't valid? Log the event, drop the connection.
  • Data you try to read doesn't match the type of message? Log the event, drop the connection.

This isn't really about security but about code quality. These are all issues that could also arise if your client is not 100% bug free. The answer is just to make the server robust. Make sure your serialisation code is as small as possible, fully tested (eg. with unit tests), and always operates with reasonable limits in mind.

 

Also, wrap the code with exception handlers and kick off bad clients at the first sign of problems. You know you can catch all possible exceptions with a single catch block, right? That can be your final line of defence when running the live server to isolate problems with one client from the rest of the server.



#11 IceBreaker23   Members   -  Reputation: 618

Like
0Likes
Like

Posted 04 April 2013 - 03:14 AM

Thank you for your answer Kylotan!

 

I did all the things you said. All I wanted was a list as you gave it to me :)

I handle exceptions with try-catch block and in the catch block it writes the exception to debug log.



#12 Dave Weinstein   Members   -  Reputation: 537

Like
3Likes
Like

Posted 04 April 2013 - 01:23 PM

Divide the problem into two areas.

Cheating issues are in general threats to game integrity. If someone has a wall hack, or a teleport cheat, or has found an item-duplication bug in an MMO, these are threats to the integrity of the game as a game, but not to the security of the server itself.

Security issues are those in which an attacker has the ability to control the server (whether by running arbitrary code or simply causing the server to be unavailable).

I'm going to completely ignore game integrity issues in this post.

Picture a Venn diagram of two circles. One is "Specified Server Functionality", the other is "Actual Server Functionality". The area that is in the first circle but not the second is an easily quantifiable bug. "The quest is supposed to end when I have recovered the McGuffin, and it doesn't".

What is more interesting is the case where instead of failing to execute specified behavior, the code executes behavior that wasn't specified one way or another. This is (in general) where you are going to find your security bugs.

The best way to find networking security bugs is to use a tool called a fuzzer. A network fuzzer will generate large amounts of deliberately malformed data, and monitor the server for failure. Especially since you already know C#, I'd recommend getting a copy of Peach 3 (it's free), and setting up a network fuzzer against your server.

The goal is that fuzzing should do nothing beyond generating your *designed* "hey, I got an invalid message" behavior. Anything else is a problem.




Old topic!
Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.



PARTNERS