Security

Started by
28 comments, last by GameDev.net 19 years, 7 months ago
Quote:Original post by WitchLord
As another solution to the problem you could digitally sign the compiled bytecode. That way the client can verify if anyone has altered the code and not run it. This would only be a viable solution if you can keep the private key secure. If you plan on having public servers then the private key isn't secure so the digital signature cannot be trusted.


This doesn't help if the code is malicious at the source, at the server. (I.e. someone has set up a server just to spread a pleague. :)
Advertisement
Would the following pseudo code help?

	...	case BC_WRT4:		a = *stackPointer;		stackPointer++;		d = *stackPointer;		if( *(asDWORD*)a < LOWEST_ADDRESS_OF_ALL_DECLARED_VARIABLES ) // Check the pointer		{			SetInternalException(TXT_NO_EXECUTE_ACCESS?);			return;		}		*(asDWORD*)a = d;		programCounter += bcSize[BC_WRT4];		return;	...


If you cannot trust anyone, Server operator, client nor 3rd party eavesdropper, then scripts probably need to be as source (Protects against viscous server), run length encrypted with checksum(protects from network listeners), and finally, realize that you can never trust the client as it will always have all the information needed to access the byte code, you just need to make sure it isn't trivially easy.

In a server/client game scenerio: Having clients run scripts is to offload the server from having to send the state changes generated by said script and are not replacements for offloading all of the work. The server should run state changing scripts to maintain the clients current state, sending snapshots so the client can autocorrect.

Mad
Quote:Original post by WitchLord
I read the reference manual for Lua, and from what I can see Lua doesn't allow saving/loading of compiled byte code, which effectively eliminates the security problem we are discussing here.
Lua does allow that. Functions can be dumped as bytecode, and all functions that load scripts will work on bytecode as well as source code.

Lua has two major tricks up its sleeve WRT malicious code.

The first is that the debug library allows you to preverify code, in the same way that the Java VM does. This obviously doesn't detect malicious intent, but makes sure that nothing is writing to bizarre, out-of-range stack addresses.

The other thing is that, as a VM with only stack and table operation opcodes, it doesn't really have the "features" necessary to enable code to break out of the sandbox. Scripts can crash, of course, but only within the confines of the VM execution.
Quote:Original post by Dentoid
This doesn't help if the code is malicious at the source, at the server. (I.e. someone has set up a server just to spread a pleague. :)


That's why I said that it wouldn't work with public servers, i.e server that anyone can install and run. If you only have private servers then the private key can be kept secure which would make it incredibly difficult for an impostor to pose as a valid server.

AngelCode.com - game development and more - Reference DB - game developer references
AngelScript - free scripting library - BMFont - free bitmap font generator - Tower - free puzzle game

Mad Dugan:

Your pseudo code doesn't really help. I can't just set a lower limit for the variables. It is quite possible that there exists memory between the lowest accessible memory and the highest accessible memory that should not be allowed to be accessed.

Sneftel:

Oh, ok. I didn't see that functionality when speeding through the manual.

I was just wondering how Java does it. Thanks for letting us know.

It seems the only solution to make the bytecode secure is to follow Lua's example. Just like the script can't manipulate pointers, the bytecode can't be allowed to either. I will analyze this to see if it is possible to do something like that, but I have a feeling that it won't be an easy task. I don't want to limit the interface that I have with C++ applications.

Maybe it is possible to have the VM analyze the bytecode when loading it to see what operations it is doing and then decide if it is trying to access anything it shouldn't. It should be possible to verify if any absolute addresses are being read from or written to. And the instructions that pushes the address of a stack location on the stack (for future manipulation) can be checked so that the location is within the stack frame of the function. In this pass I can also verify that all function ids are valid, and global variable indices as well.

One potential problem is the instruction ADDOFF, which adds an offset to a pointer. How should the VM know the allowed limit to ADDOFF? It can't. I'll have to think about how this can be worked around.

I will start working on a function like this for a future version of AngelScript. Even if it might not be able to verify everything at start I will be able to analyze the weaknesses better, and either remove them or find a way to protect them.

AngelCode.com - game development and more - Reference DB - game developer references
AngelScript - free scripting library - BMFont - free bitmap font generator - Tower - free puzzle game

Quote:Original post by WitchLord

Maybe it is possible to have the VM analyze the bytecode when loading it to see what operations it is doing and then decide if it is trying to access anything it shouldn't. It should be possible to verify if any absolute addresses are being read from or written to. And the instructions that pushes the address of a stack location on the stack (for future manipulation) can be checked so that the location is within the stack frame of the function. In this pass I can also verify that all function ids are valid, and global variable indices as well.


I think this is what I've been trying to suggest. :)
I suppose you did [wink] I just didn't see a viable solution until now.

It's still not an easy task but at least I believe I will be able to do it so that it has the same security as script code. I will also have to change how object properties are accessed as the byte code ADDOFF (add offset) alters a pointer in a way that can't be controlled. I've already come up with a solution for it so it's not a show stopper, though it will affect performance slightly.

AngelCode.com - game development and more - Reference DB - game developer references
AngelScript - free scripting library - BMFont - free bitmap font generator - Tower - free puzzle game

So I have read all the posts and this is my point of view :

- You want to send byte code over IP
- You cannot trust client side because some bad guys wants to do what they have to do, bad work, neither you can trust server because bad guys wants to also do their bad work.

The question is :
Why all of those bad guys wants to crash your application ?

If your a client, you don't have really interest in crashing your computer, don't you ?

If your a server you can have interest in crashing your server ? no I don't think so too, but, you can have interest in crash the clients connecting to you ! To do this, your server must be knowed by client ...

So, my point of view wont be to secure scripts, but rather secure your application outside the script part.

Both client and server must trust each other, so, they have to aknowledge each other :
Client : Hello server, my program is version X, with a checksum of Y and I run with ScriptVersion Z. What is your versionS ?
Server : Hello client, you are connecting server version X, with checksum of Y and I run ScriptVersion Z.

Now that client and server knows their versions, checksum, or whatever they want to check (graphic card abilities, processor, memory, etc...) they can trust each other.

Also, timestamping and versionning the messages between client and server can lead to disconnection when timeout comes (bad guy debbuging !).
Well, if you must send a script over the line to a client, the smartest option would be to sign the script with a DSA. This will allow the client to verify that the script hasn't been tampered with (on the trip from the server to the client). This isn't foolproof however, and using a CA will help to increase the security of the DSA, but none the less, it is one option.

In time the project grows, the ignorance of its devs it shows, with many a convoluted function, it plunges into deep compunction, the price of failure is high, Washu's mirth is nigh.

Quote:Original post by Washu
Well, if you must send a script over the line to a client, the smartest option would be to sign the script with a DSA. This will allow the client to verify that the script hasn't been tampered with (on the trip from the server to the client). This isn't foolproof however, and using a CA will help to increase the security of the DSA, but none the less, it is one option.


That still doesn't help if the server actually sends bad stuff.

This topic is closed to new replies.

Advertisement