C# 限制对私有文本字段的反射

C# 限制对私有文本字段的反射,c#,.net,reflection,appdomain,reflectionpermission,C#,.net,Reflection,Appdomain,Reflectionpermission,我正在尝试使用应用程序域构建一个沙盒,以隔离潜在错误代码的执行 除此之外,我想限制反射 我以这种方式构建沙箱: AppDomainSetup sandboxSetup = new AppDomainSetup { ApplicationBase = "." }; PermissionSet permissions = new PermissionSet(PermissionState.None); permissions.AddPermission(new SecurityPermiss

我正在尝试使用应用程序域构建一个沙盒,以隔离潜在错误代码的执行

除此之外,我想限制反射

我以这种方式构建沙箱:

AppDomainSetup sandboxSetup = new AppDomainSetup
{
    ApplicationBase = "."
};
PermissionSet permissions = new PermissionSet(PermissionState.None);
permissions.AddPermission(new SecurityPermission(SecurityPermissionFlag.Execution));
AppDomain sandbox = AppDomain.CreateDomain("sandbox", null, sandboxSetup, permissions);
它可以很好地处理私有实例字段和私有属性:任何在沙箱中访问它们的尝试都会被运行时拒绝

但是我注意到它不适用于文本字段(C#中的const):总是可以获得文本字段的值,即使是私有的:

private const string PASSWORD = "secret";
private string password = "secret";
private string Password
{
    get
    {
        return "secret";
    }
}
密码和密码受到正确保护,但任何代码都可以通过基本反射获得密码值:

string password = typeof(User).GetField("PASSWORD", BindingFlags.NonPublic | BindingFlags.Static).GetValue(currentUser) as string;  // OK no problem take it, it's free!
我想了解这种行为背后的基本原理:是因为文字值在程序集中总是“容易”看到,所以防止反射是一场失败的战斗,还是因为最终值没有真正“调用”,所以没有安全检查,还是

这个例子并不真正相关,因为密码不会被共享,但是想象一下这个秘密值是一个用于加密的salt值或者类似的东西


感谢您的帮助。

当您获得常量的
FieldInfo
时,您将获得
MdFieldInfo
类型。 如果我们反编译代码,我们将看到它没有对该类型进行安全检查

以下是
MdFieldInfo
类型的反编译代码:

[DebuggerHidden]
[DebuggerStepThrough]
[TargetedPatchingOptOut("Performance critical to inline this type of method across NGen image boundaries")]
public override object GetValue(object obj)
{
  return this.GetValue(false);
}
[SecuritySafeCritical]
private object GetValue(bool raw)
{
  object obj = MdConstant.GetValue(this.GetRuntimeModule().MetadataImport, this.m_tkField, this.FieldType.GetTypeHandleInternal(), raw);
  if (obj == DBNull.Value)
    throw new NotSupportedException(Environment.GetResourceString("Arg_EnumLitValueNotFound"));
  else
    return obj;
}
public override object GetValue(object obj)
{
  StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
  return this.InternalGetValue(obj, ref stackMark);
}

[SecuritySafeCritical]
[DebuggerStepThrough]
[DebuggerHidden]
internal object InternalGetValue(object obj, ref StackCrawlMark stackMark)
{
  INVOCATION_FLAGS invocationFlags = this.InvocationFlags;
  RuntimeType runtimeType1 = this.DeclaringType as RuntimeType;
  if ((invocationFlags & INVOCATION_FLAGS.INVOCATION_FLAGS_NO_INVOKE) != INVOCATION_FLAGS.INVOCATION_FLAGS_UNKNOWN)
  {
    if (runtimeType1 != (RuntimeType) null && this.DeclaringType.ContainsGenericParameters)
      throw new InvalidOperationException(Environment.GetResourceString("Arg_UnboundGenField"));
    if (runtimeType1 == (RuntimeType) null && this.Module.Assembly.ReflectionOnly || runtimeType1 is ReflectionOnlyType)
      throw new InvalidOperationException(Environment.GetResourceString("Arg_ReflectionOnlyField"));
    else
      throw new FieldAccessException();
  }
  else
  {
    this.CheckConsistency(obj);
    if ((invocationFlags & INVOCATION_FLAGS.INVOCATION_FLAGS_NON_W8P_FX_API) != INVOCATION_FLAGS.INVOCATION_FLAGS_UNKNOWN)
    {
      RuntimeAssembly executingAssembly = RuntimeAssembly.GetExecutingAssembly(ref stackMark);
      if ((Assembly) executingAssembly != (Assembly) null && !executingAssembly.IsSafeForReflection())
        throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_APIInvalidForCurrentContext", new object[1]
        {
          (object) this.FullName
        }));
    }
    RuntimeType runtimeType2 = (RuntimeType) this.FieldType;
    if ((invocationFlags & INVOCATION_FLAGS.INVOCATION_FLAGS_NEED_SECURITY) != INVOCATION_FLAGS.INVOCATION_FLAGS_UNKNOWN)
      RtFieldInfo.PerformVisibilityCheckOnField(this.m_fieldHandle, obj, this.m_declaringType, this.m_fieldAttributes, (uint) (this.m_invocationFlags & ~INVOCATION_FLAGS.INVOCATION_FLAGS_IS_CTOR));
    return this.UnsafeGetValue(obj);
  }
}

当您得到非常量值的
FieldInfo
时,您会得到
RtFieldInfo
类型,并且它会进行安全检查

以下是
RtFieldInfo
类型的反编译代码:

[DebuggerHidden]
[DebuggerStepThrough]
[TargetedPatchingOptOut("Performance critical to inline this type of method across NGen image boundaries")]
public override object GetValue(object obj)
{
  return this.GetValue(false);
}
[SecuritySafeCritical]
private object GetValue(bool raw)
{
  object obj = MdConstant.GetValue(this.GetRuntimeModule().MetadataImport, this.m_tkField, this.FieldType.GetTypeHandleInternal(), raw);
  if (obj == DBNull.Value)
    throw new NotSupportedException(Environment.GetResourceString("Arg_EnumLitValueNotFound"));
  else
    return obj;
}
public override object GetValue(object obj)
{
  StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
  return this.InternalGetValue(obj, ref stackMark);
}

[SecuritySafeCritical]
[DebuggerStepThrough]
[DebuggerHidden]
internal object InternalGetValue(object obj, ref StackCrawlMark stackMark)
{
  INVOCATION_FLAGS invocationFlags = this.InvocationFlags;
  RuntimeType runtimeType1 = this.DeclaringType as RuntimeType;
  if ((invocationFlags & INVOCATION_FLAGS.INVOCATION_FLAGS_NO_INVOKE) != INVOCATION_FLAGS.INVOCATION_FLAGS_UNKNOWN)
  {
    if (runtimeType1 != (RuntimeType) null && this.DeclaringType.ContainsGenericParameters)
      throw new InvalidOperationException(Environment.GetResourceString("Arg_UnboundGenField"));
    if (runtimeType1 == (RuntimeType) null && this.Module.Assembly.ReflectionOnly || runtimeType1 is ReflectionOnlyType)
      throw new InvalidOperationException(Environment.GetResourceString("Arg_ReflectionOnlyField"));
    else
      throw new FieldAccessException();
  }
  else
  {
    this.CheckConsistency(obj);
    if ((invocationFlags & INVOCATION_FLAGS.INVOCATION_FLAGS_NON_W8P_FX_API) != INVOCATION_FLAGS.INVOCATION_FLAGS_UNKNOWN)
    {
      RuntimeAssembly executingAssembly = RuntimeAssembly.GetExecutingAssembly(ref stackMark);
      if ((Assembly) executingAssembly != (Assembly) null && !executingAssembly.IsSafeForReflection())
        throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_APIInvalidForCurrentContext", new object[1]
        {
          (object) this.FullName
        }));
    }
    RuntimeType runtimeType2 = (RuntimeType) this.FieldType;
    if ((invocationFlags & INVOCATION_FLAGS.INVOCATION_FLAGS_NEED_SECURITY) != INVOCATION_FLAGS.INVOCATION_FLAGS_UNKNOWN)
      RtFieldInfo.PerformVisibilityCheckOnField(this.m_fieldHandle, obj, this.m_declaringType, this.m_fieldAttributes, (uint) (this.m_invocationFlags & ~INVOCATION_FLAGS.INVOCATION_FLAGS_IS_CTOR));
    return this.UnsafeGetValue(obj);
  }
}
感谢Vyacheslav提供的反编译代码,该代码明确显示未对文本字段执行安全检查。主要问题仍然是:为什么+1.)