Microsoft NET 框架中的安全机制.docx
- 文档编号:17840189
- 上传时间:2023-08-04
- 格式:DOCX
- 页数:15
- 大小:35.98KB
Microsoft NET 框架中的安全机制.docx
《Microsoft NET 框架中的安全机制.docx》由会员分享,可在线阅读,更多相关《Microsoft NET 框架中的安全机制.docx(15页珍藏版)》请在冰点文库上搜索。
MicrosoftNET框架中的安全机制
Microsoft.NET框架中的安全机制
由Foundstone和CORESecurityTechnologies两家公司提供的分析报告
本文对Microsoft的.NET框架的安全体系结构作了一个概述。
本文以Foundstone和CORESecurityTechnologies这两家公司自2000年夏季开始进行的一次长期、独立的安全分析为基础。
我们的分析报告显示,如使用得当,.NET框架使开发人员和管理员能够对其应用程序和资源进行细微的安全控制;给开发人员提供一套易用的工具集来实现功能强大的身份验证、授权和加密等例程;消除了如今由于代码缺陷(如缓冲区溢出)而使应用程序面临的许多重大安全风险;而且把作重要安全决定—如,是否要运行某个特定的应用程序,或者应让此应用程序能够访问哪些资源—的这一负担从最终用户身上转移到开发人员和管理员身上。
在本文中我们还将介绍.NET框架中的基于证据和基于角色的安全功能、代码访问安全性、验证过程、加密支持、独立存储和应用程序域,说明它们是怎样通过互相协作实现了这些目标,并为开发和运行各种类型的软件应用程序(包括客户端和服务器端)提供一个可靠平台的。
我们的结论是,.NET框架能让各类单位都更有信心保证他们的应用程序能够抵御现在已知以及将来要发生的各种安全攻击。
引言
在.NET框架的开发初期,Foundstone和CORESecurityTechnologies就协助MicrosoftCorp.对其体系结构和实现的安全性进行分析和评估。
对.NET框架的分析工作始于2000年夏,自该软件第一个Beta版出现之前开始,一直持续到Beta2版。
我们共投入了2800多小时的时间,由一个十人专家小组进行严格、独立的安全审核和测试,其间我们可以完全不受限制地访问源代码和接触Microsoft的工程师,所以完全熟悉了.NET框架的安全体系结构,包括从设计原则到代码级别实现的各个细节。
审核工作遵循由Foundstone和CORESecurityTechnologies在多年实践中形成的标准方法,多年来他们一直都在为各种单位-从财富500强企业到新兴的公司-提供复杂软件应用程序的测试、评估和安全增强服务。
站在安全解决方案提供商的角度,我们要说我们见到过“好的、坏的和极差的”,而.NET框架,在一年来我们剖析其内部工作机制的过程中,经受了我们的集体智慧的考验。
本文着重探讨.NET框架的广泛的安全功能。
它主要基于我们去年的评估结果以及我们与“.NET框架”开发小组不断的交流。
这里所表达的想法和观点完全是我们在对多个软件版本进行严谨分析和严格测试后得到的独立的观察报告。
希望本文能促进人们对.NET框架的安全机制的理解,并表达出我们对该体系结构及其实现的信心。
范围及目标
在本文中,我们将回顾许多企业在设计和开发软件解决方案的过程中所面临的许多常见的安全挑战,并概括了.NET框架如何通过它的安全体系结构为这些问题提供了合理的解决办法。
我们一直都在尝试使.NET框架复杂的安全机制能让那些至少有中等技术背景的读者理解。
这里我们假定读者对.NET框架有一些基本的了解,因此我们不会花过多的时间讲述有关所涉及到的基本技术的背景知识。
在本文档的最后,我们为那些想更深入了解.NET框架技术内容的读者提供了许多供进一步阅读的参考资源。
背景:
应用程序安全性问题
几乎没有任何人会怀疑许多软件应用程序所起到的至关重要的作用了,特别是那些使用基于Internet技术构建的应用程序。
它们已从简单、静态的数据操作渠道发展为复杂、动态的面向事务的应用程序,并成了企业商务的支柱。
然而,由于现代软件应用程序越来越复杂以及功能越来越多,也随之产生了一股不幸的、令人担忧的逆流:
越来越多的单位都已成为内部和外部入侵者对其软件发起的攻击的牺牲品。
解决办法:
一个用来管理软件风险的体系结构
.NET框架的托管代码体系结构为软件应用程序安全问题提供了一个令人信服的解决方案。
甚至在最恶劣的环境中它仍能透明地控制代码的行为,这样就极大地减少了各种应用程序(包括客户端和服务器端)中固有的风险。
事实上,如使用得当,我们相信它是开发有严格安全要求的企业级和Web应用程序的最佳平台之一。
在一个较高的级别,.NET框架使开发人员和管理员能够对其应用程序和资源进行细微的安全控制;给开发人员提供一套易用的工具集来实现强大的身份验证、授权和加密等例程;消除了如今由于代码缺陷(如缓冲区溢出)而使应用程序要面临的许多重大安全风险;而且把作重要安全决定—如,是否要运行某个特定的应用程序,或者应让此应用程序能够访问哪些资源—的这一负担从最终用户身上转移到开发人员和管理员身上。
托管代码模式
在我们详细讨论“.NET框架”如何实现这一目标之前,首先来回顾一下该“框架”本身的基本组件,其组件包括:
∙公共语言运行库
∙类库
∙程序集
公共语言运行库
公共语言运行库(CLR)是一个运行并“管理”正在执行的代码的引擎。
所以,从安全角度来看,CLR将.NET框架的限制施加到正在执行的代码上并防止它表现出意外的行为。
更具体地说,CLR在运行托管代码时执行“实时”(JIT)编译。
JIT在执行托管代码之前先将它转换为本机代码。
由于JIT在CLR内部生成代码,所以让CLR处于一个独特的位置以保证代码的安全,亦即,如果代码在本机环境中未经处理,则不允许执行这种代码完成某些操作。
类库
“.NET框架”类库是可重用的类或类型的集合,开发人员可以利用它们编写将在公共运行库中执行的程序。
它们实现了许多重要的安全功能,包括权限(即对一个或多个系统资源的访问权限)、身份验证机制以及加密协议和基元。
大多数的应用程序只须使用这些库就能从这一安全机制中受益,而无须编写特别的安全代码。
我们将在本文稍后更详细地讨论这些功能。
程序集
程序集是指使用“.NET框架”的众多语言编译器中的某一编译器编译出的可执行文件或DLL文件。
.NET框架程序集几乎可以使用任何一种主流编程语言来编写,包括VisualBasic、C#、C++、J#、Perl和COBOL等,这里仅列举几个而已。
因此,开发人员可以选择最适合他们的任务和自己的技能的语言来编程,而且无论他们选择哪种语言,都会有同样的安全基础结构在支持他们。
程序集中包含了运行库以“Microsoft中间语言”(MSIL)的形式执行的代码。
前面我们讲到过CLR可将MSIL实时编译(JIT)为本机代码,这就为将安全机制应用到执行代码提供了一个特有的有利位置。
程序集中还包含元数据,CLR使用元数据来找到类并进行加载、将实例布局到内存中、解析方法调用、生成本机代码、实施安全机制以及设置运行时上下文边界。
CLR和类库通过程序集来实现.NET框架的托管代码体系结构。
本文接下来的部分将更详细地讨论此托管代码体系结构。
.NET框架安全机制详述
.NET框架的安全体系结构由若干核心元素组成,包括:
∙基于证据的安全机制
∙代码访问安全性
∙验证过程
∙基于角色的安全性
∙加密技术
∙应用程序域
下面详细讨论每个元素。
基于证据的安全机制
“.NET框架”基于证据的安全子系统中的关键元素包括策略、权限和证据。
策略
任何具有信息系统安全方面经验的人都会告诉您安全是不可能凭空实现的—它必须由策略来实施。
因此“.NET框架”的所有安全机制最终都依赖于仔细定义的、用XML记录的策略。
本质上,.NET框架的策略定义了执行中的程序集中的代码可以访问哪些资源,从而防止软件错误地或恶意地破坏数据的完整性。
.NET框架中的策略无处不在,而且有充分的保护,使非管理员用户无法访问到它。
对于每一台计算机和每一个用户帐户,它都是自动安装的。
也可以选择通过“组策略”在Windows域中部署它。
.NET框架中的安全策略的基本功能是,使权限与证据匹配(我们马上就会讨论这两个问题)。
“.NET框架”原带的默认安全策略是由Microsoft设计的,其目的是为一般的最终用户创建一个安全的执行环境。
有足够特权的管理帐户也可以对它进行自定义以满足特别需要。
权限
权限是策略的根本。
权限描述了一个或多个资源及与之关联的权利,并实现用于请求访问和声明访问的方法。
.NET框架包括针对下列对象的权限:
DataAccess、DNS、DirectoryServices、FileIO、EventLog、Environment、FileDialog、Registry、Reflection、Socket、Web、IsolatedStorage、UI、Printing、MessageQueue和Security(它的成员包括AllFlags、Assertion、ControlAppDomain、ControlDomainPolicy、ControlEvidence、ControlPolicy、ControlPrincipal、ControlThread、Execution、Infrastructure、NoFlags、RemotingConfiguration、SkipVerification和UnmanagedCode)。
开发人员可以扩展这些权限定义,以包括应用程序定义的资源和用于验证访问权利的方法。
这与其他的托管代码体系结构(如Java2)是不同的,后者不容易实现这样的细微的自定义。
开发人员有一定的权利可以通过在程序集中嵌入权限请求来控制他们的代码如何对策略授予的权限作出反应。
有三种类型的权限请求:
最小、可选和拒绝。
如果策略未将列于“最小”权限集中的所有权限都授予一个程序集,则该程序集将无法加载,也就不能运行。
开发人员可以使用“拒绝”请求明确地拒绝对某些资源的访问,如果不是这样应用程序是能够访问这些资源的,但它并不是需要这些资源才能运行。
这意味着开发人员可以使他们的应用程序权限集甚至超过管理员定义的策略所允许的范围。
就从代码可以拒绝某些权限来看,它不会卷入因这些权限而引发的安全问题。
与目前业界常用的托管代码体系结构(如Java2)相比,这是一个非常精细化的能力,而且它允许将代码设计为使用最小特权来运行。
独立存储
在基于证据的安全机制所涉及的所有权限之中,“独立存储”权限值得特别提一下。
这一权限对建立在基础文件系统之上的特殊文件存储机制提供支持,但又能确保不同应用程序的储存库彼此隔离并且不暴露具体的文件系统特征(如路径名、可用的驱动器等)。
如果使用独立存储,则仍允许未被授予FileIO权限的不完全受信任的程序集在本地存储应用程序特定的数据。
但是,由于对这些存储区域的严格隔离和访问限制,这些程序集这样做时不会有危害本地文件系统或机器本身的风险。
这一点在运行不完全受信任的代码(如Internet应用程序)而同时又允许本地存储强大功能时特别有用。
证据
在运行时,CLR通过评估某一程序集的证据来决定将哪些权限授予该程序集。
证据可以来自驻留在程序集内部的各种资源,或是从本地的执行环境中收集到。
证据的来源可包括如下几种:
∙以加密方式密封的命名空间(强名称)
∙软件发行商身份(Authenticode®)
∙代码来源(URL、站点、InternetExplorer区域)
让策略、权限和证据共同起作用
到目前为止,我们已分别介绍了.NET框架中基于证据的安全模型中的每个主要组件。
不过必须说明一点,那就是这些组件必须很好地协作才能提供一个与当前我们启动可执行文件时常看到的执行环境完全不同的另一种执行环境。
有了.NET框架,几乎不需要用户在运行时做任何安全决策。
.NET框架在透明地确保最终用户运行的代码必须提前实施应用程序安全设计原则,这就使最终用户不用再作重要的安全决策了,他/她大多都不具备这一能力。
从开发人员的角度来看,所涉及的大部分工作几乎都是在幕后完成的。
只要足够的权限1和配置正确的策略能覆盖所有涉及到的资源,并且只要开发人员使用托管代码来访问它们,那么所需要所有证据核查和策略实施都可以透明地处理。
代码访问安全性
代码访问安全性(CAS)是一个强制引擎,它可确保程序集代码在计算机系统上执行时不会超越授予它的权限。
在加载托管代码程序集供执行时,它们就与一组对应的权限关联起来。
如果程序集中的一个方法需要用以访问某一资源的权限,则提供对该资源访问的代码将请求适当的权限对象。
此时,将启动一次“堆栈审核”。
这将检查调用链中的每个程序集是否已获得它所请求的权限,不只是检查直接调用方。
如果有某个调用方未通过此测试,那么将生成一个安全异常错误,且不执行请求的操作。
“堆栈审核”可防止“诱骗攻击”,在这一攻击方式中,不可靠的代码将试图“欺骗”另一个有较大权限的程序集中的代码来调用受保护的对象并绕过安全限制。
在将“.NET框架”类库用于已定义了策略和权限的资源时,“堆栈审核”完全是在幕后完成的。
开发人员可以使用两种机制来主动实施权限检查:
命令式和声明式。
命令式检查实际上就是对核心安全引擎的运行时方法调用,以请求一个需要或重写“堆栈审核”操作的某些部分。
声明式安全检查从本质上说是与此相同的。
但是它们是以自定义属性来表示的,在编译时对这些属性进行计算并嵌入在元数据中。
声明式检查包括的操作与命令式检查相同,另外还包括几个严格要求在JIT时执行的附加检查项。
在某些情况下,代码可能需要调用一个权限的断言方法以将后面的“堆栈审核”限制到此代码的堆栈帧。
这将使它即使在方法的调用方没有适当的权限时也能访问某些资源。
例如,提供文件访问的代码通常要求其调用方具有FileIO权限,但是接着断言非托管代码可以访问基础Windows文件系统的权限。
此技巧应尽量少用,而且它只能用于那些已被授予“断言”权限的高度受信任的代码。
请注意,断言操作是一种非常精细的操作,只应用于已断言的权限。
这样,代码访问安全性就为试图滥用运行代码行为的入侵者设置了一个极难逾越的“门槛”。
验证过程
确保托管代码运行时安全还有最后一个步骤,我们称之为验证过程。
在JIT编译过程中,CLR对所有的托管代码进行验证以确保内存类型的安全性。
它消除了代码执行或引发能绕过一般的应用程序流并回避安全检查的“意外”操作的这一风险。
验证过程可防止发生常见的错误,如:
使用整数作为指针来访问任意的内存位置、将对象看作其他的类型从而允许读取对象边界外的私有状态或内存、从私有字段或方法的类外访问私有字段或方法、访问新创建的尚未初始化的对象从而导致发生错误操作或访问内存中的驻留信息。
还有缓冲区溢出(提供的参数大小超过被调用的方法所期望的值)错误,引用包含定义的变量或方法入口点以外任何内容的内存、引用的堆栈位置超出所分配的堆栈帧范围(无效引用)、将执行转到进程中的任意位置等,这些也都可以通过验证过程得到防止。
这些常见的编程错误在如今的安全隐患中占到了绝大多数,但在由.NET框架提供的类型安全的托管环境中,它们已不再会带来威胁。
这本身可能就是使用“.NET框架”设计应用程序时最诱人的好处之一。
有关非托管代码的说明
如果代码不在CLR的控制下,我们就称之为“非托管”代码。
根据定义知道,非托管代码不受CLR安全措施的约束,因此有可能通过传统的攻击方法获得对本机环境中的资源的XX的访问权限。
所幸的是,大多数应用程序将永远不需要直接调用本机代码了。
“.NET框架”类库为许多非托管代码方法(即Win32API调用)实现了托管代码包装。
这些托管代码包装负责验证调用方的权限和参数,并调用适当的非托管代码。
基于角色的安全性
到现在为止,我们讨论的重点一直是“.NET框架”的代码执行模式的安全机制如何过分依赖从程序集或本地环境中读取的证据。
“基于角色的安全性”定义了“.NET框架”建立身份以及允许或拒绝该身份访问资源的方式。
这两个过程就是常说的身份验证和授权,它们是Web应用程序中安全设计的关键内容。
身份验证
“基于角色的安全性”使开发人员能够自由地为他们自己的应用程序构建高度自定义的身份验证方案。
通过多种多样的身份验证提供程序,所有最常见的身份验证例程都可在基于.NET框架的应用程序中使用。
这些代码例程验证凭据,创建适当的Identity和Principal对象,并将这些对象附加到请求的上下文中。
一旦确定了用户的身份,就可以在用户访问资源时作出授权决策。
身份验证提供程序还提供其他的功能,如为维护会话状态而生成cookie。
.NET框架支持下列身份验证提供程序:
∙基于窗体的(Cookie)身份验证:
使用这个提供程序会导致使用客户端重定向功能将未经身份验证的请求重定向到一个指定的HTML窗体。
然后用户可以提供登录凭据,再将窗体回发给服务器。
如果应用程序对该请求进行了身份验证(使用应用程序特定的逻辑),则ASP.NET将发出一个cookie,其中包含凭据或用于再次获得客户端身份的关键字。
以后发出的请求在请求头中将带有该cookie,这意味着以后不需要再进行手动身份验证了。
可以对照不同的来源(如,SQL数据库或MicrosoftExchange目录)对这些凭据做自定义检查。
此身份验证模块通常在您想将一个登录页面显示给用户的时候使用。
∙Passport身份验证:
这是由Microsoft提供的集中式身份验证服务,它为加入站点提供了单一登录机制和成员身份服务。
将ASP.NET与MicrosoftPassport软件开发工具包(SDK)结合使用,可提供类似于Passport用户使用的“窗体身份验证”(FormsAuthentication)的功能。
∙IIS:
Microsoft的IIS服务器提供了几个内置的身份验证机制。
它们可用来为IIS托管的应用程序提供身份验证。
如果存在对应的Windows帐户,IIS也可根据已验证的身份进行自动的帐户映射。
受支持的身份验证机制包括基本身份验证、NTLM、Kerberos、简要身份验证和X.509Certificates(使用SSL)。
∙Windows身份验证:
Windows支持许多身份验证机制,它们可通过SSPI子系统供应用程序使用。
这些身份验证机制包括Kerberos、NTLM和X509证书。
开发人员也可以另外编写自定义的身份验证和授权代码(例如,结合IIS匿名身份验证和ASP.NET的“窗体身份验证”提供程序),或者使用ASP.NET框架中已有的标准身份验证模块之一(将IISNTLM或Kerberos身份验证与ASP.NET的Windows身份验证提供程序结合使用)。
可以对身份验证提供程序按每应用程序和按每虚拟目录的方式来配置。
授权
一旦使用我们所熟知的这些方法中的一种方法可靠地建立起了身份,则对资源的访问权限就可以通过一个类似的可扩展而且灵活的体系结构来授予。
ASP.NET为应用程序代码提供了两种不同的授权方法:
∙文件授权:
将请求位置映射到物理文件,根据文件的ACL与发出请求2的身份的匹配情况决定是拒绝还是授予访问权限
∙URL授权:
通过将用户和角色与URI命名空间片段映射-包括请求方法(GET、HEAD、POST等)-明确地授予或撤消访问权限
例如,如要将对URL“
if(HTTPContext.IsCallerInRole("Admin"){…})
主体和身份
.NET框架使用“主体”和“身份”的概念为身份标识提供了一个丰富而可靠的对象模型。
“主体”表示运行代码的安全上下文,而“身份”表示与该安全上下文关联的用户的身份。
通常,在用户经过成功身份验证后将创建一个“身份”,并且将此“身份”附加到一个“主体”,该主体进而又与一个执行上下文关联起来。
然后在特定上下文中运行的代码可向“主体”查询关于“身份”角色的信息,根据角色的成员身份来允许或拒绝权限。
这种体系结构非常灵活,可以允许自定义角色、身份和主体。
例如,可将身份映射到存储在数据库或文本文件中的用户名/密码对。
实现GenericPrincipal对象就可以允许这些高度自定义的、不依赖于平台的授权方案。
另外,.NET框架还可以通过WindowsPrincipal对象使用传统的Windows安全子系统,这样就可方便地将角色映射到现有的Windows用户帐户和组。
当然,.NET框架能够进行客户端请求模拟来访问资源。
模拟仍是基于Windows的授权体系结构和可与其竞争的解决方案(如UNIX和Linux)之间的关键区别之一,它能使解决方案设计师可在整个应用程序的流程中一直将身份与一个用户帐户联系在一起,而不是定期向应用程序运行所在的进程传递控制权。
ASP.NET中的模拟可通过下面两种不同的方式来实现:
∙每请求模拟:
表示应用程序可使用发出请求的身份的特权来运行。
这有助于降低可能发生的安全漏洞所造成的影响同时又可提高审核能力。
∙应用程序级模拟:
运行应用程序的辅助进程使用在配置文件中指定的用户的身份来实现模拟,这样就通过将共享同着同一台服务器和系统的其他应用程序隔离并保护起来而减少了应用程序被破坏时带来的影响(也就是说应用程序被破坏不一定会导致系统被破坏)3。
模拟为ASP.NET应用程序在整个.NET框架中访问同类资源时提供了更精细的粒度和灵活性。
加密技术
与.NET框架中那些简单身份验证和授权功能的随时可用性类似,开发人员可以很方便地通过基于流的托管代码库访问到加密基元,以进行加密、数字签名、哈希散列和随机数的生成。
还为大多数CryptoAPI功能提供了包装。
支持的算法包括:
∙RSA和DSA公钥(非对称)加密
∙DES、TripleDES和RC2私钥(对称)加密
∙MD5和SHA1哈希散列法
除了支持上述基元外,.NET框架还支持通过加密流对象基于已实现的基元和各种反馈模式来进行加密。
它还支持数字签名、消息身份验证代码(MAC)/带密钥的哈希散列、伪随机数生成器(PRNG)和身份验证机制。
也支持新的或未形成标准的基元,如SHA-256或XMLDSIG。
ASP.NET包括了充分集成的对签名和加密cookie内容这一功能的支持,解决了Web应用程序安全这一长期悬而未决的敏感问题。
这些库随时可用而且种类齐全,它们将使人们对使用加密技术来加强日常应用程序的安全更有信心。
根据我们自己的经验,我们深信,实施得当的加密技术会显著提高某一给定应用程序的多方面的安全性。
应用程序域
最后,.NET框架提供了一种新方法,即通过所谓的应用程序域来隔离应用程序的各部分。
通常,操作系统通过用一个单独的进程运行每个应用程序来实现隔离,每个应用程序都有不同的地址空间,从而防止它们直接相互干扰。
但是对于高负荷的服务器,从系统性能上讲进程的开销是很高的,而且可能不允许每个访问该服务器的用户都运行一个独立的进程。
所幸的是,经过验证的托管代码具有类型安全性(它可确保代码不会访问或跳到内存中的任意地址,还有其他一
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- Microsoft NET 框架中的安全机制 框架 中的 安全 机制