2013-10-06 3 views
3

Цель: Мне нужно запустить код в качестве AppDomain с очень ограниченными правами - это не должно иметь никакого доступа ни к чему вообще фантазии или небезопасным, за исключением несколько вспомогательных методов, которые Я определил в другом месте.исключение кода безопасности доступа в ограниченном AppDomain

Что я сделал: Я создаю песочницу AppDomain с необходимыми основными правами, а также созданием прокси-объект, который запускает код:

static AppDomain CreateSandbox() 
{ 
    var e = new Evidence(); 
    e.AddHostEvidence(new Zone(SecurityZone.Internet)); 

    var ps = SecurityManager.GetStandardSandbox(e); 
    var security = new SecurityPermission(SecurityPermissionFlag.Execution); 

    ps.AddPermission(security); 

    var setup = new AppDomainSetup { 
     ApplicationBase = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location) 
    }; 
    return AppDomain.CreateDomain("Sandbox" + DateTime.Now, null, setup, ps); 
} 

public class Proxy : MarshalByRefObject 
{ 
    public Proxy() { } 

    public DoStuff() 
    { 
     // perform custom operation requiring permission 
     HelperAssembly.HelperMethods.Method1(); 

     // do other stuff with low permission level 
     ... 
     ... 
     ... 
    } 
} 

Я положил вспомогательные методы в выделенном строгим именем сборки и пометив их и их контейнер класса с [SecuritySafeCritical]:

// HelperAssembly.dll 

namespace HelperAssembly 
{ 
    [SecuritySafeCritical] 
    public class HelperMethods 
    { 
     [SecuritySafeCritical] 
     public static void Method1() 
     { 
      new SecurityPermission(SecurityPermissionFlag.UnmanagedCode) 
       .Assert(); 
      try 
      { 
       // logic requiring unmanaged code 
       ... 
      } 
      finally 
      { 
       CodeAccessSecurity.RevertAll(); 
      } 

     } 
    } 
} 

Затем я загружаю хелперов сборки в песочнице AppDomain и запустить Proxy.DoStuff(), ожидая его выполнить вспомогательный метод и быть на своем пути:

var appDomain = CreateSandbox(); 

appDomain.Load(typeof(HelperAssembly.HelperMethods).Assembly.FullName); 

var proxy = (Proxy)sandbox.CreateInstance(
    typeof(Proxy).Assembly.FullName, 
    typeof(Proxy).FullName).Unwrap(); 

proxy.DoStuff(); 

Однако запуск кода вызывает исключение на линии Assert() в методе хелперов:

Необработанное исключение: System.InvalidOperationException: не удается выполнить CAS Утверждает в безопасности прозрачных методов

Что является причиной такого поведения и как я могу добиться того, что я пытаюсь сделать? Насколько я понимаю, код в ненадежном AppDomain прозрачен для безопасности, а код в вспомогательной сборке является безопасным с точки зрения безопасности, то есть он должен иметь возможность запрашивать разрешения с помощью Assert().

У меня, очевидно, отсутствует кусочек головоломки, поэтому кто-то с лучшим пониманием безопасности доступа к коду объясняет, что происходит не так. Любая помощь приветствуется.

+1

Имеет ли ваша доверенная сборка атрибут AllowPartiallyTrustedCallers? IIRC используется для файлов SecuritySafeCritical ... Кроме того, вы не используете аргумент 'FullTrustAssemblies'' CreateDomain'. Это нормально? – Medinoc

+1

Атрибут [SecuritySafeCritical] игнорируется, если вы не указали название сборки. Project + Properties, вкладка Signing. –

+0

@Medinoc, правильно! Мне нужно было добавить вспомогательную сборку как доверенную в AppDomain.Create и отметить ее как [AllowPartiallyTrustedCallers]. Пожалуйста, продвигайте свой комментарий к ответу, чтобы я мог отметить его как правильно. – staafl

ответ

4

Ваш «надежный» сбор должен иметь атрибут AllowPartiallyTrustedCallers для SecuritySafeCritical, подлежащий вызову через границу сборки. Он также должен быть добавлен к fullTrustAssemblies в ваш звонок до CreateDomain.