科技行者

行者学院 转型私董会 科技行者专题报道 网红大战科技行者

知识库

知识库 安全导航

至顶网软件频道基础软件.NET 框架中的安全性概述 修改堆栈审核

.NET 框架中的安全性概述 修改堆栈审核

  • 扫一扫
    分享文章到微信

  • 扫一扫
    关注官方公众号
    至顶头条

.NET 框架中的安全性概述 修改堆栈审核

作者:Demien Watkins 2007年10月26日

关键字:

  • 评论
  • 分享微博
  • 分享邮件

在执行期间的任何阶段,在某个函数访问特定资源之前,它都可能需要检查其调用方的权限。在这一阶段,该函数可以要求对一个特定的权限或权限集进行安全检查。这就会触发堆栈审核,其结果是:如果所有的调用方都具有授予的权限,那么该函数会继续执行;如果调用方不具有所需的一个(或多个)权限,就会引发异常。下图说明了这个过程。

netframesecover_3

3. 堆栈审核示例

函数可以选择修改堆栈审核,有一些机制可完成这种修改。首先,一个函数可能需要确定调用它的多个函数。在这种情形下,它可以断言一个特定的权限。如果发生了查找断言权限的堆栈审核,那么在检查这个函数的激活记录以寻找该权限时,如果该函数具有它断言的权限,则检查成功,堆栈审核将会终止。断言本身是一个受保护操作,因为它将向断言访问受保护资源权限的函数的所有调用方开放对该受保护资源的访问权限。因此,在运行库中,安全系统会检查包含自我断言的函数的程序集是否具有它试图断言的权限。

修改堆栈审核的另一种办法是支持函数拒绝权限。当一个函数知道它不应该访问某个资源并拒绝权限时,就可能发生这种情形。PermitOnly 提供了类似 deny 的功能,因为它会导致堆栈审核失败。但 deny 指定的是会导致堆栈审核失败的权限集,而 PermitOnly 指定的则是继续堆栈审核所需的权限集。

在使用 Deny 堆栈修饰符时,应该小心。如果早期的堆栈帧是一个断言,则会忽略 Deny 修饰符。另外,拒绝基于路径的权限是相当困难的,这是因为经常有各种不同的路径字符串实际是指向相同位置的。拒绝一个特定路径表达式仍会开放其他的路径。

还有最后一个需要知道的要点。在任何时刻,一个堆栈帧只能有一个 Deny、一个 PermitOnly 和一个 Assert 处于有效状态。例如,如果开发人员需要断言许多权限,他们就应该创建一个 PermissionSet 来表示该集合,并只进行一个单独的断言。有一些方法可用来删除一个堆栈审核修饰符的当前 PermissionSet 设置,以便注册其他的权限集。此类方法的一个示例是 System.Security.CodeAccessPermission.RevertPermitOnly。

下面的示例说明了前面介绍的各种堆栈修改技术:

using System;
using System.Security;
using System.Security.Permissions;

namespace PermissionDemand
{
   class EntryPoint
   {
      static void Main(string[] args)
      {
         String f = @"c:\System Volume Information";
         FileIOPermission p = 
            new FileIOPermission(
               FileIOPermissionAccess.Write, f);
         p.Demand();
         p.Deny();
         p.Demand();
         CheckDeny(p);
         p.Assert();
         CheckDeny(p);
      }
      static void CheckDeny(FileIOPermission p)
      {
         try
         {
            p.Demand();
         }
         catch(SecurityException)
         {
            Console.WriteLine("Demand failed");
         }
      }
   }
}

前面的程序产生了下面的输出,这些输出起先看起来很不直观:

Demand failed
Demand failed

在上面的代码示例中,尽管第一个 Demand 访问的是一个受限制系统目录,但它还是成功了。请记住,运行库安全系统是在基础操作系统设置上面运行的。因此,可以让运行库安全策略对某些目录授予访问权限,当托管代码试图访问这些目录时,将会引发操作系统访问冲突。直接跟在 Deny 后面的下一个 Demand 也成功了。当执行 Demand 时,没有检查请求函数的激活记录,而只检查了它的调用方。因此,尽管函数已经拒绝访问,但也不会被 Demand 检测到。对 CheckDeny 和后面的 Demand 的调用失败了。现在检查前面方法中的 Deny,因为它位于调用方的堆栈帧中。接下来我们返回到 Main 并进行一个 Assert。在这里,有一个已经断言的权限也在这个堆栈帧中被拒绝了。当我们进入 CheckDeny 时,Demand 会再次引发一个异常,这是为什么呢?从本质上讲,Deny 重写了 Assert;这是因为 Deny 权限集总是在 Assert 权限集之前接受检查。

简要的说,使托管资源可以引发托管安全堆栈审核的功能是保护资源的运行库安全系统方法。授予的权限集是程序集从每个策略级别上运行的授权计算收到的,该权限集会与资源请求的权限进行对照检查。如果后者形成了前者的一个子集,那么就可以访问受保护资源。除非已像上面描述的那样对堆栈进行了修改,否则就会对调用链中托管资源的所有调用方执行这种子集检查。因此安全堆栈审核综合了运行库安全系统的以下两个方面:1) 证据和权限之间的可配置映射;2) 通过强制所有的调用方拥有一定级别的权限来保护资源。

实际上有两种不同的方式可用于以编程的方式表达堆栈审核请求和堆栈修改操作 — 声明性安全和命令性安全

查看本文来源
    • 评论
    • 分享微博
    • 分享邮件
    邮件订阅

    如果您非常迫切的想了解IT领域最新产品与技术信息,那么订阅至顶网技术邮件将是您的最佳途径之一。

    重磅专题
    往期文章
    最新文章