当前位置: 首页 > 图文教程 > 网络安全 > 安全基础 > CLR 中代码访问安全检测实现原理(5)

安全基础
用net start 可以启动肉鸡的命令(2)
用net start 可以启动肉鸡的命令(3)
用net start 可以启动肉鸡的命令(4)
DDOS攻击 如何判断是否遭到流量攻击
网络防“虫”手段和全局安全网络的应用
个人网络安全防卫手册(1)
个人网络安全防卫手册(2)
个人网络安全防卫手册(3)
个人网络安全防卫手册(4)
个人网络安全防卫手册(5)
个人网络安全防卫手册(6)
一位高手整理的IIS FAQ
使用Exchange 2003防御地址欺骗(1)
使用Exchange 2003防御地址欺骗(2)
RAdmin 服务端高级配置(1)
只防病毒不安全 网络还需防什么(1)
只防病毒不安全 网络还需防什么(2)
主动防御电脑病毒并非天方夜谭
用XPSP2防火墙打造最强护身甲(1)
用XPSP2防火墙打造最强护身甲(2)

安全基础 中的 CLR 中代码访问安全检测实现原理(5)


出处:互联网   整理: 软晨网(RuanChen.com)   发布: 2009-10-28   浏览: 74 ::
收藏到网摘: n/a

  前面介绍堆栈帧时曾经提到过,对所有跨越 Assembly/AppDomain 的调用,都会有特殊的帧被放入堆栈中做标记。因此在调用链跨越两个 Assembly/AppDomain 时,堆栈遍历回调函数将有一个合适的时机,检测新的 Assembly/AppDomain 是否拥有足够权限。这两类检测思路类似,都是先通过 Assembly::GetSecurityDescriptor 函数 (Assembly.cpp:747) 或 AppDomain::GetSecurityDescriptor 函数 (AppDomain.cpp:1146) 获取一个安全描述符 SecurityDescriptor;然后对需要进行 CAS 检测的情况,调用 SecurityDescriptor::GetGrantedPermissionSet 函数 (Security.cpp:2218) 获得相关权限集;最后调用回调函数传入参数中的 pfnCheckGrants 函数指针,进行权限验证。

  值得注意的是,当安全描述符被标记为完全可信任 (SecurityDescriptor::IsFullyTrusted())、堆栈遍历参数指定非受限模式 (IUnrestrictedPermission)、以及 Assembly 是系统 BCL 类库(mscorlib.dll) 或 AppDomain 是缺省 AppDomain (用于加载 BCL 类库,具体说明参见《用WinDbg探索CLR世界 AppDomain 的创建过程 》一文),则忽略 CAS 检测。

  对完全可信任概念的含义,可以参考《可怕的 Fully Trusted Code》一文。

  如果需要进行 CAS 检测,则 CheckGrants 函数 (ComCodeAccessSecurityEngine.cpp:128) 将完成权限的验证工作。而其实际工作,则将通过 Managed 方法 CodeAccessSecurityEngine::CheckHelper 方法 (CodeAccessSecurityEngine.cs:230) 完成。而 CheckHelper 方法将通过权限类型本身的 IsSubsetOf/Intersect 等方法的实现,来判断 Assembly/AppDomain 现有权限集,是否包括请求的权限。而 Assembly/AppDomain 现有权限集,则是在 Assembly 被载入以及 AppDomain 被创建时,由 CLR Loader 创建的。以后有机会再专门写篇文章分析这个权限集的构建逻辑。

以下内容为程序代码:

private static void CheckHelper(PermissionSet grantedSet, PermissionSet deniedSet, CodeAccessPermission demand, PermissionToken permToken)
{
 if (permToken == null)
  permToken = PermissionToken.GetToken(demand);

 try
 {
  // 获取权限集不能为空
  if (grantedSet == null)
  {
   throw new SecurityException(...);
  }
  // 不处理权限集不受限或请求权限为非受限权限的情况
  else if (!grantedSet.IsUnrestricted() || !(demand is IUnrestrictedPermission))
  {
   CodeAccessPermission grantedPerm = (CodeAccessPermission)grantedSet.GetPermission(permToken);

   if (grantedPerm == null)
   {
    if (!demand.IsSubsetOf( null ))
     throw new SecurityException(String.Format(...);
    else
     return;
   }
  }

  // 验证权限没有被显式禁止
  if (deniedSet != null)
  {
   CodeAccessPermission deniedPerm = (CodeAccessPermission)deniedSet.GetPermission(permToken);

   if (deniedPerm != null)
   {
    if (deniedPerm.Intersect(demand) != null)
    {
     throw new SecurityException(...);
    }
   }
  }
 }
 catch (Exception e)
 {
  // 所有的非 SecurityException 异常将都被转换为 SecurityException 异常
  // 因为这些异常的发生都是因为获取指定权限操作失败的原因
  if (e is SecurityException)
   throw e;
  else
   throw new SecurityException(...);
 }
}


  最后 CodeAccessCheckStackWalkCB 还需要处理显式指定了安全对象帧的情况。对帧安全对象进行检测的 CheckFrameData 方法 (ComCodeAccessSecurityEngine.cpp:231) 与 CheckGrants 类似,也是最终通过 CheckHelper 方法实现的,这里就不罗嗦了。堆栈帧的安全对象,等到介绍堆栈结构的时候再详细解释。

  至此,CLR 中代码访问安全检测的大致实现思路以及比较清晰了,等把堆栈帧结构和 CLR Loader 安全权限集构建的文章弄完,再整理篇完整的,呵呵。