Skip to main content
gamedev.net
🔒 Locked

[.net] Security with Scripting

Started by Raloth 12 replies 1.3k views
Original Post
Raloth
Raloth
I'm taking advantage of C# to have some pretty cool "scripting" ability in my game. Essentially, the user can write a DLL for the map that contains some custom data. There are interfaces they can inherit, and then the game sends messages to the DLL allowing the user to do whatever they want with them. It should go without saying that this is a scary thought, especially considering users will be able to share these DLLs over a lobby type chat system. However, by setting the security permissions right, there isn't much permanent harm they can do. While not permanent, I still find it incredibly easy to go ahead and crash the host program. All it would take is an infinite loop. A more subtle way would be through System.Windows.Forms...or any of hundreds of possibilities. Granted, a user doing writing those kind of nonsense "scripts" would quickly be ignored, but I would rather prevent it in the first place. The infinite loop can be solved with some simple threading. The rest is a little more complicated, and I can't think of any way to stop it. It would be amazingly easy if I could just set it up so they can only use certain namespaces (System and the game namespace exposing allowable functions)...but it doesn't seem like I can do that. If anyone can give some insight into security issues like these I would love to hear it. Otherwise I'm going to have to scrap the idea or just trust the users to play nice (haha).
____________________________________________________________AAAAA: American Association Against Adobe AcrobatYou know you hate PDFs...
mutex
mutex
I've been meaning to get myself up to speed in this area, so I don't know much at the moment, but this seems like a good article on what you want to do. The .NET Configuration Tool is interesting to play with if you want to quickly see what's possible (try creating your own permission set).

Oh and to actually tie this in with what you want to do, this page discusses how to create an AppDomain with restricted permissions. You can execute user assemblies in that AppDomain for security.

Raloth
Raloth
Thanks for the links mutex, they will help.

...but...

Common sense tells me that the app domain switching would be slow to say the least. Some comments on other message boards verify this. My system was going to be set up so that the entire game itself would be run via the scripting method. The number of app domain switches could very well make that the bottleneck, which is completely unacceptable.

I'd like to hear from someone else who has tried this.

My other option would be writing a Managed C++ wrapper around Lua. It would take more work initially but could solve the problems I'm worrying about now, and security would be much less of an issue.
____________________________________________________________AAAAA: American Association Against Adobe AcrobatYou know you hate PDFs...
Washu
Washu
Well, then, if you don't want to use AppDomains, then what you can do is when you decide to load the assembly containing the script, check it's referenced assemblies, to make sure that it only references allowed assemblies (you can require that they not reference mscorlib as well.) In this way you could provide the assemblies with a set of allowed assemblies they can reference containing all of the utility methods (like math functions) that they require.
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.
mutex
mutex
But wouldn't you still be able to use reflection to get at any assembly that happened to be loaded? I think you'd have to disallow access to Type.GetType(string) somehow. And yeah, cross-AppDomain access appears to be quite slow. Maybe there's a way to temporarily reduce the security of the current thread or AppDomain.

Raloth
Raloth
Quote:
Original post by Washu
Well, then, if you don't want to use AppDomains, then what you can do is when you decide to load the assembly containing the script, check it's referenced assemblies, to make sure that it only references allowed assemblies (you can require that they not reference mscorlib as well.) In this way you could provide the assemblies with a set of allowed assemblies they can reference containing all of the utility methods (like math functions) that they require.

That would work great

...except... (there's always an exception [headshake])

I had planned on precompiling the script file for faster load times in the actual game. Sounds good, except that it could leave the possibility open to someone writing a Managed C++ dll and manually replacing the other one. This Managed C++ could then call whatever unmanaged code it wants and I'm S.O.L. I would have to set the permissions of the entire application to disallow unmanaged code, something I can't do since there are a few unmanaged things I call myself. I would also have to disallow reading/writing files, etc.

Even if I compiled the C# code at game load time there is still no way to be sure they don't call unmanaged code. It appears that I'm right back to the AppDomain issue.
____________________________________________________________AAAAA: American Association Against Adobe AcrobatYou know you hate PDFs...
Washu
Washu
Quote:
Original post by Raloth
Quote:
Original post by Washu
Well, then, if you don't want to use AppDomains, then what you can do is when you decide to load the assembly containing the script, check it's referenced assemblies, to make sure that it only references allowed assemblies (you can require that they not reference mscorlib as well.) In this way you could provide the assemblies with a set of allowed assemblies they can reference containing all of the utility methods (like math functions) that they require.

That would work great

...except... (there's always an exception [headshake])

I had planned on precompiling the script file for faster load times in the actual game. Sounds good, except that it could leave the possibility open to someone writing a Managed C++ dll and manually replacing the other one. This Managed C++ could then call whatever unmanaged code it wants and I'm S.O.L. I would have to set the permissions of the entire application to disallow unmanaged code, something I can't do since there are a few unmanaged things I call myself. I would also have to disallow reading/writing files, etc.

Even if I compiled the C# code at game load time there is still no way to be sure they don't call unmanaged code. It appears that I'm right back to the AppDomain issue.


Strongly sign your assembly then. This will prevent it from being replaced by a malicious assembly.
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.
Raloth
Raloth
Great - but is there a compiler flag that will make it so they can't compile or access unmanaged code?
____________________________________________________________AAAAA: American Association Against Adobe AcrobatYou know you hate PDFs...
RomSteady
RomSteady
The February 2005 SDK includes a secure scripting sample. The sample uses C++ hosting C#, but the concepts should be easy to apply to C#/VB.NET.
Michael Russell / QA Manager, Ritual EntertainmentI used to play SimCity on a 1:1 scale.
Raloth
Raloth
I'm assuming you are talking about the DirectX SDK, in which case I've already looked at that sample. It doesn't do quite what I want to.

[edit] The Evidence parameter of the compiler when I make the code looks like it does what I want to do. However, I can't figure out at all how to use it.

[Edited by - Raloth on March 10, 2005 8:28:08 PM]
____________________________________________________________AAAAA: American Association Against Adobe AcrobatYou know you hate PDFs...
VizOne
VizOne
Raloth, have you actually tried and profiled the multi-AppDomain solution? I would always give it a try because AppDomains are *the* solution to have parts of an app run under more restrictive security settings. Furthermore you will be able to unload the script dll by unloading the AppDomain. Always keep in mind that most games are not CPU limited.

There are several things you can do to minimize boundary crossing. Most of the time the client-code is called at only one place of the gameloop. Load some kind of proxy dll into the second AppDomain which will provide an interface to most of the datamanipulation necessary for the game. Then, when the script requires some data, let the proxy pull it over the boundary and cache it. The next time it is accessed get it from the cache. When the script is done flush all data changes back to the main AppDomain. This can minimize the number of cross-AppDomain calls.


Regards,
Andre
Raloth
Raloth
I have found a solution more elegant than I could have hoped for:

[SecurityPermissionAttribute(SecurityAction.PermitOnly, Flags = SecurityPermissionFlag.Execution)]
By putting this in front of any method calls (or objects) involved with the actual scripting, I can change the security for just that call (or object).

[smile]

I may still have to look into AppDomains in order to unload the custom scripts, but there is no reason I can't simply shove all of the game data in the same AppDomain so there is no overhead. It's not needed while the user is in the lobby anyway, so it has the added benefit of saving (a minute amount of) memory.
____________________________________________________________AAAAA: American Association Against Adobe AcrobatYou know you hate PDFs...
SOS
SOS
I have a feeling that if the called code creates a new thread, that thread will not have the restritced permissions. You might want to check it out.
Raloth
Raloth
Quote:
Original post by SOS
I have a feeling that if the called code creates a new thread, that thread will not have the restritced permissions. You might want to check it out.

Ah...but the called code does not have the permission to create the thread in the first place. =)
____________________________________________________________AAAAA: American Association Against Adobe AcrobatYou know you hate PDFs...

Topic Locked

This topic has been locked by a moderator. New replies are not allowed.

Sign in to reply to this topic.