jeudi 27 octobre 2016

SecurityException when executing reflected method in sandbox AppDomain

I am using a separate AppDomain as a sandbox, and trying to execute a method that is constructed via reflection.

When the method is invoked, a SecurityException is thrown, even though the sandbox AppDomain has ReflectionPermission(PermissionState.Unrestricted) set on its PermissionSet.

The invocation does work when the PermissionSet is set to PermissionState.Unrestricted, but that defeats the purpose of a sandbox.

Here's an example that demonstrates the issue:

using System;
using System.Security;
using System.Security.Permissions;

namespace ConsoleTest
{
    class Program
    {
        static void Main(string[] args)
        {
            var person = new Person();
            var program = new Program();

            var customDomain = program.CreateDomain();
            var result = program.Execute(customDomain, (x) =>
            {
                var type = x.GetType();
                var propertyInfo = type.GetProperty("Name");
                var method = propertyInfo.GetMethod;
                var res = method.Invoke(x, null) as string;
                return res;
            }, person);
            Console.WriteLine(result);
            Console.ReadLine();
        }

        public object Execute(AppDomain domain, Func<object, object> toExecute, params object[] parameters)
        {
            var proxy = new Proxy(toExecute, parameters);
            var result = proxy.Invoke(domain);
            return result;
        }

        private AppDomain CreateDomain()
        {
            var appDomainSetup = new AppDomainSetup()
            {
                ApplicationBase = AppDomain.CurrentDomain.BaseDirectory,
                ApplicationName = "UntrustedAppDomain"
            };

            // Set up permissions
            var permissionSet = new PermissionSet(PermissionState.None);
            permissionSet.AddPermission(new SecurityPermission(PermissionState.Unrestricted));
            permissionSet.AddPermission(new ReflectionPermission(PermissionState.Unrestricted));

            // Create the app domain.
            return AppDomain.CreateDomain("UntrustedAppDomain", null, appDomainSetup, permissionSet);
        }

        private sealed class Proxy : MarshalByRefObject
        {
            private Delegate method;
            private object[] args;
            private object result;

            public Proxy(Delegate method, params object[] parameters)
            {
                this.method = method;
                this.args = parameters;
            }

            public object Invoke(AppDomain customDomain)
            {
                customDomain.DoCallBack(Execute);
                return this.result;
            }

            private void Execute()
            {
                this.result = this.method.DynamicInvoke(this.args);
            }
        }
    }

    public class Person
    {
        public Person()
        {
            this.Name = "Test Person";
        }

        public string Name { get; set; }
    }
}





Aucun commentaire:

Enregistrer un commentaire