Is there any way to block a C# plugin from accessing the main C# Application in a program?
I have a program and a simple plugin architecture where the plugins implement a generic interface and the main program loads all plugins that implement this interface. It's the most common custom plugin architecture I have found so far, so that's what I'm using.
I am not using Microsoft's MEF and I have my reasons for not doing so. I'll leave it at that.
The issue is that when the plugins are loaded, no matter how 'blind' they are to the main program and it's forms/classes/etc. it can still access System.Windows.Forms.Application
and can therefore gain access to my application and its currently running forms/methods/controls/etc.
I do not want this. Is there an way to restrict a plugin's access to the main Application?
EDIT: More info about the plugin
We (my boss and I) are currently discussing what the plugins need to do. They all obviously need to add functionality, but we originally decided to give each plugin access to the currently running form so that it can add controls and events directly to the form. This was based on the assumption that only we, the developers, would be writing them.
Now we are considering the possibility of third party plugins and the original design, obviously, 开发者_StackOverflow社区has about as much security as a "Do Not Enter" sign on an open door with no one around.
Or a "Take One" sign hanging on a bowl of individual skittles on Halloween.
One way of doing this is to host your plugins in their own AppDomains. You can configure these AppDomains to have limited security to prevent them from accessing resources in the main AppDomain. This does complicate things a lot, but will give you the sand-boxing you're after.
An additional benefit you receive from AppDomain hosting is that you can load and unload these domains if you wish to refresh plugins, plus you can protect your main AppDomain from crashes in your "child" domains.
Update
After seeing your update re. the capabilities of your plugin, AppDomains are not going to help if your plugin must have direct access to UI elements e.g. access to a form to add controls. You will not be able to give direct access to a form over an AppDomain boundary, or produce controls in one AppDomain and then marshal them across to another.
You could still consider hosting plugins in another AppDomain, but you will need to think about some sort of proxy mechanism so that actions like adding a control to a form can be done on behalf of a plugin, rather than letting the plugin access the form directly. For instance, you could pass in a form builder object which had methods such as AddButton
. The proxy could then perform these actions of behalf of the plugin in the main domain. In this way you could provide a limited API for the plugin complete with required events.
This approach is by no means trivial, but once you have mastered the basics it's not too complicated.
Update 2
Things have moved on since rolling your own plugin frameworks with AppDomins back in the day. There is now support baked into the .Net framework since 3.5 for plugins:
MAF - Managed Addin Framework / System.Addin
It supports AppDomain isolation modes for plugins and has plugin loaders, etc. No need to roll your own.
If you can run your plugins in their own AppDomains
, that would certainly increase the level of isolation. It can also make it a pain to communicate with them though. Without knowing more about what the plugins are meant to do, it's hard to know whether or not that's appropriate.
So to restate your primary concern:
... and can therefore gain access to my application and its currently running forms/methods/controls/etc.
Before embarking on a complex and difficult means of loading, isolating, and restricting these extensions you should know a few things about Windows and the CLR. First, any program running on the box can use a number of Windows APIs to inject code into your process. Once code is loaded into your process, either by you or by the OS, accessing the CLR runtime and loading assemblies and/or running code in your existing AppDomain is fairly easy.
Knowing this you should weigh and balance the effort you excerpt to restrict 'extensions'. If I where building something like this I would be more concerned about other things than a malicious piece of extension code manipulating the state of my application. For example these are things you might consider:
- Only load extensions that are approved by your user, allow them to control what is allowed and allow them to revoke an extension later if desired. Look at Office or VStudio as an example.
- Ensure these approved extensions are untampered by using a code signing requirement (strong names, or code signing certificates).
- Consider having the ability to revoke an extension's ability to run remotely if it's found to be malicious.
- Prove a well-appointed Interface API to allow developers to easily implement desired behavior. If it's easy for them to use your interfaces to accomplish their task they won't need to 'hack'.
Beyond this there really isn't much else you can do. As I said, anyone can attack your application even with the above safe-guards. Your primary concern should be to not surprise your users. Thus the due-care in what code YOUR application runs is advisable, but what those extensions do once your users grant them access is not really something you can completely control.
This isn't to say that an AppDomain isolation won't provide you value, it may; however, IMHO getting the security restricted enough without limiting their ability to function will prove to be difficult.
UPDATE
... but if you load a plugin into an AppDomain which is configured with limited permissions how can it use this vector?
Correct, as I said in my closing statements, you can limit their access to unmanaged code within the AppDomain. This also limits their ability to develop a usable Windows experience. I expect that most WinForms applications use at least one PInvoke call or unmanaged COM control. This limitation imposed may be acceptable, I really can't say without more information about what functionality they are trying to provide.
All I was trying to say is that by installing and approving the extension your users are accepting the responsibility of allowing that extension to run. What that extension does and how malicious it may attempt to be is not your responsibility, assuming of course that you loaded the correct code. This is why I recommend focusing your energy on running approved code rather than worrying about what that code might do once it's in your process.
The best way to handle this is expose a documented plugin API. If your plugins run with full trust, then even if you run the plugin in its own AppDomain it can inject itself back into the application - then all it takes is someone to make a wrapper available and all the plugins are back to the same state they started in. If your API allows plugins to provide the desired features in a straightforward, consistent and documented manner, then that's what plugin developers will use.
The following are external UI hooks for WPF, Windows Forms, and the classic Spy++ (all with source).
- Snoop (the WPF Spy)
- Managed Spy
- .NET Object Spy and InvokeRemote
- Win Spy++
精彩评论