I'm currently trying to create a very very simple sandbox.
Some class A has a method Execute which is invoked in another AppDomain
than the caller.
Problem is I've execution permission only and reflection is possible anyway.
This is the code sample:
[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();
}
}
UPDATE
Great! Finally I did it.
Thanks to your advices I've revised my code and I'd like to share it with you, since I had a hard time understanding how to don't use CAS but use same kind of permissions in the new .NET 4.x and above security model, and the way of sandboxing using an AppDomain
. That's it:
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();
}
}
}
Reflection permission is demanded when invoking an inaccessible member. A
and B
are public types with public constructors, and so are accessible. You could invoke those constructors without reflection, so there is no demand when you attempt to do so with reflection.
Moreover, using reflection for discovery is always legal; you can interrogate an object and ask it for a list of its private members, even without reflection permission being granted. It is only when you attempt to cause an invocation of the private member that the permission is demanded.
From MSDN Library: ReflectionPermission
controls access to non-public types and members through the System.Reflection APIs. Without ReflectionPermission
, code can use reflection to access only the public members of objects.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With