通过限制AppDomain中的文件系统和网络插件访问(Restrict plugin access

2019-07-04 03:22发布

我问前一阵子如何限制插件访问(我想阻止他们写入到磁盘或网络),我被告知使用的AppDomain 。 我已经搜索并尝试和失败如何得到这个工作。

任何人都可以提供一些信息,这样我就可以上手,简单地说让不允许写入文件或网络应用程序域。

Answer 1:

我想这是你所需要的,如果我理解正确的话你的观点。

System.Security.PermissionSet ps = 
    new System.Security.PermissionSet(System.Security.Permissions.PermissionState.None);
ps.AddPermission(new System.Security.Permissions.FileIOPermission(System.Security.Permissions.FileIOPermissionAccess.NoAccess, "C:\\"));
System.Security.Policy.PolicyLevel pl = System.Security.Policy.PolicyLevel.CreateAppDomainLevel();
pl.RootCodeGroup.PolicyStatement = new System.Security.Policy.PolicyStatement(ps);
AppDomain.CurrentDomain.SetAppDomainPolicy(pl);
System.Reflection.Assembly myPluginAssembly = AppDomain.CurrentDomain.Load("MyPluginAssembly");

这是更准确地你是什么意思?

请注意,您可以提供字符串的方含,你不希望插件访问路径的数组。 如果初始化的FileIOPermission类的新实例时,您可以提供。

让我知道,如果这有助于。 :-)



Answer 2:

对于.NET Framework 4.0中,请遵循下面的代码这个 MSDN文章。

下面的示例实现前一节中的程序。 在这个例子中,一个在Visual Studio解决方案命名为Sandboxer项目还包含一个名为UntrustedCode项目,它实现了类UntrustedClass。 此方案假定您已经下载了包含有望返回true或false,以表明您提供的号码是否是斐波那契数的方法库程序集。 取而代之的是,该方法尝试读取您的计算机中的文件。 下面的示例示出了不可信代码。

using System;
using System.IO;
namespace UntrustedCode
{
    public class UntrustedClass
    {
        // Pretend to be a method checking if a number is a Fibonacci
        // but which actually attempts to read a file.
        public static bool IsFibonacci(int number)
        {
           File.ReadAllText("C:\\Temp\\file.txt");
           return false;
        }
    }
}

下面的示例示出了执行不可信代码的Sandboxer应用程序代码。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Security;
using System.Security.Policy;
using System.Security.Permissions;
using System.Reflection;
using System.Runtime.Remoting;

//The Sandboxer class needs to derive from MarshalByRefObject so that we can create it in another 
// AppDomain and refer to it from the default AppDomain.
class Sandboxer : MarshalByRefObject
{
    const string pathToUntrusted = @"..\..\..\UntrustedCode\bin\Debug";
    const string untrustedAssembly = "UntrustedCode";
    const string untrustedClass = "UntrustedCode.UntrustedClass";
    const string entryPoint = "IsFibonacci";
    private static Object[] parameters = { 45 };
    static void Main()
    {
        //Setting the AppDomainSetup. It is very important to set the ApplicationBase to a folder 
        //other than the one in which the sandboxer resides.
        AppDomainSetup adSetup = new AppDomainSetup();
        adSetup.ApplicationBase = Path.GetFullPath(pathToUntrusted);

        //Setting the permissions for the AppDomain. We give the permission to execute and to 
        //read/discover the location where the untrusted code is loaded.
        PermissionSet permSet = new PermissionSet(PermissionState.None);
        permSet.AddPermission(new SecurityPermission(SecurityPermissionFlag.Execution));

        //We want the sandboxer assembly's strong name, so that we can add it to the full trust list.
        StrongName fullTrustAssembly = typeof(Sandboxer).Assembly.Evidence.GetHostEvidence<StrongName>();

        //Now we have everything we need to create the AppDomain, so let's create it.
        AppDomain newDomain = AppDomain.CreateDomain("Sandbox", null, adSetup, permSet, fullTrustAssembly);

        //Use CreateInstanceFrom to load an instance of the Sandboxer class into the
        //new AppDomain. 
        ObjectHandle handle = Activator.CreateInstanceFrom(
            newDomain, typeof(Sandboxer).Assembly.ManifestModule.FullyQualifiedName,
            typeof(Sandboxer).FullName
            );
        //Unwrap the new domain instance into a reference in this domain and use it to execute the 
        //untrusted code.
        Sandboxer newDomainInstance = (Sandboxer) handle.Unwrap();
        newDomainInstance.ExecuteUntrustedCode(untrustedAssembly, untrustedClass, entryPoint, parameters);
    }
    public void ExecuteUntrustedCode(string assemblyName, string typeName, string entryPoint, Object[] parameters)
    {
        //Load the MethodInfo for a method in the new Assembly. This might be a method you know, or 
        //you can use Assembly.EntryPoint to get to the main function in an executable.
        MethodInfo target = Assembly.Load(assemblyName).GetType(typeName).GetMethod(entryPoint);
        try
        {
            //Now invoke the method.
            bool retVal = (bool)target.Invoke(null, parameters);
        }
        catch (Exception ex)
        {
            // When we print informations from a SecurityException extra information can be printed if we are 
            //calling it with a full-trust stack.
            (new PermissionSet(PermissionState.Unrestricted)).Assert();
            Console.WriteLine("SecurityException caught:\n{0}", ex.ToString());
            CodeAccessPermission.RevertAssert();
            Console.ReadLine();
        }
    }
}


Answer 3:

如果您使用的插件,你或许会知道的代理。

虽然通过代理加载你的组件,你可以指定通过LoadAssembly()方法使这一特定组件的安全策略级别,如果我没有记错。 换句话说,这是通过反射来完成。

我知道我的答案是没有那么多的细节,但我希望它会给你在哪里寻找你的解决方案的想法。 我将眼睛去寻找关于这个问题的进一步的细节,这样我可能是更好的帮助。 =)

希望你能分享你的发现,当你已经做到了。



文章来源: Restrict plugin access to file system and network via appdomain
标签: c# appdomain