沙盒化 AppDomain 中的 SecurityException [英] SecurityException in Sandboxed AppDomain

查看:22
本文介绍了沙盒化 AppDomain 中的 SecurityException的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试使用 C# 作为脚本语言,使用 CSharpCodeProvider(使用 VS2010 和 .NET 4.0).我希望脚本以最少的权限在受限的 AppDomain 中运行.目前,我在尝试实例化 AppDomain 中的类时遇到异常(调用 CreateInstanceAndUnwrap()).下面是一些重现异常的简化代码:

I'm attempting to use C# as a scripting language using CSharpCodeProvider (using VS2010 and .NET 4.0). I want the scripts to be run in a restricted AppDomain with minimal permissions. Currently, I'm getting an exception while trying to instantiate a class in the AppDomain (The call to CreateInstanceAndUnwrap()). Here is some simplified code that reproduces the exception:

using System;
using System.Collections.Generic;
using Microsoft.CSharp;
using System.CodeDom;
using System.CodeDom.Compiler;
using System.Security;
using System.Security.Policy;
using System.Security.Permissions;
using System.Reflection;
using System.Runtime.Remoting;

namespace ConsoleApp
{
    class Program
    {
        static void Main(string[] args)
        {
            // set permissions
            PermissionSet permissions = new PermissionSet(PermissionState.None);
            permissions.AddPermission(new SecurityPermission( SecurityPermissionFlag.Execution));

            AppDomainSetup adSetup = new AppDomainSetup();
            adSetup.ApplicationBase = AppDomain.CurrentDomain.BaseDirectory;

            //Create a list of fully trusted assemblies
            Assembly[] asms = AppDomain.CurrentDomain.GetAssemblies();
            List<StrongName> sns = new List<StrongName>();
            for (int x = 0; x < asms.Length; x++)
            {
                StrongName sn = asms[x].Evidence.GetHostEvidence<StrongName>();
                if (sn != null && sns.Contains(sn) == false)
                    sns.Add(sn);
            }
            //this includes: "mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"            

            AppDomain domain = AppDomain.CreateDomain("NewAppDomain", AppDomain.CurrentDomain.Evidence, adSetup, permissions);//, sns);//, sn4, sn, sn2, sn3);
            try
            {
                String asmName = Assembly.GetExecutingAssembly().FullName;
                String typeName = typeof(ConsoleApp.ScriptRunner).FullName;
                //Throws exception here
                ScriptRunner scriptRunner = domain.CreateInstanceAndUnwrap(asmName, typeName) as ScriptRunner;
            }
            catch (SecurityException se)
            {
                System.Diagnostics.Debug.WriteLine(se.Message);
            }
            catch (Exception ex)
            {
                System.Diagnostics.Debug.WriteLine(ex.Message);
            }
        }
    }

    public class ScriptRunner : MarshalByRefObject
    {      
        public ScriptRunner()
        {
            //A breakpoint placed here is never reached.
            CompilerParameters param;
            param = new CompilerParameters();
            param.CompilerOptions = "";
            param.GenerateExecutable = false;
            param.GenerateInMemory = true;
            param.IncludeDebugInformation = false;

            // C# compiler
            CSharpCodeProvider codeProvider = new CSharpCodeProvider();  

            CompilerResults results = codeProvider.CompileAssemblyFromFile(param, "Danger.cs");           
        }
    }
}

该异常是从 mscorlib 抛出的,它是一个具有内部 System.Security.SecurityExceptionSystem.Reflection.TargetInvocationException.这是一个例外:

The exception is being thrown from mscorlib and it is a System.Reflection.TargetInvocationException that has an inner System.Security.SecurityException. Here is the exception:

System.Reflection.TargetInvocationException was unhandled
  Message=Exception has been thrown by the target of an invocation.
  Source=mscorlib
  StackTrace:
       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)
       at System.RuntimeType.CreateInstanceDefaultCtor(Boolean publicOnly, Boolean skipVisibilityChecks, Boolean skipCheckThis, Boolean fillCache)
       at System.Activator.CreateInstance(Type type, Boolean nonPublic)
       at System.RuntimeType.CreateInstanceImpl(BindingFlags bindingAttr, Binder binder, Object[] args, CultureInfo culture, Object[] activationAttributes)
       at System.Activator.CreateInstance(Type type, BindingFlags bindingAttr, Binder binder, Object[] args, CultureInfo culture, Object[] activationAttributes)
       at System.Activator.CreateInstance(String assemblyName, String typeName, Boolean ignoreCase, BindingFlags bindingAttr, Binder binder, Object[] args, CultureInfo culture, Object[] activationAttributes, Evidence securityInfo, StackCrawlMark& stackMark)
       at System.Activator.CreateInstance(String assemblyName, String typeName)
       at System.AppDomain.CreateInstance(String assemblyName, String typeName)
       at System.AppDomain.CreateInstanceAndUnwrap(String assemblyName, String typeName)
       at System.AppDomain.CreateInstanceAndUnwrap(String assemblyName, String typeName)
       at ConsoleApp.Program.Main(String[] args) in C:\Documents and Settings\NaultyCS\my documents\visual studio 2010\Projects\ConsoleApplication4\ConsoleApplication4\Program.cs:line 46
       at System.AppDomain._nExecuteAssembly(RuntimeAssembly assembly, String[] args)
       at System.AppDomain.ExecuteAssembly(String assemblyFile, Evidence assemblySecurity, String[] args)
       at Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly()
       at System.Threading.ThreadHelper.ThreadStart_Context(Object state)
       at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean ignoreSyncCtx)
       at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
       at System.Threading.ThreadHelper.ThreadStart()
  InnerException: System.Security.SecurityException
       Message=Request failed.
       Source=ConsoleApplication4
       GrantedSet=<PermissionSet class="System.Security.PermissionSet"
version="1">
<IPermission class="System.Security.Permissions.SecurityPermission, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"
version="1"
Flags="Execution"/>
</PermissionSet>

       PermissionState=<PermissionSet class="System.Security.PermissionSet"
version="1"
Unrestricted="true"/>

       RefusedSet=""
       Url=file:///C:/Documents and Settings/NaultyCS/my documents/visual studio 2010/Projects/ConsoleApplication4/ConsoleApplication4/bin/Debug/ConsoleApplication4.EXE
       StackTrace:
            at ConsoleApp.ScriptRunner..ctor()
       InnerException: 

所以在我看来,mscorlib 要求完全信任.我已将其添加为完全受信任的程序集,但没有任何效果.如果我将权限设置为不受限制,则上述代码有效:

So it appears to me that mscorlib is demanding full trust. I've added it as a fully trusted assembly, but it has no effect. The above code works if I set the permissions to unrestricted:

PermissionSet permissions = new PermissionSet(PermissionState.Unrestricted);

但我想限制 AppDomain.我在这里做错了什么?

But I want to restrict the AppDomain. What am I doing wrong here?

推荐答案

抱歉编辑晚了.请尝试以下操作.我使用测试应用程序在 Visual Studio 中启动并运行它.附带说明一下,我个人不喜欢构造函数中的逻辑",因为真正的错误往往会被隐藏起来.以下步骤将 Compile 逻辑从构造函数移至新方法.

Sorry for the late edit. Try the following. I got it up and running in Visual Studio with a test app. On a side note, I personally do not like "logic" in constructors because the true error tends to get a little hidden. The steps below have the Compile logic moved from the constructor to a new method.

  1. 确保您的控制台应用程序具有 StrongName/Signed.
  2. 包括 sns 变量作为调用 AppDomain.CreateDomain 的最后一个参数.LinkDemand 权限需要完全信任您的 ConsoleApp.

  1. Ensure your Console App has a StrongName / Signed.
  2. Include the sns variable as the last parameter to call AppDomain.CreateDomain. The LinkDemand Permission requires your ConsoleApp to be fully trusted.

AppDomain domain = AppDomain.CreateDomain("NewAppDomain", AppDomain.CurrentDomain.Evidence, adSetup, permissions, sns.ToArray());

  • 更改 asmName 以使用程序集的完整文件路径.

  • Change the asmName to use the Full File Path to your assembly.

    String asmName = Assembly.GetExecutingAssembly().ManifestModule.FullyQualifiedName;
    

  • 删除对以下两行代码的 CreateInstanceAndUnwrap 调用

  • Delete the CreateInstanceAndUnwrap call to the following 2 lines of code

    var handle = Activator.CreateInstanceFrom(domain, asmName, typeName);
    var scriptRunner = (ScriptRunner)handle.Unwrap();
    

  • 将所有代码从构造函数移动到新方法,例如Start".

  • Move all your code from the Constructor to a new method such as "Start".

    添加用于调用 Start 方法的行.

    Add the line to call the Start method.

    scriptRunner.Start();
    

  • 添加 FileIOPermission 以读取您的 Danger.cs 文件.

  • Add the FileIOPermission to read your Danger.cs file.

    permissions.AddPermission(new FileIOPermission(PermissionState.None) { AllFiles = FileIOPermissionAccess.Read });
    

  • 这篇关于沙盒化 AppDomain 中的 SecurityException的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

    查看全文
    登录 关闭
    扫码关注1秒登录
    发送“验证码”获取 | 15天全站免登陆