您的位置:首页 > 编程语言 > Go语言

Godtear.Security,基于CAS(Code Access Security)的权限控制(一)

2009-06-11 14:12 176 查看
你是否曾以管理员的身份登录系统并在无意中下载或运行了木马,病毒?你的软件是否曾因为引用第三方组件而意外地访问了敏感资源?尽管系统提供了完整的角色管理和权限控制,但伪装的恶意程序还是一次次地被执行。究其原因在于传统的安全机制对权限控制的深度和粒度是不足的。多数普通安全机制根据用户的登录凭据(通常为密码)赋予用户权限,并限制允许用户访问的资源(通常为目录和文件)。但是,这种方法无法解决以下几个问题:用户从许多来源获取代码,这些来源中有一些可能不可靠;代码可能包含 bug 或具有脆弱性,使它有可能被恶意代码利用;代码有时候会执行一些操作,而用户并不知道它会执行这些操作。结果,当谨慎且可信的用户运行恶意软件或包含错误的软件时,计算机系统可能会损坏,私有数据可能会泄漏。多数操作系统安全机制要求每一段代码都必须完全受信任(Web 页的脚本可能除外),然后才可运行。因此,仍需要一种可广泛应用的安全机制,即使两个计算机系统之间没有信任关系,该机制也允许在一个计算机系统上生成的代码能够在另一系统上安全地执行。所幸.NET平台提供了除角色访问安全外的代码访问安全机制。

一,CAS(代码访问安全)介绍

NET Framework提供的CAS(Code Access Security/代码访问安全)机制则是一种更细粒度的安全机制,代码访问安全性使代码可以根据它所来自的位置以及代码标识的其他方面,获得不同等级的受信度。代码访问安全性还实施不同级别的对代码的信任,从而最大限度地减少了必须完全信任才能运行的代码的数量。使用代码访问安全性,可以减小恶意代码或包含错误的代码滥用您的代码的可能性。它可以减轻您的责任,因为您可以指定应该允许代码执行的一组操作,同时还可指定永远不允许代码执行的一组操作。代码访问安全性还有助于最大限度地减少由于代码中的安全脆弱性而造成的损害。

代码访问安全性是帮助限制代码对受保护的资源和操作的访问权限的一种机制。在 .NET Framework 中,代码访问安全性执行下列功能:

· 定义权限和权限集,它们表示访问各种系统资源的权限。

· 使管理员能够通过将权限集与代码组关联来配置安全策略。

· 使代码能够请求运行所需权限以及其他一些有用的权限,以及指定代码绝对不能拥有哪些权限。

· 根据代码请求的权限和安全策略允许的操作,向加载的每个程序集授予权限。

· 使代码能够要求其调用方拥有特定的权限。

· 使代码能够要求其调用方拥有数字签名,从而只允许特定组织或特定站点的调用方来调用受保护的代码。

· 通过将调用堆栈上每个调用方所授予的权限与调用方必须拥有的权限相比较,加强运行时对代码的限制。

为了确定是否已授予代码访问资源或执行操作的权限,运行库的安全系统遍历调用堆栈,将每个调用方所授予的权限与目前要求的权限相比较。如果调用堆栈中的任何调用方没有要求的权限,则会引发安全性异常,并会拒绝访问。堆栈步旨在防止引诱攻击;在这种攻击中,受信程度较低的代码调用高度信任的代码,并使用高度信任的代码执行未经授权的操作。在运行时要求所有调用方都拥有权限会影响性能,但这对于帮助保护代码免遭受信程度较低的代码的引诱攻击至关重要。若要优化性能,可以使代码执行较少的堆栈步;但是,任何时候这样做时均必须确保不会暴露安全缺陷。

下图阐释“程序集 A4”中的方法要求其调用方拥有权限 P 时引起的堆栈步。

CodeAccessPermission permissionA =new FileIOPermission(FileIOPermissionAccess.AllAccess, @"C:"");

CodeAccessPermission permissionB =new FileIOPermission(FileIOPermissionAccess.Read, @"C:"temp");

if (permissionB.IsSubsetOf(permissionA))

else

代码的执行结果如下:PermissionB is a subset of PermissionA

l 验证权限

下面代码演示了在访问F:"textfile.txt前验证文件的访问权限,如果不满足安全要求则打印:no rights to access this file.

try

catch (SecurityException)

l 拒绝权限

下面的代码演示了在调用不信任的代码前拒绝对文件目录的访问权限,从而防止不被信任的代码可能对文件的非法访问。不被信任的代码调用完后通过CodeAccessPermission.RevertDeny()解除前面的权限拒绝。

CodeAccessPermission permission =new FileIOPermission(FileIOPermissionAccess.AllAccess , @"F:"");

//拒绝对目录F:"的访问权限,避免后续被调用的代码访问F:"目录

permission.Deny();

//不被信任的代码,

Method();

//解除拒绝

CodeAccessPermission.RevertDeny();

public void Method()

下面的代码演示了只授予后续不被信任的代码对目录的只读权限,以防止不被信任的代码对文件的非读访问。不被信任的代码调用完后通过CodeAccessPermission.RevertPermitOnly解除前面的只读控制。

CodeAccessPermission permission =new FileIOPermission(FileIOPermissionAccess.Read , @"F:"");

//仅仅允许对目录F:"的读权限,避免后续被调用的代码非读访问F:"目录

permission.PermitOnly();

//不被信任的代码,

Method();

//解除限制

CodeAccessPermission.RevertPermitOnly();

public void Method()

l 断言权限

Assert(断言)可以让被调用者执行调用者没有的权限。下面的代码演示了被调用者断言自己对文件访问的权限从而避开调用者对其文件访问权限的拒绝。

try

}

class Test

随意使用断言是非常危险的,阻止断言的方法是在调用者程序集中申明禁止断言:

[assembly: SecurityPermission(SecurityAction.RequestRefuse, Assertion = true)]

2, 以声明方式请求权限

除了要求强制通过代码的权限,可以使用属性以请求权限。 属性可以使用类或单个方法时才相关联。

[FileIOPermission(SecurityAction.Deny,Write = @"F:"textfile.txt")]

public void Method()

如果自定义一个权限则应该定义个相应的Attribute类来为你的自定义权限发出声明式要求。声明的安全属性必须直接或者间接从SecurityAttribute派生。如果该权限是代码访问权限,则属性类从CodeAccessSecurityAttribute 派生,后者从 SecurityAttribute 派生。安全属性类必须实现 CreatePermission 方法,该方法根据关联的自定义权限创建权限对象的一个实例。请注意,此关联的自定义权限类必须用SerializableAttribute 标记,才能由编译器序列化到元数据中。另外, 自定义权限的属性版本必须定义在不引用它的程序集中。自定义权限也应定义在该程序集中。对于声明式安全,这是必需的,因为该属性是在程序集加载时执行的,在遇到对该属性的引用时,可能还未创建该属性。如果试图在定义声明式权限的程序集中使用该权限,将导致引发TypeLoadException。自定义权限及其声明属性将在后续的文章中详细阐述。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: