I'm building a project that will support loading in external, managed DLLs, essentially as a modding system. However due to security reasons I'd like to restrict (as far as possible) what those external DLLs can access and do because they won't be made by myself.
My current plan was to simply blanket ban every assembly besides a select whitelist which I can add to upon request, however my main issue is the System.dll. It's probably the most important one to restrict access to due to the obvious reason that it can access System, however it also has vital namespaces like System.Collections, so it needs to be useable.
Is there a way to check specifically what assemblies and namespaces a loaded DLL is utilising or am I going about this the wrong way?
Related
I have several C# assembly libraries, which are not strongly named (signed). I would like to make a SxS COM-wrapper over those components using the tlbexp.exe to consume in native programs. Is it necessary to sign them or is there another way to do it?
Thanks
There are strong misconceptions in this question, it confuzzles the roles of two programmers. You are the author of the library, somebody else uses your library and probably works for another company and has no idea who you are. The client programmer. You in turn have no idea how the client programmer uses your library, how many programs he wrote and what he does to deploy your library on his users' machines. You run Tlbexp.exe only to help him write his code.
This is a recipe for trouble, like it is no matter what language or tooling you use when you create libraries. That trouble starts when you make a change in the library and the client programmer has to rebuild and redeploy his programs that use your library.
There is extra trouble in a COM library because by default registration is machine-wide. Which is pretty nice if the change you made is a bug-fix, all of the client programs that use your library automatically get the fix. But it is not nice if the change is breaking and causes the old client program to fail. The standard disaster is that the client programmer rebuilds some of this programs but forgets or ignores some old ones he no longer maintains. The end-user is often the real victim, he's got a program that crashes but two programmers that don't think it is their problem to fix.
What is necessary is that programs that the client programmer does not update keep using the old version of your library so it is unaffected by the change. In other words, there need to be multiple copies of your DLL on the users machine and a program automagically needs to pick the right one.
Thankfully that is easy to do for a [ComVisible] .NET assembly. Either the client programmer, his user or an installer you provide for him can put the assembly in the GAC. Which allows multiple copies of an assembly to exist side-by-side and the CLR can automatically find the correct one. That has two requirements. You need to bump the [AssemblyVersion] of your library, that's standard. And the assembly needs to have a strong name so it can be put in the GAC. That is trivial to do by you, using Project > Properties > Signing and ticking the "Sign the assembly" checkbox. This has no security implications so the key doesn't matter and a password is entirely unnecessary. It is not easy to do by the client programmer so this is something that you must do. Always.
The client programmer also has the option to use isolated COM with a manifest (aka "regfree COM"), probably what you meant with "SxS COM-wrapper". With the benefit that each program he writes has its own copy of the DLL, the way it works by default in .NET. Bug-fixes need to be deployed manually but a change in your library can't break an unmaintained client program. But this is entirely his choice, there is nothing that you can do to ensure that this is done. You must assume that he doesn't use it, and he almost certainly won't at first, so you can't bypass the need to strong-name.
When an assembly is strongly named, its types can only be used from other strongly named assemblies. Since your assemblies are not strongly named, there's no need to sign your COM wrapper.
Signing an assembly makes it possible to place it in the Global Assembly Cache (GAC). This has the benefit of keeping multiple versions side by side, without breaking existing clients.
The alternative is to use the Windows registry via regasm's /codebase switch. Much in the same way as classic COM components are set up, this option registers your COM-visible assembly on a system wide basis.
Since you wish to deploy your COM wrapper via SxS / Registration-Free activation, thereby bypassing the registry and GAC altogether, there's really no need sign it.
Currently I'm working on a .NET hobby project that involves a complex system of objects which work in combination with eachother. However, I encountered a little problem, I am unable to find a mechanism in .NET to support replacing code at runtime, and be able to dispose of the old code, loaded previously. This means replacing a module/object dynamically and almost instantly displaying the changes to the user, for example, when he restarts a procedure, but not the whole program.
I have already taken into account the possibility of having separate AppDomain for each session and loading the necessary assemblies into it but this seems a little bit too expensive. I should also mention that every session benefits from a common base of assemblies, for instance, to connect to a database, so this means loading those classes into every single session. Marshalling data back and forth from the separate AppDomain also represents an additional overhead (could be used when data is sent to the client application through the network, code for this contained in the main AppDomain, which manages the sessions).
Is there a framework or way of replacing/unloading particular parts of code? How is it done in real-world applications? Can there be a workaround? Or have I picked the wrong set of tools?
You need some kind of plugin system with well defined interfaces. Then you load at runtime binaries (your plugin *.dll) and create objects from it and then execute methods on it.
When you create a system where objects from your plugins must be created through your IPluginManager you have no problem with replacing code at runtime. :)
Or
You have something like a folder with *.cs files which will on demand compiled (in memory) and create the objects you want to use from them and call the methods on them.
Which is basically the same like above, without compiling at run time.
From there you can make further improvements.
EDIT:
Like you wrote the only problem without using AppDomain is that once loaded assemblies can't be unloaded. But that's not really a problem.
I don't think you need separate AppDomains: you can dynamically load assemblies within the current AppDomain. And each assembly should probably implement some defined interfaces (depending on your usage). You could use the FileSystemWatcher class, for example, to load/unload assemblies as needed.
See http://msdn.microsoft.com/en-us/library/25y1ya39(v=vs.110).aspx
You can have a look at MEF. It stands for: Managed Extensibility Framework .
Here's another article about it MEF on codeproject.
It is used to load dll's in runtime by composing them. This is what is usually used for plugins or anything else you kinda drop into a folder and expect it to run .
Here's a link to some more tutorials as well: Where can I learn about MEF?
Yes, you're right, it is not possible to simply unload an assembly (only AppDomains). But I think one of the features of ASP.Net vNext is the ability to have just in-memory assemblies and when you simply alter the source code on the drive it gets automatically compiled and loaded. Therefor a mechanism must exist to unload the previous version.
I think they are doing that by simply creating a AppDomain where all assemblies are loaded into again to avoid any cross domain communication. But i don't really know and maybe if you would dig more into the mechanism on how they do this stuff in ASP.NET you maybe find a good solution. More informations about the hot topics from vNext you can maybe also find at Scotts Blog.
Well, I've found 2 solutions that work for me, which I would like to share. The first one is to use CollectibleAssembly and define the types. This is certainly a bit tricky, and a number of restrictions are imposed on this type of dynamic assembies.
The other option is to use a scripting language like IronPython or IronRuby. Also a great feature of the new Roslyn compiler is that it also provides scripting APIs, not previously available in the .NET framework. What's more, the Roslyn scripting languages tend to look very much like their full-blown equivalents (C# or VB). And I've also found a tiny example of its capabilites.
How can I limit the loading and execution of my libraries based on a defined precondition? For example, if I distribute to a client an application that uses an external library, how can I ensure the external library is only used with the application and not used by the client for other purposes?
Is code access security the answer? If so, is there a good example of how to apply it in the situation described above?
Thanks!
UPDATE: I cannot use services to protect the logic. I must supply the code in an assembly, and want to protect it from being used to build other products.
The best way to limit access is to move the logic from an assembly into a service layer. If you are truly concerned about protecting the logic in that assembly this is the best way.
Remember, any mechanism can be defeated with enough effort if the client has the assembly in their hands and is truly motivated to use it. That is why a service layer is a perfect solution as it gives your application access to the logic without allowing the client to obtain the implementation itself.
You should look into code obfuscation Nothing that you do will prevent someone dedicated enough from using the logic contained in your assembly however they see fit, however obfuscation will make it a more difficult and will hopefully deter most people.
See this question for more information
There's a build option to only allow friendly assemblies to use yours but that implies you can sign both your assembly and your client's as well. I doubt what you want to do is possible witout some sort of service layer or authentication/connection limitation to a server logic. Sorry.
Just a thought here and definitely this is not the safest or best way. Maybe just a small work around.
Instead of sending the assembly with the executable, how about moving the assembly to the Global Assembly Cache (GAC) and modifying the executable code to access the assembly present in the GAC? You can then change the name of the assembly to some garbage name (or whatever you think suitable) which the client will not be able to understand. So finding your assembly in that forest of assemblies would be almost impossible.
Hope this helps!
Regards,
Samar
Im currently adding a interface to my application so other people can extend it with plugins. My application is used by MMO gamers and i will not have any control over the plugins ( In that anyone will be allowed to make them ) and i was hoping i could have some degree of control over the code in the plugins.
What im afraid of is someone making a plugin that either contains bad code that starts writing to folders outside "allowed" folders or does this by design. Since this will be run by a MMO gamers some sort of keylogger would be very bad.
So im hoping there is a way for me to:
Force the plugin to run inside a sandbox where it does not have direct access to filesystem,windows or network. In effect forcing them to use the API i provide for those actions.
I was thinking it might be posible to inspect the plugin dll hoping it contained a list of what namespaces it uses, and simply not load plugins that contained "bad" namespaces.
My plugin interface is based on this great codeproject artice , i did try to search for some information on this. But i was unable to refine my search to a point where it returned something usefull, if it mathers my skill level is C# and some cross platform c++.
It would be possible to inspect the assembly for certain things before you load it. Prior to executing code or constructing a type within the assembly, you could run through the entire set of assembly types and references using reflection, and search for "invalid" references. However, this is not going to be very effective, as you're always searching for things that are bad - when really, you need to define the operations that are good, instead, and only allow those.
The only way to cleanly enforce a different security policy for plugin is to load the plugin into a different AppDomain.
By loading the plugin in it's own AppDomain, you can enforce different security policies upon its code (basically run it within a sand box). You can provide interfaces or classes that are passed into the plugin in order to give it access to functionality beyond those in the plugin itself.
What recommendations can you give for a system which must do the following:
Load Plugins (and eventually execute them) but have 2 methods of loading these plugins:
Load only authorized plugins
(developed by the owner of the
software)
Load all plugins
And we need to be reasonably secure that the authorized plugins are the real deal (unmodified). However all plugins must be in seperate assemblies. I've been looking at using strong named assemblies for the plugins, with the public key stored in the loader application, but to me this seems too easy to modify the public key within the loader application (if the user was so inclined) regardless of any obfuscation of the loader application. Any more secure ideas?
Basically, if you're putting your code on someone else's machine, there's no absolute guarantee of security.
You can look at all kinds of security tricks, but in the end, the code is on their machine so it's out of your control.
How much do you stand to lose if the end user loads an unauthorised plugin?
How much do you stand to lose if the end user loads an unauthorised plugin?
Admittedly this won't happen often, but when/if it does happen we lose a lot and I although I understand we will produce nothing 100% secure, I want to make it enough of a hindrance to put people off doing it.
The annoying thing about going with a simple dynamic loading with full strong name, is that all it takes is a simple string literal change within the loader app to load any other assembly even though the plugins are signed.
you can broaden your question : "how can I protect my .net assemblies from reverse engineering ?"
the answer is - you can not. for those who havent seen it yet, just look up "reflector", and run it on some naive exe.
(by the way, this is always the answer for code that is out of your hands, as long as you do not have en/decryption hardware sent with it),
obfuscating tries to make the reverse engineering to be harder (cost more money) than development, and for some types of algorithems it succeeds.
Sign the assemblies.
Strong-name signing, or strong-naming,
gives a software component a globally
unique identity that cannot be spoofed
by someone else. Strong names are used
to guarantee that component
dependencies and configuration
statements map to exactly the right
component and component version.
http://msdn.microsoft.com/en-us/library/h4fa028b(VS.80).aspx