[.net] Security with Scripting
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).
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.
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.
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.
...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.
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.
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.
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.
Quote:Original post by RalothQuote: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.
Great - but is there a compiler flag that will make it so they can't compile or access unmanaged code?
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.
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]
[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]
This topic is closed to new replies.
Advertisement
Popular Topics
Advertisement