首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >在沙箱应用程序域- SecurityException中加载程序集

在沙箱应用程序域- SecurityException中加载程序集
EN

Stack Overflow用户
提问于 2014-09-30 19:48:09
回答 2查看 3.8K关注 0票数 1

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

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

我用的是本教程

创建沙箱Appdomain

代码语言:javascript
复制
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;
}

创建沙箱(Sandboxer类型为MarshalByRefObject):

代码语言:javascript
复制
string physicalPath = HttpContext.Current.Request.PhysicalApplicationPath + @"App_Data\";
 AppDomain Sandbox = createAppdomain(physicalPath);

// http://msdn.microsoft.com/en-us/library/dd413384(v=vs.110).aspx
ObjectHandle handle = Activator.CreateInstanceFrom(
     Sandbox,
     typeof(Sandboxer).Assembly.ManifestModule.FullyQualifiedName,
     typeof(Sandboxer).FullName,
     true,
     BindingFlags.Public | BindingFlags.Instance | BindingFlags.CreateInstance,
     null,
    // byte[] rawAssembly
     new object[] { rawAssembly },
     null,
     null);
Sandboxer newDomainInstance = (Sandboxer)handle.Unwrap();   

string s = newDomainInstance.callMethod();

加载Assembly,调用该方法:

代码语言:javascript
复制
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;
}

StackTrace:

代码语言:javascript
复制
"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) ..."

我错过了什么?(对不起,我的英语。)

编辑:尝试将该行添加到类中以授予完全权限:

代码语言:javascript
复制
[PermissionSet(SecurityAction.Assert, Unrestricted = true)]

在这之后,object obj = Activator.CreateInstance(MyClass);工作得很好。我需要沙箱,所以这不是解决办法。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2014-10-04 19:39:07

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

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

票数 1
EN

Stack Overflow用户

发布于 2014-11-13 15:14:07

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

异常显示我的沙箱DLL是问题的根源,这并没有帮助。因为结果都是MSDN文档中的一个句子:

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

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

所以我用Load(byte[])替换了Load(Byte[], null, SecurityContextSource.CurrentAppDomain),现在它的工作方式类似于LoadFrom

票数 4
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/26128893

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档