即使不在拨款集中,反射也不受限制
我目前正在尝试创建一个非常非常简单的沙箱。
某些类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();
}
}
}
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();
}
}
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
调用不可访问成员时需要反射权限。
A
和B
是具有公共构造函数的公共类型,因此可以访问。您可以在不使用反射的情况下调用这些构造函数,因此当您尝试使用反射来执行此操作时没有任何要求。此外,使用反射进行发现始终是合法的;即使没有授予反射权限,您也可以询问一个对象并要求其提供其私有成员的列表。仅当您尝试调用私有成员时才需要该权限。
Reflection permission is demanded when invoking an inaccessible member.
A
andB
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.
来自 MSDN 库</a>:
ReflectionPermission< /code> 通过 System.Reflection API 控制对非公共类型和成员的访问。如果没有
ReflectionPermission
,代码只能使用反射来访问对象的公共成员。From MSDN Library:
ReflectionPermission
controls access to non-public types and members through the System.Reflection APIs. WithoutReflectionPermission
, code can use reflection to access only the public members of objects.您检查过 .net 3.5 上的代码吗? .NET 4 有一个新的
授予集不再影响 sansbox 的安全模型。当我想要测试打算在完全信任的 .net 进程上的中等信任上下文中运行的代码时,我对此深感困扰。
一种可能的解决方案是强制 CLR 使用旧安全模型,然后在新 AppDomain 中显式拒绝 ReflectionPermission。
抱歉回答不完整,我现在正在使用移动设备,但明天会再回来查看。希望这能让你开始。
Have you checked your code on .net 3.5? .NET 4 has a new
security model where the grant sets do no longer affect the sansbox. I was seriously bitten by this when I wanted to test code intended to run in medium trust contexts on a full trust .net process.
A possible solution is to force the CLR to use the legacy security model and then explicitly deny ReflectionPermission in the new AppDomain.
Sorry for the partial answer, I'm on mobile right now but will check back tomorrow. Hope this gets you started.