Obecnie próbuję stworzyć bardzo prostą piaskownicę.

Niektóre klasy A mają metodę Wykonaj, która jest wywoływana w innym AppDomain niż wywołujący.

Problem polega na tym, że mam tylko pozwolenie na wykonanie, a refleksja i tak jest możliwa.

Oto przykładowy kod:

[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();
    }
}

AKTUALIZACJA

Świetnie! W końcu to zrobiłem.

Dzięki waszym radom poprawiłem swój kod i chciałbym się nim z wami podzielić, ponieważ trudno mi było zrozumieć, jak nie używać CAS, ale używać tego samego rodzaju uprawnień w nowym .NET 4 Model bezpieczeństwa .x i nowszy oraz sposób piaskownicy przy użyciu AppDomain. Otóż ​​to:

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();
        }
    }
}
5
Matías Fidemraizer 9 luty 2012, 23:57

3 odpowiedzi

Najlepsza odpowiedź

W przypadku wywołania niedostępnego członka wymagane jest zezwolenie na odbicie. A i B są typami publicznymi z publicznymi konstruktorami, a więc są dostępne. Możesz wywołać te konstruktory bez odbicia, więc nie ma żadnych wymagań, gdy próbujesz to zrobić z odbiciami.

Co więcej, używanie refleksji do odkrywania jest zawsze legalne; możesz przesłuchać obiekt i poprosić go o listę jego prywatnych członków, nawet bez zezwolenia na odbicie. Wymagane jest zezwolenie tylko wtedy, gdy próbujesz wywołać wywołanie członka prywatnego.

11
Eric Lippert 10 luty 2012, 01:26

Z Biblioteki MSDN: ReflectionPermission kontroluje dostęp do niepublicznych typów i członków za pośrednictwem interfejsów API System.Reflection. Bez ReflectionPermission kod może używać odbicia, aby uzyskać dostęp tylko do publicznych członków obiektów.

2
Michael Liu 10 luty 2012, 01:27

Czy sprawdziłeś swój kod w .net 3.5? Platforma .NET 4 ma nowy model zabezpieczeń, w którym zestawy dotacji nie wpływają już na sansbox. Byłem tym poważnie ugryziony, gdy chciałem przetestować kod przeznaczony do uruchamiania w kontekstach o średnim zaufaniu w procesie pełnego zaufania .net.

Możliwym rozwiązaniem jest zmuszenie środowiska CLR do korzystania ze starszego modelu zabezpieczeń, a następnie jawne odrzucenie ReflectionPermission w nowej AppDomain.

Przepraszam za częściową odpowiedź. Korzystam teraz z komórki, ale sprawdzę jutro. Mam nadzieję, że dzięki temu zaczniesz.

1
Johannes Rudolph 10 luty 2012, 01:06