C# 正在沙盒Appdomain中加载程序集-SecurityException

C# 正在沙盒Appdomain中加载程序集-SecurityException,c#,sandbox,appdomain,C#,Sandbox,Appdomain,我想从运行时创建的程序集调用方法。它是部分受信任的代码,所以我想为它创建一个沙箱应用程序域 我用Roslyn创建程序集,结果是一个字节[]。我可以在默认的Appdomain中加载它并从中调用,它可以正常工作。问题是(我想)沙箱 我用过 创建沙盒Appdomain: private AppDomain createAppdomain(string location) { AppDomain currentAppdomain = AppDomain.CurrentDomain;

我想从运行时创建的程序集调用方法。它是部分受信任的代码,所以我想为它创建一个沙箱应用程序域

我用Roslyn创建程序集,结果是一个
字节[]
。我可以在默认的
Appdomain
中加载它并从中调用,它可以正常工作。问题是(我想)沙箱

我用过

创建沙盒
Appdomain

private AppDomain createAppdomain(string location)
{
     AppDomain currentAppdomain = AppDomain.CurrentDomain;

     // Create the permission set to be granted to the untrusted application
     Evidence ev = new Evidence();
     ev.AddHostEvidence(new Zone(SecurityZone.Internet));
     PermissionSet internetPS = SecurityManager.GetStandardSandbox(ev);
     var platform = Assembly.GetExecutingAssembly();
     internetPS.AddPermission(new FileIOPermission(FileIOPermissionAccess.Read | FileIOPermissionAccess.PathDiscovery, Path.GetDirectoryName(platform.Location)));

     // Sign the assembly that contains the hosting class (named Sandboxer in this example) that calls the untrusted code
     // .NET Framework assemblies such as mscorlib and System.dll do not have to be added to the full-trust list
     // because they are loaded as fully trusted from the global assembly cache.
     StrongName[] fullTrustAssembly = new StrongName[1];
     fullTrustAssembly[0] = typeof(Sandboxer).Assembly.Evidence.GetHostEvidence<StrongName>();

     // Initialize the AppDomainSetup parameter of the CreateDomain method
     //  The ApplicationBase property is an important setting,
     // and should be different from the ApplicationBase property for the AppDomain of the hosting application.
     // If the ApplicationBase settings are the same,
     // the partial-trust application can get the hosting application to load (as fully trusted) an exception it defines, thus exploiting it.
     AppDomainSetup adSetup = new AppDomainSetup();
     adSetup.ApplicationBase = Path.GetFullPath(location);


     // Call the CreateDomain(String, Evidence, AppDomainSetup, PermissionSet, StrongName[]) method overload to create the application domain
     // http://msdn.microsoft.com/en-us/library/ms130766(v=vs.110).aspx
     AppDomain newDomain = AppDomain.CreateDomain("Sandbox", null, adSetup, internetPS, fullTrustAssembly);

     return newDomain;
}
加载
程序集
,调用以下方法:

private string callMethod()
{   
     // No Exception thrown yet, but some problems with the Evidence:
     // Evidence    'asm.Evidence' threw an exception of type 'System.Security.SecurityException'   System.Security.Policy.Evidence {System.Security.SecurityException}
     //"Request for the permission of type 'System.Security.Permissions.SecurityPermission, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089' failed."
     Assembly asm = Assembly.Load(rawAssembly);

     Type MyClass = asm.GetType(myClassName);

     // In this line I get the Exception:
     // System.Security.SecurityException
     // "Request failed."
     object obj = Activator.CreateInstance(MyClass);

     MethodInfo mi = MyClass.GetMethod(myMethodName);
     mi.Invoke(obj, null);

     // some code

     return s;
}
堆栈跟踪:

"at System.RuntimeTypeHandle.CreateInstance(RuntimeType type, Boolean publicOnly, Boolean noCheck, Boolean& canBeCached, RuntimeMethodHandleInternal& ctor, Boolean& bNeedSecurityCheck)
at System.RuntimeType.CreateInstanceSlow(Boolean publicOnly, Boolean skipCheckThis, Boolean fillCache, StackCrawlMark& stackMark)\
at System.RuntimeType.CreateInstanceDefaultCtor(Boolean publicOnly, Boolean skipCheckThis, Boolean fillCache, StackCrawlMark& stackMark)\r\n   at System.Activator.CreateInstance(Type type, Boolean nonPublic)
at System.Activator.CreateInstance(Type type) ..."
我错过了什么?(对不起,我的英语不好。)

编辑: 试图将此行添加到类以授予完全权限:

[PermissionSet(SecurityAction.Assert, Unrestricted = true)]

在此之后
objectobj=Activator.CreateInstance(MyClass)工作正常。我需要沙盒,所以这不是一个解决方案。

您的问题是在使用不受信任的堆栈调用完全受信任时加载的沙盒程序集。因此,您在激活过程中的某个地方遇到了安全异常(根据您的代码,无法100%确定原因)。解决方案与您发现的完全一样,就是将断言添加到函数中。这将允许此函数以完全信任的方式执行(断言将阻止堆栈遍历),但加载的程序集部分受信任,因此仍将被沙盒


如果您这样做,您需要确保沙盒代码不能与该方法交互,因此可能会滥用它。您可以通过将函数标记为SecurityCritical来实现这一点,这样只有完全受信任的代码才能与函数交互

您的问题是在使用不受信任的堆栈调用完全受信任时加载的沙盒程序集。因此,您在激活过程中的某个地方遇到了安全异常(根据您的代码,无法100%确定原因)。解决方案与您发现的完全一样,就是将断言添加到函数中。这将允许此函数以完全信任的方式执行(断言将阻止堆栈遍历),但加载的程序集部分受信任,因此仍将被沙盒


如果您这样做,您需要确保沙盒代码不能与该方法交互,因此可能会滥用它。您可以通过将函数标记为SecurityCritical来实现这一点,这样只有完全受信任的代码才能与函数交互

我遇到了同样的问题,头撞了一个小时。 因为我在另一个例子中同样的代码运行良好! 所以我开始删除一些东西,直到我发现唯一的区别在于加载程序集的方式:
Assembly.LoadFrom
工作正常
Assembly.Load(byte[])
总是给我一个安全异常

异常表明我的沙盒DLL是问题的根源,这没有帮助。因为事实证明,在MSDN文档中,这些都是一句话:

使用此方法加载的程序集的信任级别与调用程序集的信任级别相同。要从具有应用程序域信任级别的字节数组加载程序集,请使用load(byte[],byte[],SecurityContextSource)方法重载

哎呀!我认为,在权限非常有限的appdomain中加载具有“完全信任”的程序集(而不在完全信任列表中)会使CLR不高兴。从加载的程序集执行的第一行->砰!(这就是为什么我断言异常令人困惑:它提到“错误的”DLL作为异常源)


因此,我将
加载(byte[])
替换为
加载(byte[],null,SecurityContextSource.CurrentAppDomain)
,现在它可以像
加载一样从

运行。我遇到了同样的问题,并撞了我一个小时的头。 因为我在另一个例子中同样的代码运行良好! 所以我开始删除一些东西,直到我发现唯一的区别在于加载程序集的方式:
Assembly.LoadFrom
工作正常
Assembly.Load(byte[])
总是给我一个安全异常

异常表明我的沙盒DLL是问题的根源,这没有帮助。因为事实证明,在MSDN文档中,这些都是一句话:

使用此方法加载的程序集的信任级别与调用程序集的信任级别相同。要从具有应用程序域信任级别的字节数组加载程序集,请使用load(byte[],byte[],SecurityContextSource)方法重载

哎呀!我认为,在权限非常有限的appdomain中加载具有“完全信任”的程序集(而不在完全信任列表中)会使CLR不高兴。从加载的程序集执行的第一行->砰!(这就是为什么我断言异常令人困惑:它提到“错误的”DLL作为异常源)


因此,我将
Load(byte[])
替换为
Load(byte[],null,SecurityContextSource.CurrentAppDomain)
现在它的工作原理类似于加载自

您可能希望从不受限制的/everywhere权限开始,查看代码是否工作,然后开始逐个删除,以查看哪一个失败。由于某些原因,我无法(尚未)确定,如果您使用Assembly.Load(字节[])加载程序集,您的沙盒程序集将尝试要求完全信任,但无法获得它。即使它位于完全信任程序集列表中。如果改为使用Assembly.LoadFrom(字符串),它将按预期工作。。。想想看吧我想,即使我不完全相信,我可能会自己提出一个问题。。请看下面我的答案!您可能希望从不受限制的/everywhere权限开始,以查看代码是否工作,然后开始逐个删除以查看哪一个失败。由于某些原因,我无法(尚未)确定,如果您使用Assembly.Load(byte[])加载程序集,您的沙盒程序集将尝试要求完全信任,但无法获得它。即使它位于完全信任程序集列表中。如果改为使用Assembly.LoadFrom(字符串),它将按预期工作。。。想想看吧我想,即使我不完全相信,我可能
[PermissionSet(SecurityAction.Assert, Unrestricted = true)]