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

安全基础
网管技术:常见BIOS报错信息及解决方法
分布式拒绝服务(DDOS)攻击及防范研究
四种宽带接入方式及其传输速率
网管必读 解读无线网络的七大安全困惑
经验:识别系统的非法进程及剿杀
全面清除系统垃圾的方法
QQ、网游等账号防盗防骗的实用小经验
上网前保证Windows XP系统安全的办法
七种DDoS攻击技术方法简介
硬盘与内存检测 四种查毒绝招
当网站注册时输入验证码总是不正确解决方法
不让自己的秘密留在别人的电脑中
IE崩溃遭难不求人 快速简单处理方法
损招 让应用程序莫名其妙地失效
不再弹广告 破除隐身僵尸木马的隐身妖术
利用QQ传播 网络欺骗“绑架”奥运会
渗透测试的攻与守 认清网络面临的问题
手动剿杀“上兴远程控制”木马
个人电脑防黑客入侵八准则
关注Windows系统服务中的安全隐患

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


出处:互联网   整理: 软晨网(RuanChen.com)   发布: 2009-10-28   浏览: 29 ::
收藏到网摘: 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 安全权限集构建的文章弄完,再整理篇完整的,呵呵。