C# .NET Framework 4.x中的插件系统安全性(不含CAS)

C# .NET Framework 4.x中的插件系统安全性(不含CAS),c#,.net,security,plugins,permissions,C#,.net,Security,Plugins,Permissions,我想实现的是一个具有以下功能的插件系统: 从我(开发人员)可能不信任但安装插件的最终用户信任的源加载外部插件 在特定范围内授予每个插件的权限;e、 一个插件可能有从特定位置读取文件的权限,而其他插件可能被允许连接到特定的网站位置 每插件权限的一个特例:与另一个对象交互,很可能是作为接口实例提供的,而不访问其任何非公共成员(甚至不使用秘密反射技术) 在插件代码造成任何伤害之前,防止最终用户不同意的操作,例如访问非公共成员或在文件系统上操作 在我的搜索过程中,我发现了很多涉及代码访问安全性的解决

我想实现的是一个具有以下功能的插件系统:

  • 从我(开发人员)可能不信任但安装插件的最终用户信任的源加载外部插件
  • 在特定范围内授予每个插件的权限;e、 一个插件可能有从特定位置读取文件的权限,而其他插件可能被允许连接到特定的网站位置
  • 每插件权限的一个特例:与另一个对象交互,很可能是作为接口实例提供的,而不访问其任何非公共成员(甚至不使用秘密反射技术)
  • 在插件代码造成任何伤害之前,防止最终用户不同意的操作,例如访问非公共成员或在文件系统上操作
在我的搜索过程中,我发现了很多涉及代码访问安全性的解决方案,据我所知,这些解决方案在.NET4.x中已经过时了。我还在MSDN页面上读了一些关于新安全模型的内容,在这里似乎是必要的;但是,我找不到任何示例来说明如何应用这些代码。我的猜测是,这将涉及创建单独的AppDomain,并可能使用主要权限,但这只是我所知的范围

另一方面,我还发现有人提到只需要强命名程序集,但我不认为这就足够了。如果我没有弄错的话,一个强大的命名优势是插件开发人员可以通过使用自己的私钥对程序集哈希进行签名来证明自己的身份,而其他人可以使用众所周知的可信公钥进行检查。然而,单凭这一点似乎太不灵活了,因为它要么需要开发人员亲自决定应该信任谁的代码,要么只信任任何学会对其程序集进行签名的人

我将非常感谢一个使用最新安全模型的安全管理代码的好例子。我目前的想法是:

  • 用于暴露潜在敏感操作(如A和B)的服务接口
  • 服务的虚拟实现,重点是防止未经授权执行这些操作
  • 来自不同程序集的两个插件,一个具有执行操作A的权限,另一个具有执行操作B的权限
  • 一种应用程序,用于设置服务、加载带有插件的程序集并尝试对每个程序集执行操作,从而阻止未经授权的操作并正确执行授权的操作
  • 在应用程序中运行时,插件本身都不能访问一般敏感的API,如文件I/O或网络,但应该可以通过服务访问
  • 所有这些,同时尽可能密切地遵循(与2010年SO提出的基于CAS的解决方案相反)

当然,如果能以更好的方式实现目标,欢迎您提出替代体系结构的建议。

您提出的问题在多个层面上都很困难

我见过的最接近这一点的是一个被遗忘已久的Microsoft项目,名为。在该项目中,您使用.net语言编写一个生物代码,构建它,然后提交包含该生物的程序集,使其生活在用.net 1.0编写的terrarium服务器上。对于微软的开发者来说,创建一个任何用户都可以运行代码的环境是一个挑战,但是要做到安全和友好。他们创建了一个工具来禁止在汇编中使用某些类型。它被称为

过去,我曾尝试使用应用程序域实现同样的目标,但没有取得多大成功

我仍不时地思考,实现这一任务的最佳方式是什么。这是可能的,Android和iOS就是这样工作的,但它要求我尽可能地编写整个操作系统或框架

我计划创建一个AppDomain并将我的插件加载程序加载到此域。然后加载程序通过劫持程序集加载程序加载插件程序集和它试图加载的所有程序集。加载程序集时,它使用AsmCheck.vNext检查它是否做了一些可疑的事情。对于加载的每个程序集,它都使用IoC容器(如)来限制对框架的访问

程序集的验证在我这方面通过使用插件注册表检查强名称或检查代码签名证书来完成

在你看到Confuser或其继任者之前,一切似乎都很好。它通过将方法转换为自初始化静态委托来创建访问方法的代理类型,该委托引用的方法不是名称而是引用id。现在,我如何分析和/或限制对此方法的访问

或者,您可以完全阻止System.IO命名空间,并提供自己的IO库,但如何限制其中一个使用PInvoke并调用GetProcAddress,以便它可以访问ReadFile、WriteFile等

要处理的案件太多了,这只是冰山一角。如果您必须严格限制插件的使用,那么您必须编写自己的框架或提供类似lua的脚本语言

你可以尝试应用容器化。每个插件都被加载到一个特殊的容器中,并与应用程序对话以执行需要权限的任务。除此之外,运行在容器中的代码认为容器就是整个计算机

总有一天我希望有人能以一种简单有效的方式解决这个问题


附言:我的答案不是答案。这是一个答案,因为它不适合注释。

您可以强制插件在单独的进程中运行,并仅使用RPC与应用程序交互。 这样,他们将无法访问除您通过API提供的内容之外的任何内容

Android操作系统也做了同样的事情来为应用程序展示功能


CAS本身并没有被弃用,但不鼓励将其用作受信任代码(应用程序)和不受信任代码(插件)之间的安全边界。据我所知