On a scale from 1 to 10 how bad of an idea would it be to use a JSON like format for game networking?

Started by
23 comments, last by hplus0603 11 years, 1 month ago
Existing (and even moderately successful) real-life games do that. I know at least two Facebook MOs that do this, one recently added XOR-encryption (*cough*) for security.
Everybody knows that you need 2 rounds of XOR-encryption for it to work...


I remember one (successful) MMO that I played years ago that would simply send the output of Java's Serialize() over the network (unencrypted). No, it didn't break their neck. They eventually added encryption after 5 or 6 years to thwart proxy botting. They're still in business.
I often lament the fact that software development is heavily influenced by the law of diminishing returns. It's so much more costly to make something correct than it is to make something adequate, so there's rarely a business case for the former. If it all blows up later, you can almost always fix it later.
Advertisement

I'm afraid I have to disagree with your conclusions on serialization/deserialization risk.

This is a severely bad idea, unless you really want malicious players to have free run of your game - both client and server.

The format of the packets -- whether JSON, XML, ASN.1-BER, or your custom binary serialization format -- does not change your security model at all.

This isn't actually true. The more generalized your serialization/deserialization is, the worse its security posture is. The worst being of course, deserialization into arbitrary code (ala JSONP or YAML). The recent issues in the Rails community should highlight that.

My point is transmitting executable code as a communication mechanism does change your security profile. To make it secure you have to basically strip out all execution potential from your data stream and the interpretation mechanisms, at which point you may as well just use an existing serialization mechanism in the first place.

Every web browser and web site sends gobs of executable code to your client -- Javascript is the de facto application language of the future. Yet, security holes don't come from Javascript; they come from Java or Flash plug-ins written in native code.

There are whole classes of browser exploits that are only possible because of the ability of an attacker to run arbitrary Javascript. So again, bad example.

You're right, this is side tracking. The argument that sending executable code is unsafe isn't particularly strong IMO.

Sending code from the server to the client is done all the time, even for native code: That's what a patcher does!

Again, this is a bad example. There are so many badly written patchers out there that there are a whole class of "Evilgrade" vulnerabilities, where an attacker can impersonate the update service and run arbitrary code.

To pull things back to the original question, JSON is actually a reasonable choice, with a couple of caveats.

The first is never use JSONP. The second is to make sure that the JSON parser you are using is not calling a more dangerous parser behind the scenes (as in a recent Rails issue).

I would certainly use JSON over a languages generic object serialize/deserialize functionality; you want to make sure that you can strictly control the output of the parsing of untrusted data, and anything that looks like "object Deserialize( byte[] rawNetworkData)" (in whatever language you are using) is inherently unwise.

You could give the MessagePack protocol (http://msgpack.org/) a go. It's like a binary JSON with readers and writers in many languages. I've successfully used it on a server network running LuaJIT to transfer data around, and it's quite compact.

A JSON like format - great. It will make debugging easier, that's for sure.

But Lua? Unless you have a Lua parser that will treat it purely as data and not try to execute it, it would be extremely dangerous. Anybody on the internet could craft some malicious Lua code and send it to your server to be executed.

Lua is sandboxed. It's an important point you make though: Choose carefully the Lua functions that your network packets can execute; don't give network packets generic functions with filesystem access, for starters (No DeleteFile() or CreateFile() or anything like that).

Aside from that, I don't see a problem with sending Lua scripts - but I'm no security expert. As for the 'text is larger than binary' - this is absolutely true. HTML is text when it's sent over the network - but it's not sent 10-30 times a second like a real-time competitive FPS or MMO might require, just three or four times every few minutes - and the delay in receiving and processing the HTML and CSS and such is visible (just hit 'refresh' on your browser - it's not instantaneous). So, like everything, the pros and cons need to be weighed depending on the project requirements.

The more generalized your serialization/deserialization is, the worse its security posture is. The worst being of course, deserialization into arbitrary code (ala JSONP or YAML). The recent issues in the Rails community should highlight that.

To be fair, the Ruby/Rails people were doing some REALLY STUPID things with their data, as there is absolutely no good reason that any parser, be it JSON, YAML, or anything else, should be attempting to deserialise and construct arbitrary objects looked up by name. The formats do not inherently support this feature - it was an incredibly stupid addition that was added by web developers to make their life simpler, for which they (and thousands of others) are now paying the price. There's nothing inherently unsafe to YAML or JSON parsing. You do have to understand your parser though (because evidently the people writing them can't be trusted to keep them safe).

Lua is an interesting case as it is obviously executable code. Yes, it can be sandboxed, but at some point you need to pull the data from the sandbox into the rest of the app, which is the risky part. So I'd just prefer to go with a plain data format like JSON. Lua is fine for trusted data.

at some point you need to pull the data from the sandbox into the rest of the app, which is the risky part.

Although, to be fair, no more risky than pulling data out of a decoded packet into the app. The bigger risk with executable bytecode would be the potential for a DOS attack, where "decoding" the packet would set the interpreter into an infinite loop of some sort. Sandboxes can be built to avoid this (LUA interpreter exits after at most N instructions) but it's yet another thing to worry about.

Executable code is almost never actually needed for a runtime game packet format, though.
enum Bool { True, False, FileNotFound };

This topic is closed to new replies.

Advertisement