有没有办法阻止 C# 插件访问程序中的主 C# 应用程序?
我有一个程序和一个简单的插件架构,其中插件实现通用接口,主程序加载实现该接口的所有插件。这是迄今为止我发现的最常见的自定义插件架构,所以这就是我正在使用的。
我没有使用 Microsoft 的 MEF,并且我有不这样做的理由。我就这样吧。
问题是,当加载插件时,无论它们对主程序及其表单/类/等有多么“盲目”。它仍然可以访问 System.Windows.Forms.Application ,因此可以访问我的应用程序及其当前运行的表单/方法/控件/等。
我不想要这个。有没有办法限制插件对主应用程序的访问?
编辑:有关该插件的更多信息
我们(我的老板和我)目前正在讨论插件需要做什么。显然它们都需要添加功能,但我们最初决定让每个插件访问当前正在运行的表单,以便它可以直接向表单添加控件和事件。这是基于这样的假设:只有我们(开发人员)才会编写它们。
现在我们正在考虑第三方插件的可能性,显然,最初的设计具有与周围无人的开着的门上的“请勿进入”标志一样的安全性。
或者在万圣节时,一碗单独的九柱游戏上挂着“Take One”的牌子。
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, 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.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
如果您可以在自己的
AppDomains
中运行插件,那肯定会提高隔离级别。但与他们沟通也会变得很痛苦。如果不了解更多插件的用途,就很难知道这是否合适。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.因此,重申一下您最关心的问题:
在开始采用复杂且困难的方法来加载、隔离和限制这些扩展之前,您应该了解一些有关 Windows 和 CLR 的知识。首先,在盒子上运行的任何程序都可以使用许多 Windows API 将代码注入到您的进程中。一旦代码被您或操作系统加载到进程中,访问 CLR 运行时以及加载程序集和/或在现有 AppDomain 中运行代码就相当容易了。
知道这一点后,您应该权衡和平衡您为限制“扩展”所做的努力。如果我构建这样的东西,我会更关心其他事情,而不是操纵我的应用程序状态的恶意扩展代码。例如,您可能会考虑以下事项:
除此之外,你确实无能为力。正如我所说,即使有上述保护措施,任何人都可以攻击您的应用程序。您最关心的应该是不要让用户感到惊讶。因此,建议适当注意您的应用程序运行的代码,但是一旦您的用户授予他们访问权限,这些扩展程序的作用并不是您真正可以完全控制的。
这并不是说 AppDomain 隔离不会为您提供价值,它可能会带来价值;然而,恕我直言,在不限制其功能的情况下对安全性进行足够的限制将被证明是困难的。
更新
正确的,正如我在结束语中所说,您可以限制他们对 AppDomain 内的非托管代码的访问。这也限制了他们开发可用的 Windows 体验的能力。我预计大多数 WinForms 应用程序至少使用一个 PInvoke 调用或非托管 COM 控件。这种限制可能是可以接受的,如果没有更多关于他们试图提供什么功能的信息,我真的不能说。
我想说的是,通过安装和批准该扩展,您的用户将接受允许该扩展运行的责任。该扩展程序的作用以及它可能尝试的恶意程度不是您的责任,当然假设您加载了正确的代码。这就是为什么我建议您将精力集中在运行已批准的代码上,而不是担心该代码在您的流程中后可能会做什么。
So to restate your primary concern:
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:
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
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.
处理此问题的最佳方法是公开记录的插件 API。如果您的插件以完全信任的方式运行,那么即使您在自己的 AppDomain 中运行该插件,它也可以将自身注入回应用程序中 - 那么所需要的只是有人使包装器可用,并且所有插件都回到与它们相同的状态如果您的 API 允许插件以简单、一致和记录的方式提供所需的功能,那么这就是插件开发人员将使用的。
以下是适用于 WPF、Windows 窗体和经典的 Spy++(全部带有源代码)。
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).
一种方法是将插件托管在它们自己的 AppDomain 中。您可以将这些 AppDomain 配置为具有有限的安全性,以防止它们访问主 AppDomain 中的资源。这确实使事情变得更加复杂,但会给你带来你想要的沙箱。
您从 AppDomain 托管获得的另一个好处是,如果您希望刷新插件,您可以加载和卸载这些域,此外您还可以保护您的主 AppDomain 免受“子”域崩溃的影响。
更新
在看到您的更新后。如果您的插件必须直接访问 UI 元素(例如访问表单以添加控件),那么就插件的功能而言,AppDomains 将无济于事。您将无法通过 AppDomain 边界直接访问表单,也无法在一个 AppDomain 中生成控件,然后将它们编组到另一个 AppDomain。
您仍然可以考虑在另一个 AppDomain 中托管插件,但是您需要考虑某种代理机制,以便可以代表插件完成向表单添加控件等操作,而不是让插件直接访问表单。例如,您可以传入一个表单构建器对象,该对象具有诸如
AddButton
之类的方法。然后,代理可以代表主域中的插件执行这些操作。通过这种方式,您可以为插件提供有限的 API,并包含所需的事件。这种方法绝不是微不足道的,但一旦掌握了基础知识,它就不会太复杂。
更新 2
自从使用 AppDomins 推出您自己的插件框架以来,事情已经发生了变化。自 3.5 版本起,.Net 框架现已支持插件:
MAF - 托管插件Framework / System.Addin
它支持插件的AppDomain隔离模式,并具有插件加载器等。无需您自己推出。
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.