Отражение не ограничено, даже если оно не в наборе грантов - PullRequest
5 голосов
/ 09 февраля 2012

Я сейчас пытаюсь создать очень очень простую песочницу .

У некоторого класса A есть метод Execute , который вызываетсяв другом AppDomain, чем вызывающий.

Проблема в том, что у меня есть только разрешение на выполнение, и в любом случае возможно отражение.

Это пример кода:

[Serializable]
public class A : MarshalByRefObject
{
    public void Execute()
    {
        typeof(A).GetConstructor(Type.EmptyTypes).Invoke(null); // Fine - Why?
        typeof(B).GetConstructor(Type.EmptyTypes).Invoke(null); // Fine - Why?
    }
}

public class B
{

}

class Program
{
    static void Main(string[] args)
    {
        PermissionSet set = new PermissionSet(PermissionState.None);

        SecurityPermission security = new SecurityPermission(SecurityPermissionFlag.Execution);
        set.AddPermission(security);

        Evidence evidence = new Evidence();
        AppDomainSetup setup = new AppDomainSetup();
        setup.ApplicationBase = "C:";

        AppDomain domain = AppDomain.CreateDomain
        (
            "hello",
            evidence,
            setup,
            set
        );

        A a = (A)domain.CreateInstanceAndUnwrap(Assembly.GetExecutingAssembly().FullName, typeof(A).FullName);
        a.Execute();
    }
}

ОБНОВЛЕНИЕ

Отлично! Наконец я это сделал.

Благодаря вашим советам я пересмотрел свой код и хотел бы поделиться им с вами, поскольку мне было трудно понять, как не использовать CAS, но использовать такие же разрешенияв новой модели безопасности .NET 4.x и выше, а также способ песочницы с использованием AppDomain.Вот и все:

using System;
using System.Reflection;
using System.Security;
using System.Security.Permissions;
using System.Security.Policy;

namespace ConsoleApplication1
{
    [Serializable]
    public class A : MarshalByRefObject
    {
        public void Execute()
        {
        B b = new B();

        // BOMB! ERROR! Security demand: reflection forbidden!
        b.GetType()
                .GetMethod("ExecuteInB", BindingFlags.Instance | BindingFlags.NonPublic)
                    .Invoke(b, null);
        }
    }

    public class B
    {
        private void ExecuteInB()
        {

        }
    }

    class Program
    {
        static void Main(string[] args)
        {
            PermissionSet set = new PermissionSet(PermissionState.None);

            SecurityPermission security = new SecurityPermission(PermissionState.None);
            security.Flags = SecurityPermissionFlag.Execution;
            set.AddPermission(security);

            Evidence evidence = new Evidence();
            AppDomainSetup setup = new AppDomainSetup();
            setup.ApplicationBase = "C:";

            AppDomain domain = AppDomain.CreateDomain
            (
                "hola",
                evidence,
                setup,
                set
            );

            A a = (A)domain.CreateInstanceAndUnwrap("ConsoleApplication1", "ConsoleApplication1.A");
            a.Execute();
        }
    }
}

Ответы [ 3 ]

11 голосов
/ 10 февраля 2012

Разрешение на отражение требуется при вызове недоступного члена. A и B являются открытыми типами с открытыми конструкторами и поэтому доступны. Вы можете вызывать эти конструкторы без отражения, поэтому при попытке сделать это с отражением не требуется.

Более того, использование отражения для обнаружения всегда допустимо; Вы можете опросить объект и запросить у него список его закрытых членов, даже без разрешения на рефлексию. Только когда вы пытаетесь вызвать вызов частного участника, требуется разрешение.

2 голосов
/ 10 февраля 2012

Из Библиотека MSDN : ReflectionPermission контролирует доступ к непубличным типам и членам через API-интерфейсы System.Reflection.Без ReflectionPermission код может использовать отражение для доступа только к открытым элементам объектов.

1 голос
/ 10 февраля 2012

Вы проверяли свой код на .net 3.5? В .NET 4 появился новый модель безопасности, где наборы разрешений больше не влияют на sansbox. Я был серьезно укушен этим, когда захотел протестировать код, предназначенный для выполнения в контекстах со средним доверием, в процессе полного доверия .net.

Возможное решение состоит в том, чтобы заставить CLR использовать унаследованную модель безопасности, а затем явно запретить ReflectionPermission в новом домене приложений.

Извините за частичный ответ, я сейчас на мобильном, но завтра вернусь. Надеюсь, это поможет вам начать.

...