第一部分 基础知识第一章 准 备
在对计算机安全进行有针对性的讨论之前,我们必须先定义这个研究领域,必须有一些通用的准则来帮助我们将今天可能遇到的大量概念和安全机制进行分类整理。因此,我们的第一项任务就是要寻找“计算机安全”的定义。为避免孤立地讨论一个个单独的安全系统,我们将提出一组通用的工程性原则,这组原则可用于指导安全的信息处理系统的设计。我们鼓励大家在阅读本书时,时刻留心书中所介绍的各类安全系统中的这些原则。
目标提出计算机安全的一种定义,介绍机密性、完整性和可用性。
解释计算机安全最根本的一个两难处境。
简述在构造安全系统时通常必须做出的一些设计决定。
指出计算机安全机制必须依赖于有效的物理或机构保护措施。
1.1 定义按照一种良好的学术传统,我们将通过定义我们的研究目标来开始我们的研究,至少我们会努力这么做。计算机安全研究在计算机系统中维护安全所使用的技术。我们不打算去区分计算机系统(不确切地说,内有处理器和存储器的装置)和信息技术(IT)系统(不确切地说,紧密耦合的计算机系统网络),因为随着技术的不断飞速发展,现代的计算机已经是一种由各部件紧密耦合而成的网络了,曾经是应用程序的软件也可能成为操作系统的一部分。Web浏览器就是当前这种趋势的一个鲜明例子,在你机器上运行的软件不需要存储在你的机器上,它可以来自于一个本地服务器,或者甚至来自于Internet上的一个web服务器。因此,你可以将“计算机安全”和“IT安全”作为同义词来使用,而不会引起太多的误解。
乍一看,计算机安全好象是一个相当显而易见的概念。然而不幸的是,安全属于这样一类概念,当你试图讲清楚它的确切含义的时候,它似乎离显而易见越来越远了。在起草计算机安全的定义以及随后对这些定义进行修正方面已经做了大量的努力。但是这些文档的编写者几乎无一例外地都被批评为眼光过于狭窄,或过多地介入了从严格意义上来说不属于计算机安全的一些计算机科学领域。
1.1.1 安全
安全是关于财产的保护。这个定义意味着你必须知道你的财产和它们的价值。这种带有普遍性的看法当然也适用于计算机安全,因此风险分析也是综合性的信息安全策略的一部分。但是,这个话题不在本书的范围之内,本书的重点在于保护措施。对保护措施的一种大致的分类如下:
预防:采取措施防止你的财产遭到破坏。
发现:采取措施使你能够发觉什么时候财产被破坏了,它是怎么被破坏的,以及是谁造成的破坏。
反应:采取措施使你能够重新获得财产,或者使财产从破坏中恢复。
为了说明这一点,考虑你家中贵重物品的保护。
预防:门窗上的锁,使盗贼难以闯入你家;保护家产的墙,或者在中世纪可以增加另一层保护,就是城堡的护城河。
发现:当某样东西不在那儿了,你将会发现它被偷了;当入室事件发生时报警器响了(希望如此);闭路电视提供的信息可以确定入侵者。
反应:你可以打电话报警;你可能决定替换被偷的物品;警察可能追回被偷的物品并送还给你。
来自物理世界的例子有助于解释计算机安全的原则,然而,将物理安全与计算机安全进行类比并不总是可能的或是可取的,事实上,有些术语应用于信息技术环境时很容易引起误解。举一个与我们讨论的领域有密切关系的例子,考虑使用信用卡号码在Internet上购物。一个骗子可能使用你的信用卡号码购物,而费用从你卡上扣除。你怎么来保护你自己呢?
预防:下订单时使用密码;依靠贸易商行在接受信用卡购物订单前对购物者进行某些检查;不要在Internet上使用你的卡号。
发现: 一项你没有授权的交易出现在你的信用卡帐单上。
反应:你可以申请一个新的卡号;欺诈交易的损失可以由持卡人、骗子购物的商行或者信用卡的发行商承担。
在这个例子中,骗子“窃取”了你的卡号,但你依然持有这张卡,这和你的卡被盗的情况是不同的。因此在某些法律框架下,比如在英国,骗子不能被起诉为盗窃你的信用卡卡号。必须制定新的律法来解决这个新的问题。
考虑保护机密信息的选择,我们继续关于保护问题的讨论。有可能仅当秘密被揭露时你才发现已经泄密了,而在某些情况下,损失是无法挽回的。你的竞争对手可能已经得到了你耗费数年功夫完成的产品设计,在你之前占领了市场,并获取了全部的利润,而你却歇业了。在这种情形下,预防是唯一的选择。这也解释了为什么历来计算机安全相当重视对机密信息泄露的预防。
1.1.2 计算机安全
为了首先获得计算机安全的概念,我们分析一下信息财富是如何受到损害的。最常给出的定义包括以下三个方面:
机密性(Confidentiality):防止未经授权的信息透露。
完整性(Integrity):防止未经授权的信息修改。
可用性(Availability):防止未经授权的信息或资源截留。
读者可以立即就这些话题的优先顺序展开讨论,并且给出一个重新排序的例子。或者读者可以论证说这个列表不完整——因为列表永远不会完整——并再增加一些内容,比如读者关心通信,可以增加真实性(可靠性,authenticity),若感兴趣电子商务类应用,则可以增加可审计性(accountability)。
即使在这样一般的层次上,你仍会发现对于某些安全方面的精确定义有不同意见。因此,我们通常会给出定义的出处,这样定义的背景就比较清楚了。象美国可信赖计算机系统评价标准(橙皮书[112])、欧洲信息技术安全评价标准(ITSEC[117])和加拿大可信赖计算机产品评价标准(CTCPEC[150])等,就是安全评价标准(第9章)的主要来源。上面的定义就出自ITSEC。
1.1.3 机密性
历史上,安全和保密是紧密联系在一起的。即使在今天,许多人仍然觉得计算机安全的主要目的是阻止未授权的用户阅读敏感信息。更一般地说,未授权的用户不应该获悉敏感信息。机密性(隐私,机密)即要解决计算机安全的这个方面的问题。术语“隐私”(privacy)和“机密”(secrecy)有时候用来区分个人数据的保护(隐私)和机构数据的保护(机密)。机密性概念已经被很好地定义了,并且计算机安全中的研究通常集中在这个题目上,因为最起码它提出了与物理安全不相类似的新问题。有时候安全性(security)和机密性(confidentiality)甚至被用作同义词。
在一个纸质文档的世界中,控制对一个文档的访问是很简单的,你只要列出那些允许阅读这个文档的人就可以了。然而稍微有些不同的是,计算机安全为实现机密性还必须控制写操作。读者将在4.2节看到更多有关这方面的内容。
1.1.4 完整性
很难给出一个简洁的完整性定义。一般来说,完整性是要确保每个事物保持它该有的状态。(很抱歉给出这样一个毫无帮助的但却反映了现实的定义。)在计算机安全的范围内,我们可能会满足于这样一个定义,即完整性研究如何防范未授权的写操作。按照这种解释,完整性是双重机密性,而我们可以指望用类似的技术来同时达到两个目的。
然而,更进一步的问题象“被授权做某人做的事”和“遵循正确的程序”也已经被包含进完整性术语中。Clark和Wilson在他们的颇有影响力的论文[32]中采用了这个方法,该论文声称完整性就是这样一种特性:
完整性 系统中的任何用户,即使被授权,也不允许以一种会使得公司的资产或帐目记录丢失或被讹误的方式来修改数据项。
如果将完整性与防止所有未授权的行为等同起来,则机密性就成为了完整性的一部分。
迄今为止,我们是通过指出必须控制的用户行为来确定安全性问题。从系统的观点来看,在定义完整性时最好把注意力集中在系统状态上。橙皮书中关于数据完整性的定义正好就是这种类型的:
数据完整性 当被计算机处理的数据与源文件中的数据一样,且没有受到意外的或恶意的修改或破坏时所呈现的状态。
在这里,完整性是外部一致性的同义词。存储在计算机系统中的数据应当正确地反映计算机系统外的某些事实。非常理想的当然是存储在任何计算机系统中的信息都正确地反映事实,然而,仅靠计算机系统内部的机制来保证这个特性是不可能的。
更为混乱的是,信息安全的其他领域有它们自己关于完整性的概念。比如,在通信安全中,完整性是指:
对因蓄意操作或随机的传输错误而引起的传输数据的修改、插入、删除或重放而进行
的检测和纠正。
当没有人被授权进行修改时,你可以把有意的修改看作是未授权修改的一种特殊情形。但是,采取这种观点并没有多大帮助,因为授权体系的有或无对于需要解决的问题的本质以及相应的安全机制都有影响。
完整性通常是其他安全特性的先决条件。比如,攻击者可能试图通过修改操作系统或操作系统引用的访问控制列表来挫败机密性控制。因此,我们必须保护操作系统的完整性或者访问控制列表的完整性来实现机密性。
最后,我们应当注意的是还有更一般的完整性定义,它把安全性和可用性都当作是完整性的一部分。
1.1.5 可用性
我们采用CTCPEC中给出的定义:
可用性 产品的服务在需要时不经太多延迟即可使用的特性。
国际标准ISO 7498-2[51],通信安全的ISO/OSI安全体系结构,给出了几乎相同的定义:
可用性 需要时可被一个授权实体访问和使用的特性。
可用性是超出传统的计算机安全范围的一个非常令人关注的问题。用于改善可用性的工程技术来自于其他领域,象容错计算。在安全领域,我们想要保证的是,恶意的攻击者不能阻止合法用户合法访问他们的系统。也就是说,我们希望防止拒绝服务(denial of service)。对此,我们引用ISO 7498-2的定义:
拒绝服务 阻止对资源的授权访问或者延误时间关键性的操作。
近来,因特网上已经出现了洪泛攻击(flooding attacks)的事件,攻击者用大量的连接请求淹没服务器,从而有效地使服务器瘫痪。在许多情形下,可用性可能是计算机安全最重要的特性,但处理这类问题的安全机制却是特别缺乏。事实上,限制太多的安全机制本身就可能导致拒绝服务。
1.1.6 可审计性
现在我们已经讨论了计算机安全的三个传统领域。回想一下,你可以看到它们都研究了访问控制的不同方面,并且把重点放在了预防令人讨厌的事件上面。我们必须接受这样的事实,即我们几乎从来都无法防止所有不正确的行为。首先,我们可能会发现授权行为可以导致安全违背;其次,我们可能会在我们的安全系统中发现一个缺陷,使得攻击者可以找到绕过我们的控制的办法。因此,你可能需要在你的安全列表中加入新的安全要求。用户应当为他们的行为负责,这个要求在正在出现的电子商务世界中尤为重要,而你已经能在象橙皮书这样历史性的文档中找到它了:
可审计性 审计信息必须有选择地保存和保护,以便影响安全的行为可以被追溯到责任方。
为了做到这一点,系统必须识别和认证用户,必须保存一份安全相关事件的审计记录。如果发生了安全违背事件,审计记录中的信息可以帮助确认作恶者,以及作恶者损害系统所采取的步骤。
1.1.7 可靠性和安全性(Safety)(安全(保险),安全,安全措施)
在进行安全性(security)讨论时,还必须提及计算的其他领域,象可靠性,它涉及(意外)故障,和安全性(safety),它涉及系统故障对环境的影响,也涉及到系统在不利条件下必须正确运行的情形。
提及这些领域的原因之一是概念上有重叠。依你首选的观点而定,安全性(security)可以是可靠性的一个方面,或者反之亦然。IFIP WG 10.4试图避免这种两难的处境,它引入可信任性(dependability)作为一个统一的概念,并将安全性(security)、可靠性、完整性和可用性当作可信任性的各个方面。
可信任性(Dependability,可靠性(强度,坚固度),相依性,依赖性) 指计算机系统的这样一种性质,它使得系统提供的服务有理由被信任。这里,系统提供的服务就是它的用户所能感知到的它的行为;用户是与系统相互作用的另一个系统(物质,人)。
原因之二是有些应用必须同时解决多个问题。比如,考虑安全紧要(safety-critical)应用中的一个计算机系统。有时系统用户必须对紧急事件作出反应,安全(security)控制应当防止入侵者恶意造成意外事故。入侵检测系统试图通过寻找陌生的行为模式来识别攻击,对紧急事件的反应有时候看上去也是陌生的——但愿紧急事件很少发生——因此入侵检测可能会将紧急情况下的合法行为误解为攻击,并启动安全(security)机制,这可能会把问题搞糟,因为安全(security)机制会干扰应急人员的行动。一般来说,你不能孤立地解决安全性(security)的问题,而不考虑你想要保护的应用的其他要求。
最后,应用于这两个领域的工程方法是类似的。比如,评价安全(security)软件的标准和评价安全紧要(safety-critical)软件的标准有许多相似之处,有些安全专家希望最终将只有一个标准。
1.1.8 我们的计算机安全定义
在本书中,我们将采用以下的计算机安全定义:
计算机安全 计算机安全研究如何预防和检测计算机系统用户的非授权行为。
正确授权和访问控制这两个概念对于本定义是至关重要的。正确授权假设存在一个安全策略,即一组声明什么行为是允许的和什么行为是禁止的规则。安全策略域即是由策略所控制的用户、数据客体、机器等实体组成的集合。
你可以将纠正不正确行为的影响包括到安全定义中,但这个方面对于我们进一步的讨论作用不大。
从对术语的初步讨论得出的主要结论是:
不存在单一的安全定义;
当你阅读文档时,注意不要将你自己的安全概念与文档中使用的概念相混淆;
大量的时间正被花费(和浪费)在试图定义明确的安全概念上。
计算机安全最根本的两难处境随着依赖计算机安全的用户数量从处理机密数据的少数公司发展到与因特网相连的每个人,人们对计算机安全的需求已经发生了巨大的变化。最起码,这种变化已经导致了一种根本性的两难处境的出现:
不懂安全的用户有特殊的安全需求,却常常不具备安全的专门知识。
这种两难处境在当前的安全评估策略中是显而易见的。通俗地说,安全评估检查产品是否提供了它所承诺的安全服务。因此,必须规定安全系统的功能,我们需要确保安全控制是有效的,并且能够抵抗渗透的企图。
橙皮书是第一本评估安全产品(操作系统)的指南,在计算机安全的发展中有着巨大的影响力。在橙皮书中,功能性和承诺(assurance,(质量)保证,担保)被捆绑成预定义的类,用户只能从这个固定的菜单中选择。许多提供商还通过给出产品的橙皮书分类来说明产品的安全等级。但是橙皮书相当刻板,并且在解决计算机网络和数据库管理系统的安全评估上还不是非常成功。因此,迫切要求有一套更灵活的标准集。
ITSEC适应了这种需要,它将功能性和承诺分开,以便规定特定的评估目标(targets of evaluation,TOE)。不懂安全的用户现在只要搞清楚特定的TOEs,并且针对不同的TOEs去比较被评估的产品。
计算机安全的这个两难处境会以不同的形式出现,解决它是目前计算机安全中最为紧迫的挑战。不足为怪的是,这个难题不存在简单的答案。
同这个根本性的两难处境相比较,安全与易于使用之间的冲突采用了简单的工程上的折衷。安全对性能的影响是多方面的。
安全机制需要额外的计算资源,这个代价容易被量化。
安全干扰用户熟悉的工作模式,繁琐或不合适的安全限制导致生产力的浪费。
必须花费精力去管理安全,因此安全系统的购买者经常选择具有最好的图形用户界面的产品。
安全是一种需要论证的代价。评估没有安全的代价属于风险分析的范围,风险分析是安全管理的一个重要方面,但它不在本书讨论的范围内。
数据对信息计算机安全是关于控制对信息和资源的访问。然而,控制对信息的访问有时是很难描述的,因此常常用更加直截了当的目标,即控制对数据的访问来代替。数据和信息之间的区别是很微妙的,但它也是计算机安全中某些更加困难的问题的根源。数据代表了信息,信息是数据的(主观)解释。
数据 依照约定所选择的用来表现我们概念上和真实世界中某些方面的物理现象。我们赋予数据的含意称为信息。数据用来传输和存储信息,以及依照形式化规则处理数据之后获取新的信息[24]。
当信息和相应的数据之间存在紧密联系时,这两种方法可能会产生非常相似的结果。但事情并不总是这样的。将信息通过一个隐蔽信道(见4.2.4)传输是可能的,在这里,数据是对访问请求的“是”或“否”的回答,而收到的信息却是一个敏感文件的内容。另一个例子是统计数据库的推理(inference)问题(见14.4)。我们来扼要地看一下这个问题,考虑一个纳税申报单的国内税收数据库,这个数据库不仅被税务稽查员使用(他们访问个人记录),也被财政部官员使用以便进行总体规划。财政部官员必须能够访问纳税申报单的统计概要,但是没有权利访问个人记录。假定数据库管理系统仅允许对足够大的数据集进行统计查询以保护个人数据,但是仍然可能对两个仅相差一条记录的足够大的数据集进行统计查询,并将查询结果结合起来。这样,即使没有对数据进行直接访问,仍然可以获得关于某条个人记录的信息。
计算机安全的原则你可能会听到这样一些话,说计算机安全是一个非常复杂的问题,“象火箭科学”。你千万不要让这样的看法把你吓倒。如果你有机会用系统化的方法去实现一个计算机系统的安全特性,那么一套行之有效的软件(系统)开发方法以及对一些基本的安全原则的良好理解,将会使你省力不少。然而,如果你事后才想起来要在一个已经非常复杂的系统上再加上安全特性,那么当你被该系统已经采取的各种并未考虑安全要求的设计决定所限制时,你就非常艰难了。不幸的是,后者的情形是经常发生的。
现在我们要提出一些基本的计算机安全设计要素(design parameters),这些设计决定提供了编排本书内容的框架。图1.1说明了计算机安全设计空间中的主要维度,横轴代表安全策略的重点(见1.4.1),纵轴代表一种保护机制被实现的计算机系统层次(见1.4.2)。
控制重点让我们重新描述1.1.4中给出的完整性定义。我们可以说完整性与服从(compliance,一致(符合,顺从))一组给定的规则有关。我们可以在以下方面定出规则:
数据项的格式和内容(内部一致性);比如,一条规则可以规定帐目数据库中的余额域必须包含一个整数;这个规则不依赖于访问数据项的用户或者作用在数据项上的操作。
可能作用在一个数据项上的操作;比如,一条规则可以规定只有“开户”、“查余额”、“取款”和“存款”操作可以访问帐目数据库中的余额项,并且只有银行工作人员允许执行“开户”操作;这样的规则可能依赖于用户和数据项。
允许访问一个数据项的用户;比如,一条规则可以规定只有帐户的持有者和银行工作人员可以访问帐目数据库中的余额项。
我们刚才已经进行了一项重要的和一般性的观察,得出了我们的第一个设计原则。
第1个设计决定(决策,decision) 在一个给定的应用中,一个计算机系统中的保护机制应该集中在数据、操作还是用户上?
在实施安全控制时,这个选择是一个基本的设计决定。操作系统传统上集中在保护数据(资源)方面,而在现代应用中则更多地与控制用户的行为有关。
1.4.2 人-机标尺
图1.2给出了一个计算机系统的简单的分层模型。这个模型只准备用作一个一般性的指导,你不应该指望在你分析的每一个计算机系统中发现所有这些层次,而当你发现一个系统有多于我们模型中给出的五个层次时也不要觉得吃惊。
用户运行应用程序,这些应用程序被定制成满足非常明确的应用需求。
应用程序可以使用像数据库管理系统(DBMS)或客体访问经纪人(ORB,object reference broker)这样的通用软件包提供的服务。
这些软件包运行在操作系统之上,操作系统执行文件和内存管理,并控制对打印机和I/O设备等资源的访问。
操作系统可能有一个协调对处理器和内存访问的内核。
硬件,即处理器和内存,物理上存储和处理计算机系统拥有的数据。
安全控制可以被合理地放置于任何一个层次上。我们现在已经解释了我们的第二个基本安全原则的各个方面。
第2个设计决定(决策,decision) 一个安全机制应该被放置在计算机系统的哪一个层次上?
当你研究已有的安全产品时,你将观察到从硬件到应用软件每一层上的安全机制。设计者的任务就是为每一个机制寻找合适的层次,以及为每一个层次寻找合适的机制。
再来看一下我们的新的安全原则,将一个计算机系统的安全机制想象成一些同心的保护环,其中硬件机制位于中心,应用机制位于外围(图1.3)。靠近中心的机制趋向于更通用、更面向计算机和更关心控制对数据的访问,外围的机制则更适合解决个别的用户需求。结合我们的前两个安全原则,我们将用人-机标尺来指放置安全机制,图1.4。
1.4.3 复杂性对保险性一个安全机制在人-机标尺上的位置常常同它的复杂性密切相关,在中心你看到简单的通用机制,而应用通常要求功能丰富的安全机制。因此,你还必须作出第三个决定。
第3个设计决定(决策,decision) 你偏爱简单性和更高的保险性(assurance,确信(保证,信心)),还是更希望一个功能丰富的(feature-rich)安全环境?
这个决定和计算机安全的两难处境相关联,一个简单的通用机制无法满足特殊的保护需要,但是要在一个功能丰富的安全环境中选择一个合适的选项,用户必须是安全专家,无疑地安全知识缺乏的用户就被置于了一个不利的位置。
为了获得高度的保险性,安全系统必须经过尽可能彻底的详细检查,因此在复杂性和保险性之间显然有一个折衷。你想要的保险程度越高,你的系统就应该越简单。因此,你将会立即注意到以下原则:
功能丰富的安全系统和高保险性(保证,assurance)是很难相互匹配的。
不难理解,高保险性要求遵从系统化的设计原则(practice,惯例;常规;准则)。事实上,计算机安全是较早利用形式化方法为工具来寻求最高程度保险性的领域之一。
1.4.4 集中式控制还是分布式控制
在一个安全策略域内,应该执行相同的控制。如果有一个唯一的中央实体负责安全,那么很容易获得一致性,但是这个中央实体可能成为性能瓶颈。反过来,一个分布式的解决方案可能更有效,但我们必须格外小心,保证不同的成员执行一致的策略。
第4个设计决定(决策,decision) 定义和执行安全的任务是应该交给一个中央实体,还是应该托付给系统中的各个成员?
这个问题出现在分布式系统安全中是很自然的,你将会看到这两种方法的例子。但是,正象Bell-LaPadula模型(见4.2)中必选和任选的安全策略所论证的那样,这个问题在大型机系统的环境下也是很有意义的。
下面的层次到目前为止,我们已经简要地谈到了保险性,但是我们主要研究了为表达最恰当的安全策略所要做的选择。现在我们该来考虑一下试图绕过我们的保护机制的攻击者了。每一个保护机制定义了一个安全周界(边界),那些失效后也不会损害保护机制的系统部分位于周界的外部,那些可被用来使保护机制失效的系统部分位于周界的里面。这个观察导致了对1.4.2中提出的第二个设计原则的一个直接和重要的扩展。
第5个设计决定(决策,decision) 你如何防止攻击者访问位于保护机制下面的层次?
可以访问“下面层次”的攻击者处于一个能够摧毁保护机制的位置。比如,如果你在操作系统中获得了系统特权,通常你就能够改变那些包含有服务层和应用层安全机制控制数据的程序或文件。操作系统的逻辑访问控制可以通过对物理存储设备的直接访问而绕过去。下面我们将进一步给出5个例子来说明这一点。安全机制有易于攻击的软肋,并易于遭受来自下面层次的攻击,这些事实表明我们必须关注这些问题,但没有必要为此而悲观失望。当你达到了一个无法运用计算机安全机制的阶段,或不想使用计算机安全机制时,你仍然能够采取适当的物理的或机构的安全措施(图1.5)。
恢复工具如果内存的逻辑组织由于某些物理的内存故障而损坏,那文件就无法访问了,即使这些文件的物理表示仍然是完整的。恢复工具,象诺顿实用程序(Norton Utilities),可通过直接读(物理)内存来帮助恢复数据,进而恢复文件结构。这样的工具当然也可以用来绕过逻辑访问控制,因为它不关心逻辑存储结构。
Unix设备
Unix将I/O设备和物理内存设备作为文件来管理,因此同样的访问控制机制也可用于这些设备,就象用于文件一样。如果访问许可定义得不好,比如将读访问授予一个包含读保护文件的磁盘,那么攻击者就可以读磁盘内容,然后重建文件。读者可以在第6章Unix安全中找到更多的信息。
客体重用(内存释放)
在一个单处理器多道程序设计系统中,几个进程可以被同时执行,但是任何时刻只有一个进程能够“占有”处理器。任何时候当操作系统挂起一个运行着的进程而去激活下一个进程时,必须执行一个上下文切换,被挂起的进程以后要继续执行时所需的全部信息必须保存下来,而与新进程相关的信息必须建立起来。出于安全的考虑,必须避免存储残留,即在分配给新进程的内存区域中遗留数据。这可以通过用一个固定的位模式重写所有被释放的存储位置或者只允许新进程对它已经写入的存储位置进行读访问来解决。
备份一个尽责的系统管理员会定期地进行备份。谁能够得到备份磁带,谁就能够访问磁带上的所有数据。逻辑访问控制在此毫无帮助,备份磁带必须被安全地锁藏起来以保护数据。
内核转储当系统崩溃时,它会创建一个其内部状态的内核转储,这样可便于确定崩溃的原因。如果内部状态包含敏感信息,如密钥,而内核转储存放在一个任何人都可以访问的文件中,那么一个警觉的攻击者可以毫无困难地破坏系统的安全。
进一步的阅读
如果你想更多地了解计算机安全,你有许多书可以作参考。文献[130]提供了对该学科的一个非常通俗易懂的介绍。如果你想一般性地了解计算机安全,特别是你想更多地了解安全管理,文献[145]是一本不错的书。在本领域的另一个方面,文献[1]介绍了计算机安全的理论基础。文献[56]详细讨论了设计安全操作系统的技术细节,综述了Gasser在上世纪80年代建立安全的操作系统的经验。文献[125]对信息安全进行了综合性的介绍,并为进一步阅读提供了许多有价值的指导。
为进一步阅读与本介绍性章节相关的内容,文献[163]中对访问路径的讨论是特别相关的。这本书还对财务部门中常用的操作系统的安全特性作了有趣而实用的描述。介绍专用操作系统安全特性的书一般比较昂贵,而且大多关注与管理这类系统有关的问题,如要调用的窗口及可选择的选项等,对安全实现的方法没有作太多深入的介绍。Park关于AS/400[122]的书是一个例外,这本书深入讨论了操作系统的技术细节,并且说明了较低层的代码怎样损害由操作系统提供的安全。关于Unix安全较好的书是[36,50,55,162],对于Windows NT你可以参考[63,139,149],象上面所说的那样,这些书也都有自己相应的读者群。对于更专门的话题,你可以在相关章节的后面找到更多资源的指导。
为了正确认识一个研究领域的现状,你还应该了解它的历史。文献[156]和[2]是两篇很有影响力的报告,它们引发了计算机安全中的许多研究。如果你无法得到这些报告,文献[93]提供了对计算机安全早期历史的一个概要。
练习题练习1.1 收集安全概念的定义。可以从美国TCSEC计划、英国ITSEC计划和加拿大 CTCPEC网站开始:
http://www.radium.ncsc.mil/tpep/process/faq.html
http://www.itsec.gov.uk
http://ftp.cse-cst.gc.ca/pub/criteria/CTCPEC
许多大的IT公司在他们自己的网站上也有关于安全的网页。
练习1.2 写一篇短文讨论数据与信息之间的区别,并用你自己的例子证明控制对数据的访问并不一定意味着就是控制对信息的访问。
练习1.3 医疗记录引起独特的安全问题。假定你的医疗记录可以被在线访问到,一方面这个信息是敏感的,应该保护不让泄漏;另一方面在危急情况下,救治你的医生必须能够访问到你的医疗记录。你如何使用预防、发现和恢复措施来保护你的记录?
练习1.4 设计一个安全策略用于保护存放在计算机系统中的考试成绩,你的策略至少应该考虑学生、主讲老师和管理人员的访问需求。
练习1.5 在你正在使用的计算系统上,找出可能包含安全机制的软件组件。
练习1.6 讨论:一个好的图形用户界面是购买安全产品的恰当的判断标准吗?
练习1.7 再找出一些例子,说明某一层的安全机制可以被能够访问较低层次的攻击者绕过。
练习1.8 确定在分析个人计算机(PC)安全时可能适用的安全周界。在你的分析中,考虑什么时候我们可以正确地假设放置PC的屋子、PC本身或者PC中的某些安全模块位于安全周界之内。
身份识别与认证安全系统有时必须检查请求服务的用户的身份,认证就是验证用户身份的过程。用户认证有如下两个理由:
用户身份是访问控制决策的一个参数;
在将安全相关事件记入审计日志时,用户身份要被记录下来。
将访问控制建立在用户身份的基础上并不总是必需的或是合适的,然而在审计日志中使用身份却有非常充分的理由。本章研究身份识别和认证,因为它是目前计算机系统的标准。分布式系统中的认证是第十章的内容。
目标重温一种相当熟悉的机制,以此来了解一些一般性的经验。
获得口令保护的入门知识。
懂得安全机制有赖于管理措施才能有效实施。
理解在计算机安全中使用抽象的危险性。
2.1 用户名和口令
确切地说,你接触计算机安全是从你注册到一台计算机上并被要求输入你的用户名和口令开始的。第一步称为识别,声明你是谁;第二步称为认证,你证明你就是你所声称的那个人。为了将“认证”这个词的用法与其他解释区分开来,我们特别指:
实体认证 验证一个被声称的身份的过程。
一旦你输入了用户名和口令,计算机就把你的输入和存在口令文件中的相应条目进行比较。当你输入了一个有效的用户名和相应的口令后,注册就成功了。如果用户名或口令不正确,注册失败。通常注册画面会再次显示出来,你可以重试一次。有些系统记录失败的注册次数,并当次数达到某门限值时锁住用户帐号。为了减少攻击者使用已有用户注册但无人看管的计算机的可能性,可以不仅在会话开始时要求认证,也可以在会话期间定期要求认证(重复认证)。你也可以选择锁住屏幕,或当某个用户空闲太久时自动关闭其会话。
重复认证解决了计算机安全中一个熟悉的问题,称为TOCTTOU(time of check to time of use),即操作系统在会话开始时检查用户的身份,而随后在会话过程中使用身份作访问控制决策。
以前,你可能会在一个包含友好欢迎词和你将要使用的某些系统信息的屏幕上输入用户名和口令。如今,警惕的系统管理员不会让外界获得太多的信息,并且将欢迎词换成了警告非授权用户不要进入。比如,Windows NT提供有一个显示法律公告的选项,用户必须接受这些警告信息,注册才能进行下去。
今天,大多数计算机系统使用基于用户名和口令的身份识别和认证作为它们的第一道防线。对于大多数用户来说,这个机制已经成为在计算机上启动一个会话过程所不可缺少的组成部分。这样,我们就有了一个广泛接受而又不难实现的机制;然而另一方面,获取有效的口令又是获得对计算机系统未授权访问的一种极其普通的方法。因此,让我们来分析一下作为认证机制的口令的实际安全性。我们将考虑以下三种威胁:
口令猜测口令欺骗口令文件泄漏不要忘了用户在口令保护中起着重要的作用。当你泄漏了口令,比如告诉了同事,或者写在便笺上并贴在计算机上,都会危及到认证的安全。
选择口令口令选择是一个重要的安全问题。尽管你无法完全避免攻击者意外地猜测出有效的口令,但你可以努力使这种事件的发生率尽可能的低。为说明如何做,你必须知道攻击者基本上遵循以下两种猜测策略:
穷尽搜索(强力):尝试有效符号所有可能的组合,直到一定的长度。
智能搜索:通过一个受限的名字空间进行搜索,比如,尝试那些与用户有联系的口令,像名字、朋友和亲戚的名字、汽车商标、车牌号、电话号码等,或者尝试那些较常流行的口令。这种方法的一个典型例子是字典攻击,它尝试来自于一个在线字典的所有口令。
那么,你的防卫措施是什么?
设置口令:如果系统管理员或者用户忘了为用户帐户设置口令,攻击者甚至免除了猜测口令的麻烦。
改变缺省口令:当系统被交付使用时,它们通常带有缺省的帐户,像具有缺省口令manager(“管理员”)的缺省帐户system(“系统”)。这有助于现场工程师安装系统,但是如果口令不改,攻击者可以很容易地进入系统。在刚才举的例子中,攻击者甚至可以获得一个非常有特权的帐户。
口令长度:为了挫败穷尽搜索,必须规定一个最小口令长度。不幸的是,许多Unix系统的最大口令长度只设到8个字符而已。
口令格式:在你的口令中混合使用大、小写字母,并且包含数字和其他非字母符号。
避免易于猜测的口令:当你发现攻击者配备有流行口令的清单,并且字典攻击已经大大扩展了“易于猜测”的范围时,你不要觉得吃惊。今天,几乎针对每一种语言你都可以找到一本在线字典。
系统怎样进一步地帮助改善口令的安全性呢?
口令检查器:作为一个系统管理员,你可以使用针对某些“脆弱”口令字典的口令检查工具来检查口令。这样可以模仿并先发制人地对付针对系统的字典攻击。
口令生成:某些操作系统包含有口令发生器,能够生成随机的和可发音的口令。用户不允许选择自己的口令,而必须采用系统建议的口令。
口令老化:许多系统可以设置口令到期的日期,迫使用户定期改变口令。可以有附加机制防止用户回复到老的口令,比如,使用一个保存有最近用过的10个口令的列表。当然,通过足够多次的改变直至老的口令又被接受,坚定的用户还是能够回复到他们喜爱的口令的。
限制注册尝试:系统可以监视不成功的注册企图并作出反应,完全锁住用户帐户,或至少锁住一段时间,以防止或阻止进一步的尝试。
通知用户:在成功注册之后,系统可以显示上一次注册的时间以及从那以后失败的注册企图次数,从而提醒用户有关最近的攻击企图。
依照刚才所说的,似乎只要用户使用由系统产生的长口令、口令中混合使用大小写字母和数字符号、并定期改变口令,我们就可以获得最高的安全性。这种方法真的奏效吗?在实际中我们获得希望的安全性了吗?
用户不太可能记住长而复杂的口令,因而,这样的口令将被记在纸上,并放在靠近计算机的地方,而这对合法用户和潜在的入侵者都是最有用的,因此留心贴在计算机终端上的口令是安全管理员的本职工作。当口令频繁改变时也有类似需要考虑的问题。发现难以按照这种严格的口令管理方案去做的用户,可能试探着去使用更易于记忆从而也更易于被猜测的口令。他们可能很快回复到他们喜爱的口令,或对口令作一些简单的和易于推断的改变。比如,如果你必须每个月改变口令,将月份(两个数字,从1到12,或三个字母,从JAN到DEC,依你的选择)加到你所选择的口令上,就提供了你可以记住的口令。当然,攻击者只要发现了其中的一个口令,他就很容易猜测下一个。
还有另外一个方面的问题你必须考虑。假定你的用户非常认真地采取了所有的安全预防措施,避免使用易于猜测的脆弱口令,不把口令写下来,但是不可避免地经常忘记口令,这会影响用户的工作。为了获得一个新的口令,用户必须同系统管理员联系,这又会影响系统管理员的工作,并为新的攻击开辟途径。如果用户和系统管理员不能亲自见面,他们可能需要通过电话协商新的口令。系统管理员能够正确地认证用户吗?威逼操作员发布口令被证明是一种可靠的侵入系统的方法。成功的攻击更多地依赖于社交能力而不是技术的精巧。
你一定不能孤立地考虑安全机制。事实上,在一种安全机制上强调太多可能会削弱系统,因为至少用户会找出绕过安全机制的途径去做他们的工作。通过口令,你已经注意到口令的复杂性和人的记忆本领之间的折衷。
欺骗攻击通过用户名和口令的身份识别和认证提供了单向认证(unilateral,一方的(单向的))。用户输入口令,计算机验证用户的身份。但是,用户知道谁接收了这个口令吗?到目前为止,这个答案是否定的。用户不能保证线路另一端当事人的身份。
这是一个现实的问题,它导致了第二种类型的口令泄漏。在欺骗攻击中,攻击者(他可能是一个合法用户)运行一个程序,在某些终端或工作站上给出一个假的注册画面。一个毫无戒备的用户来到这个终端试图注册。这个受害者通过标准注册菜单的引导被要求输入用户名和口令,这些信息被攻击者保存下来。然后执行可能被移交给用户,或者用一个(假的)出错消息中止注册,欺骗程序终止运行。控制被返回到操作系统,操作系统用一个真的注册请求提示用户,用户重试,第二次注册成功,并可能完全不知道口令已经泄漏的事实。针对这样的欺骗攻击该怎么办呢?
显示失败的注册次数可以暗示用户已经发生过这样的攻击。如果你的第一次注册失败了,但在你进行第二次注册时,你被告知自上一次会话以来没有不成功的注册,那么你就应该有所怀疑了。
可信任路径:保证用户是与操作系统通信而不是与一个欺骗程序在通信。比如,Windows NT有一个安全注意序列CTRL+ALT+DEL,它调用Windows NT的操作系统注册画面。你应该按这样的安全注意键开始一个会话,即使这时屏幕上已经显示了注册画面。
相互认证:如果用户要求更有力地确信与之通信的系统的身份,如在一个分布式系统中,那么可以要求系统向用户认证自己。
除了欺骗攻击,入侵者还可以有其他“找到”口令的方法。上面我们对于注册的描述是相当抽象的,口令直接从用户传递给口令检查例程。实际上,口令会被临时存放在中间存储位置,如缓冲器、高速缓存,或者甚至是一个网页。这些存储位置的管理通常超出用户的可控范围,而口令在这些位置的存放时间可能会比用户预料的要长。
在开发基于web的在线银行服务[5]时,开发者遇到的一个问题很好地说明了这一点。Web浏览器会缓存信息,以便用户能够返回到他们最近访问过的页面。为使用在线银行服务,你在一个web页上输入你的口令。你处理完你的事务,关闭银行应用,但是没有终止浏览器进程。该终端上的下一个用户能够回退到有你口令的那一页,并以你的名义注册。
作为一种防范措施,建议在完成银行事务后退出浏览器。注意到现在用户被要求参与到内存管理活动中来,这在其他地方是不会涉及到的。这是客体重用(见1.5)的又一个例子。
抽象是有用的,同时又是危险的。用抽象的术语来讨论口令安全是有用的;你可以研究关于口令格式或口令老化的策略,而不需要知道在你的IT系统中口令是怎么处理的。仅在这样抽象的层次上讨论口令安全是危险的,实现方面的缺陷会损害最好的安全策略。
保护口令文件为了验证用户的身份,系统将用户输入的口令同保存在口令文件中的一个值进行比较。对于攻击者来说,这样的口令文件当然是极具吸引力的一个目标。未加密的口令文件内容的泄漏或者对口令文件内容的修改,构成了口令泄漏的第三种可能。你甚至可能还要关心加密口令的泄漏,那样字典攻击可以离线进行,而象(像)限制失败的注册次数这样的保护措施将不会起作用。为保护口令文件,我们可以有以下选择:
密码保护,
操作系统执行访问控制,
密码保护和访问控制相结合,或者可能有更强的保护措施来减慢字典攻击的速度。
对于密码保护,我们甚至不需要加密算法,有一个单向函数就行了。目前,你可以使用以下的初步定义:
单向函数就是易于计算但很难逆推的函数,也就是说,给定x很容易计算f(x),但给定f(x)很难计算x。
第12章有关于单向函数的更详细的介绍。单向函数早就用于保护存储的口令了([158],p.91ff),口令文件中保存的不是口令x 而是f(x)。当用户注册并输入口令(设为x')时,系统调用单向函数f,并将f(x')与用户的f(x)相比较,如果两个值相同,用户就被成功认证。下面我们将使用“加密的”口令这个词,即使实际上我们只是对口令使用了一个单向函数。
如果不担心字典攻击的话,口令文件现在谁都可以看了。如果f是一个真正的单向函数,从f(x)重建口令x是不可行的。在字典攻击中,攻击者“加密”字典中的所有单词,并与口令文件中的各个加密表项进行比较,如果找到匹配的表项,攻击者就知道了那个用户的口令。单向函数可以用来减慢字典攻击的速度,这种考虑指导了在Unix系统中选择使用单向函数crypt(3),该函数使用略加修改的DES算法,用全零的数据块作为初始值,用口令作为密钥,重复运行算法25次[104]。当然,这会给合法用户注册带来一点点性能损失,但是如果你优化了单向函数的速度,你同时也提高了字典攻击的性能。
操作系统中的访问控制机制只允许拥有适当权限的用户访问文件和其他资源。只有特权用户才能写口令文件,否则的话,即使口令被加密保护了,攻击者也可以简单地通过修改用户的口令来访问这些用户的数据。如果只有特权用户才能读口令文件,那么从理论上说口令可以不用加密保存。如果口令文件中包含了非特权用户也需要的信息,那么口令文件必须包含加密的口令。然而,这样的文件仍然可被用于字典攻击,一个典型的例子是Unix的/etc/passwd。因此,最近的Unix版本将加密的口令保存在一个不可公开访问的文件中,这样的文件被称为影子口令文件(shadow password files)。比如,HP-UX可以使用一个影子口令文件/.secure/etc/passwd。
专用存储格式提供了一种较弱的读保护形式,比如Windows NT以专门的二进制格式保存加密的口令。一般用户的攻击企图会被挫败,但是一个意志坚定的攻击者将能获得或推断出必要的信息,从而找到安全相关数据存储的位置。“通过隐匿而获得的安全性”本身不是非常强壮,但可以把它加到其他机制上,如口令加密。
但是,存在着这样一种危险,就是对这种外围防线的成功突破会摧毁其他所有的部分。1997年初,有人声称Windows NT的口令安全已被突破了。听上去很严重,是吗?实际情况是发布了一个程序,能将加密的口令从二进制格式转换成另一种易于阅读的表示形式。激动之余发现根本不是什么大事情。
如果你担心字典攻击,但又不能隐藏口令文件,你可以考虑口令加盐。当一个口令需要加密保存时,加密前将一些附加信息(盐)附加到口令上,盐同加密的口令保存在一起。如果两个用户有相同的口令,它们在加密口令的文件中将有不同的表项。加盐减慢了字典攻击的速度,因为不可能同时搜索几个用户的口令。
你已经看到了三个安全设计的问题:
几种机制结合起来可以增强保护。加密和访问控制用来保护口令文件。
通过隐匿而获得的安全性只能防御不经心的入侵者。不要对这种策略抱太多的信任。
如果可能的话,将安全相关的数据和那些要被公开访问的数据隔离开来。在Unix中,/etc/passwd包含有以上两种数据。影子口令文件能够获得所希望的隔离性。
2.5 一次签到
用口令来区分朋友和敌人已经有几个世纪了。在IT环境中,它们控制对计算机、网络、程序和文件等的访问。但作为用户,如果你为获取一点信息而在信息空间漫游时必须一遍又一遍地输入口令,你会觉得很不方便。当你坐在计算机前,需要网络中某台数据库服务器中的信息时,如果你必须做以下一些事情,你会觉得愉快吗:
向计算机输入第一个口令,
输入第二个口令进入网络,
输入第三个口令访问服务器,
输入第四个口令访问数据库管理系统,
输入第五个口令打开数据库中的一张表。
且不去想可能需要记忆五个不同的口令,并需要在每一种场合选择一个正确的口令输入,就是将相同的口令重复输入五遍也是够糟糕的了。
一次签到服务解决了这个问题。你只要输入一次口令,系统保存这个口令,并在你需要重新认证的时候为你取出口令做这件事。
这样一种一次签到服务为你增加了方便,但它也引起了新的安全问题。你如何保护存储的口令?前面提到的一些技术不再有用,因为系统现在需要你的明文形式的口令。
系统设计者必须均衡考虑方便性和安全性。易于使用是使得IT系统真正有用的一个重要因素,不幸的是,许多方便的举措也引入了新的弱点。后面还会遇到这样的问题。
可供选择的方法如果你不满足于口令提供的安全等级,你还可以做什么呢?从一般观点来看,以下选择都是可取的。作为用户,你可以基于以下信息进行认证:
你知道的事,
你拥有的东西,
你是谁,
你做什么,
你在哪里。
你知道的事
用户必须知道一些“秘密”才能被认证。你已经看到了这种认证模式的第一个例子,口令就是你知道的事情。另一个例子是同银行卡一起使用的个人识别号码(PIN)或者类似标记(tokens)。第三个例子,考虑你打电话查询银行帐户的情形,接听电话的银行职员在告诉你任何信息之前可能会向你询问更多的个人信息,像家庭住址、出生日期、配偶名字等。
在这种认证模式中,获知你秘密的任何人就“是你”,另一方面,如果你把你的秘密告诉其他人,你不会留下痕迹。考虑以下情形,在你单位发生了滥用计算机的事件,有人用你的用户名和口令注册了。你能证明你是无辜的吗?你能证明你没有泄漏口令吗?
你拥有的东西
用户必须出示一个物理标记才能被认证。能打开锁的钥匙就是你拥有的东西,这种标记的另一个例子是用于控制进入公司大门的卡片或身份标签。在将来,一旦智能卡的读卡机成为工作站的标准部件,智能卡可能成为口令的替代物。
物理标记可能会遗失或被盗。如前所述,任何拥有标记的人将具有与合法拥有者相同的权利。为了增加安全性,物理标记通常与你知道的事结合起来使用,如银行卡与PIN一起使用,或者它们包含能够识别合法用户的信息,如银行卡上的照片。然而,就是将这些机制结合起来也不能防止骗子获得必要的信息去假冒合法用户,也不能阻止用户自愿传递这些信息。
你是谁
如果你真的必须准确无误地认证每一个人,你可以使用生物测定技术。刚才已经提到了带有照片的卡片,更复杂的方法使用掌纹、指纹、虹膜图案或视网膜图案来辨别一个人。
口令认证每一次都给出明确的拒绝或接受。在生物测定中,一个存储的图案与实际测量的图案进行比较,但这些图案几乎从来都不能精确匹配。因此,我们必须面对一个新的问题,就是假阳性(false positives)和假阴性(false negatives)。错误地接受一个用户(假阳性)显然是一个安全问题,而拒绝一个合法用户(假阴性)则会造成尴尬的及低效的工作环境。生物测定认证系统的设计者必须在这两种错误之间找到合理的平衡,而这种平衡极其依赖于找到这种平衡的应用。
还有一个问题,用户会接受这样一个机制吗?在被提取指纹时,他们可能感觉象被当成了罪犯一样,他们可能也不喜欢用一束激光扫描视网膜的做法。
你做什么
人们往往以一种独特的和可重复的方式做一些机械性的工作。检查手写签名就是来自纸质文档世界的一个例子,在这里伪造并不是那么困难的。为了获得更高的安全性,用户可以在一个特殊的垫子上签名,垫子可以测量出像书写速度和书写力度这样的特征。在一个键盘上,打字速度以及击键之间的间隔被用来认证用户个人。如前所述,认证系统必须建立起来,使得假阳性和假阴性减少到相关应用可以接受的程度。
你在哪里当你注册时,系统可能还要考虑你在哪里。一些操作系统已经这样做了,并且仅当你是从某个特定的终端注册时才允许访问。比如,系统管理员只可以从操作员控制台注册,而不能从任何一台用户终端注册。类似地,作为用户你只允许从你办公室的工作站上注册。这类决定在移动和分布式计算中将会更加频繁。如果在认证过程中必须建立精确的地理位置,系统可以使用全球定位系统(GPS)的服务。在处理一个请求的注册时确定用户的位置,也有助于解决过后关于用户真实身份的争端。
口令并不能认证人:成功的认证只意味着用户知道一个特定的秘密。没有办法区分合法用户和获得了该用户的口令的入侵者。
进一步的阅读
文献[104]介绍了Unix口令安全的历史,在上面还可以找到非常有趣的关于典型口令选择的统计,文献[48]介绍了Unix口令安全后来的发展。文献[63,139]描述了Windows NT的口令方案。几乎所有关于计算机安全的书都包含有大量的有关正确选择口令的建议,并且阐述了口令安全的重要性。Pfaffenberger关于因特网隐私的书[124]有一章介绍了自动口令生成,并附有指向相关软件产品的链接。
你可以在因特网上找到大量的口令破解程序,分析这样的一个程序将使你对破解程序搜索的口令类型以及所使用的字典的长度和复杂性有一个清楚的了解,但未经明确授权而运行这样一个程序可能与你单位的规章制度以及许多国家的刑法相抵触。
练习题练习2.1 检查你计算机系统上的口令方案。它在口令长度、口令格式以及口令期限方面有规定吗?口令在你系统上是怎么存储的?
练习2.2 假定只允许使用26个字母来构造口令:
如果口令最多为n个字符,n=4,6,8,不区分大小写,可能有多少个不同的口令?
如果口令最多为n个字符,n=4,6,8,区分大小写,可能有多少个不同的口令?
练习2.3 假定口令的长度为6个字符,可以使用字母和数字字符,区分大小写。在以下条件下,强力攻击平均所需的时间分别为多少?
检查一个口令需要1/10秒时间;
检查一个口令需要1微秒时间。
练习2.4 假定你只允许使用26个字母来构成长度为n的口令,进一步假设你在区分大小写和不区分大小写的两个系统中使用了相同的口令,给出猜测出大小写区分的口令所需的最多尝试次数。
练习2.5 编程:写一个口令生成程序,以一个长度为s的随机二进制种子作为输入。在下面的实验中取s=8,16,32,64:
让不同的用户用你的方案生成口令,记录不同的用户选择了相同口令的事件。
生成一个口令并加密之。通过尝试随机种子的所有值试图找出原来的口令。在找到口令之前你需要的猜测次数的期望值是多少?
练习2.6 讨论:口令由用户输入并由计算机检查,因此,在用户和计算机之间一定有通信的通道。到目前为止,我们一直是非常抽象地看待这个通道,假设它存在并且足够安全。什么时候这种假设是合理的?什么时候是不合理的?
练习2.7 如果你每次都要求使用几个口令,你可能考虑将它们保存在一个口令簿里。口令簿是一个含有你口令的受保护文件,对口令簿的访问可以通过一个主口令来控制。这样一个方案能够提供实际的好处吗?
练习2.8 [65]中描述的口令猜测在时间和内存之间存在一个折衷。令N为可能的口令数目,在一个使用N次试编码的预计算步骤中,构造出一个具有N2/3个表项的表。如果你过后想找出一个给定的加密口令,你需要N2/3次试编码。当长度为6的口令选自于5-比特字符集时,你需要多少内存空间?如果一次试编码耗时1毫秒,你多快能找到口令?
练习2.9 对商用生物测定认证系统进行一次调查,你发现用户对此系统的接受程度如何?
访问控制现在你已经登录到了系统上,创建了新的文件,并且想保护你的文件。你的有些文件可能是公用的,有些仅打算给有限的用户使用,而有些可能是私有的。你需要一种语言来表达你想要的访问控制策略,并且需要执行访问控制的机制。本章介绍一些讨论访问控制的词汇,第四章将详细讨论访问控制策略。
目标介绍访问控制的基本模型。
考虑几组访问操作,明白用直觉来代替术语的实际定义是危险的。
给出独立于特定安全策略的基本的访问控制结构。
定义部分排序(order)和格(lattice),这是经常用来表达安全策略的数学概念。
3.1 背景
在深入到访问控制的细节之前,先来考虑一下计算机系统以及计算机系统的使用在过去的几十年中发展的方式。计算机系统处理数据,并且协调(mediate,处于中间的(作为引起...的媒介,调停))对内存、打印机等共享资源的访问。它们必须提供对数据和资源的访问控制,尽管主要是为了完整性而不是机密性的缘故。传统的多用户操作系统为众多不同的用户提供普通服务,就其本质来说,这些操作系统具有简单和通用的访问操作,并且不牵涉到它们所处理的文件的意义。现代桌面操作系统支持单个用户完成他们的工作,在这种情形下,你会发现非常复杂并且极其依赖于特定应用的访问操作。用户并不关心他们程序执行时较低层的细节,因此可以想象,将高层的安全需求映射到低层的安全控制上可能是十分困难的。简而言之,你将会目睹从通用计算机系统到(灵活的)专用计算机系统的转变,在比较本书介绍的不同的访问控制模型时将这个趋势牢牢地记在心里。
3.2 主体和客体 注:大多安全方面的书在涉及安全模型时把object译为客体;在面向对象程序设计时,则译为对象。
为了讨论访问控制,我们首先必须给出一个合适的术语。“访问”的本质含义是一个主动的主体使用某种特定的访问操作去访问一个被动的客体,同时有一个引用监视程序(reference monitor)(第五章)准许或拒绝访问。这个基本的访问控制模型(见图3.1)是由Lampson[82]提出的。
典型的主体是用户或进程,典型的客体是文件或资源,象内存、打印机或计算机网络中的节点。但这并不是要把系统中的每个实体都明确地分为主体或客体,根据不同的情况,一个实体可以是一个访问请求的主体,而又是另一个访问请求的客体。术语“主体”和“客体”只是区分一个访问请求中的主动方和被动方。主体和客体给出了关注控制的两个选项,你可以规定以下任一种:
一个主体允许做什么,或者可以对一个客体做什么。
这是1.4.1中第一个设计原则的例子。传统上,一个操作系统的主要任务是管理文件和资源,也就是客体。在这样一种环境下,你主要遇到的是使用第二种方法的访问控制机制。然而,我们刚才已经提到了面向应用的IT系统,象数据库管理系统,直接面向终端用户提供服务。这种系统可以适当地加入控制主体行为的机制。
3.3 访问操作
访问操作是不同的,取决于你如何看待一个计算机系统,可以从基本的内存访问到面向客体系统中的方法调用。类似的系统可能使用不同的访问操作,更糟的是,在看似相同的操作上可能附加不同的含义。我们将研究一些典型的访问操作集,并从该领域早期的重要成果中确定我们的术语。
3.3.1 访问方式
在最基本的层面上,一个主体可以观察一个客体或者改变一个客体,因此,我们定义两种访问方式:
观察: 查看客体的内容
改变: 改变客体的内容
尽管大多数访问控制策略可以按照观察和改变的观点来表示,但这种策略描述通常离它们正在处理的应用太远了,难以检查正确的策略是否已经执行了。因此,你通常会发现一组较为丰富的访问操作。
3.3.2 访问权限和访问属性
在下一个复杂度上,你会发现4.2中讨论的Bell-LaPadula安全模型的访问权限,和Multics操作系统[119]中的访问属性,这是计算机安全历史上的两个里程碑。
有四种访问权限,执行、读、添加(有时也称为盲写)和写。图3.2给出了这些访问权限与观察和改变这两个基本访问方式之间的关系。
为了弄懂这样定义的原因,考虑一个多用户操作系统如何控制对文件的访问。用户在允许存取前必须先打开文件,通常文件可以被打开用于读或写。在这种方式下,操作系统可以避免象两个用户同时写同一个文件这种可能的冲突。为了效率的缘故,写访问通常包括读访问,比如一个编辑文件的用户不应该要求打开文件两次,一次用于读,一次用于写。因此,定义写命令是有意义的,以便它可以包括观察和改变这两种方式。
几乎没有一个系统真正实现了添加操作。在大多数的应用中,允许用户不观察客体的内容而去改变客体是一种不可行的操作。审计日志是添加权限有用的一个例子,写日志文件的进程不需要读文件,并且可能根本就不应该读文件。
操作系统可以根本不打开文件而使用文件,如程序,因此引入了既不包括观察也不包括改变方式的执行权限。你可能要问计算机怎么能够不读程序的指令就执行程序呢?你当然是对的,而且Multics执行属性确实要求执行和读权限。但是存在一些操作,客体的内容不读就可以用于执行中。考虑一个加密引擎,它在一个特殊的防篡改寄存器(图3.3)中存有一个主密钥,物理上没有办法可以读出这个主密钥,但是访问控制规则可以决定谁能使用这个密钥加密。我们可以不读这个密钥而调用它,执行权限刚好是解决这样一个问题所需要的。
在解释其他人定义的访问操作时,小心使用你自己的直觉。
Multics操作系统区分数据部分的访问属性和目录部分的访问属性。根据客体的类型用不同的方法解释一组给定的访问权限实际上是一种普遍的做法,在命名这些访问属性时我们仍然要使用象“读”或“写”这样的术语。为了使我们的表示法保持清晰,我们将用e,r,a,w来表示Bell-LaPadula访问权限。图3.4显示了访问属性和访问权限之间的对应关系。
3.3.3 Unix
一个较常用的例子是Unix操作系统的访问控制,访问控制策略用三种操作来表示:
读(read):从一个文件读;
写(write):写进一个文件;
执行(execute):执行一个(程序)文件。
这些操作同Bell-LaPadula模型中的那些操作不同,比如,在Unix中写访问并不意味着读访问。当应用于目录时,访问操作采用以下含义:
读:列出目录内容;
写:创建或重命名目录中的一个文件;
执行:搜索目录。
如你所见,Unix通过控制对文件目录的写访问来控制谁可以创建和删除文件,其他操作系统包含一个特殊的删除操作用于该目的。Unix中为文件规定的访问权限是通过修改文件在目录中的表项被改变的,其他操作系统则包含特殊的操作用于此目的。
3.3.4 Windows NT
作为最后一个例子,我们来看一下Windows NT操作系统的新技术文件系统(NTFS)用作访问控制基础的许可(permission,许可,容许,同意,【WIN,NT】权限)[63],它们是:
读
写
执行
删除
改变许可
改变所有权(ownership)
在这里,我们不依赖对目录的操作来处理文件的删除或访问权限的改变。修改访问权限是你在设置安全策略时可能想使用的一种操作,这种修改主体访问权限的操作在主体的权限被其他方修改时倾向于称为准许(grant)和取消,而在主体改变自己的访问权限时称为声明(assert,宣称(声明,维护),断言)和否认(deny)。在授权(delegation,授权;代理;代表团)策略中,当一个主体调用另一个主体且需要建立被调用主体的权限时,这一类操作是令人感兴趣的。
3.4 所有权
我们已经提到了控制主体如何访问客体的策略,并将在下一章中讨论这样的策略。我们还必须规定谁负责制定这些策略,有两个基本的选择:
资源的所有者规定谁可以访问。这类策略可称为是自主性的(自主的,discretionary),因为访问控制任由所有者来处理。
一个系统范围的策略规定谁可以访问。显然,这类策略可称为是强制性的(mandatory)。
大多数操作系统支持资源所有权的概念,并且在作访问控制决策时考虑所有权。它们可能包含重定义资源所有权的操作。
上面给出了自主性/强制性访问控制的直观解释,这仅是为了说明不应该将它们同计算机安全中常用的自主/强制性访问控制的定义相混淆。在计算机安全中,这些术语指的是橙皮书[112]中所规定的特定的安全策略。再一次声明,你必须小心不要让你的直觉误导你。
3.5 访问控制结构
下面,我们必须声明哪些访问操作是允许的。访问权限可为每个主体和客体的组合单独定义,对于数量众多的主体和客体,这种结构管理起来很不方便,而采用中间控制层是较为可取的。在下面的段落中,我们要涉及到:
主体集合S,
客体集合O,
访问操作集合A。
我们不需要对这些集合作更详细的解释了。
3.5.1 访问控制矩阵
访问控制(access rights)用一个访问控制矩阵(表)很简单地定义:
M = (Mso)s(S,o(O 且 Mso(A,
表项Mso规定了主体s可以施加于客体o上的访问操作的集合。这种方法回到了计算机安全的早期[82]。访问控制矩阵也被称为访问许可矩阵。访问控制矩阵是一个抽象的概念,当主体和客体的数量很大或者主体和客体的集合频繁改变时不太适合于直接实现。
Bell-LaPadula模型(4.2)使用访问控制矩阵建立橙皮书中的自主性访问控制策略模型。图3.5给出了一个具有两个用户和三个文件的访问控制矩阵的简单例子。
bill.doc可以被Bill读和写,但完全不允许Alice访问。
edit.exe可以被Bill和Alice执行,但除此以外他们不能访问。
fun.com可以被两个用户读和执行;只有Bill能够写这个文件。
3.5.2 能力(capabilities)
你几乎不会去直接实现一个访问控制矩阵。访问权限可以和主体保存在一起也可以和客体保存在一起,这之间有一个选择。在第一种情况下,每个主体被赋予一个能力(capability),这是一个说明该主体访问权限的不可忘却的标记,这个能力对应于访问控制矩阵中的主体行。我们前一个例子中作为能力给出的访问权限是:
Alice的能力:edit.exe,execute; fun.com,execute,read
Bill的能力:bill.doc,read,write; edit.exe,execute; fun.com,execute,read,write
典型地,能力是同自主性访问控制相联系的。当一个主体创建一个新的客体时,它可以通过授予其他主体合适的能力来允许它们访问这个客体。同样,当一个主体(进程)调用另一个主体时,它可以将它的能力,或者它的部分能力传递给被调用的主体。
能力决不是一个新的概念,但是到目前为止它们还没有成为一个广泛使用的安全机制,其原因如下,主要与安全管理的复杂性以及操作系统面向管理客体的传统定位有关。
对于谁可被获准访问一个给定的客体难以得到一个全面的了解;
取消一个能力非常困难,或者操作系统必须被授以这个任务,或者用户必须清楚它们已经传递的所有能力,当能力中的权限包括向第三方传递该能力时,这个问题尤其棘手。
然而,分布式系统的出现重新引起了人们对基于能力的访问控制的兴趣,在分布式环境中安全策略必须处理在计算机网络的节点间进行物理地或虚拟地漫游的用户。
当你决定使用能力时,你还必须花费一些心思考虑它们的保护问题。你将能力存放在什么地方?如果能力仅在一个单独的计算机系统中使用,那么仅依靠操作系统的完整性保护(第五章)就可以了。当能力在网络中传播时,你还需要加密保护(第十二章)。
3.5.3 访问控制列表
访问控制列表(ACL)将客体的访问权限同客体本身存放在一起,因此,一个ACL对应了访问控制矩阵中的一列,声明谁可以访问一个给定的客体。ACL是橙皮书C2类[112]安全操作系统的一个典型特征。我们前一个例子中的访问权限用ACL的形式表示为:
bill.doc的ACL Bill,read,write
edit.exe的ACL Alice,execute; Bill,execute
fun.com的ACL Alice,execute,read; Bill,execute,read,write.
访问权限的管理仅依靠单个主体是相当麻烦的,因此通常将用户置于组中,并也可以从用户组取得访问权限。在UNIX中,你见到过附在文件上的简单的ACL,它允许对三类主体规定其基本访问模式,即用户、组和其他(见6.4)。
对于主要配合客体访问管理的操作系统来说,ACL是一个合适的概念。但是,如果你想总的了解一个用户有哪些许可,比如要取消那个用户的许可,你需要费力地搜索所有的ACL。
3.6 中间控制
不管你如何实现访问控制矩阵,在一个大型的系统中管理用这种矩阵表示的安全策略是一项复杂的任务,尤其是,要确保矩阵中的每一项正确表示我们的意愿是繁琐和易于出错的。另外,仅依靠主体和客体的访问控制只支持相当有限的安全策略。可以被适当地包含进一个访问控制决策的其他信息可以是主体用来访问客体的程序,这完全不是一个新的思想,你可以从以下对Titan操作系统[109]的访问控制所作的评论看到这一点,该操作系统是牛津大学于60年代早期开发的。
特别地,使用一个程序标识作为访问控制决策的一个参数,和用户标识一起使用或者替代用户标识使用是可能的,这是牛津的人们一直以来觉得不可思议而没有采用的特性。
不要认为新技术必然引起新的安全问题,“新”问题时常是老问题的化身,而它们的解决原则都已是知道的。
3.6.1 分组和否定的许可
组作为一种简化访问控制策略定义的方法已经被提及到。具有类似访问权限的用户被集合成组,组被授予访问客体的许可。一些安全策略要求一个用户只能是一个组的成员,其他一些安全策略则允许是多个组的成员。
图3.6显示了一种理想状况,所有的访问许可可以通过组成员关系来传达(be mediated,处于中间的(作为引起...的媒介,调停),处在中间调解,斡旋,介于)。通常,安全策略有一些特殊的场合,在这些场合中直接给某些主体访问一个客体的许可,或者否认一个主体从它的组成员关系中获得的许可是较为方便的。一个否定的许可(negative permission)就是访问控制结构中的一个表项,它规定了一个主体不允许执行的访问操作。图3.7中,主体s1不允许访问客体o1,而主体s3被准许访问客体o5。
图3.6
3.6.2 保护环
保护环是用于说明主体和客体之间中间层的一个特别简单的例子。每个主体(进程)和每个客体依照其“重要性”被赋予一个数字,在一个典型的例子中,这些数字可以是0、1、2和3。进程按照以下规则获得它们的数字:
操作系统内核,
操作系统,
实用程序,
用户进程。
要进行访问控制决策,就比较主体和客体的数字。(决策的结果依赖于你使用保护环想要执行的安全策略。)这些数字对应同心保护环,其中环0位于中心,提供最高程度的保护(图3.8)。如果一个进程被赋予数字i,那么我们说进程“运行在环i”。
保护环主要被用于完整性保护。QNX/Neutrino微内核的系统/用户保护是说明这种保护机制的一个最新例子,它将软件组件分配给保护环,如下:
Neutrino微内核运行在环0。
Neutrino进程管理器运行在环1。
所有其他程序运行在环3。
包含敏感数据(如操作系统代码)的内存位置只能被运行在环0或环1的进程访问。
Unix使用一种类似的保护模型,但只使用级0和级3。保护环已经用于Multics操作系统中,并且开发了特殊的硬件来支持这种安全机制[138]。Intel 80386和80486微处理器在机器语言级上提供了类似的特性。然而,保护环是一种一般性的工具,可用来实现不同于这儿或者文献中提到的访问控制策略。
3.6.3 VSTa微内核中的能力(Abilities)
为了表达更复杂的访问控制策略,你需要中间层上的概念,这样更灵活,并且具有更多的内部结构。VSTa微内核的能力是这种概念的一个很好的例子,因为它们不完全是3.5.2中定义的能力(capability),所以我们使用abilities来表示。一个ability就是一个数据结构,它从一个点开始,后面跟有n个整数的一个序列,即一个ability就是一个串.i1.i2.….in,其中i1…in是整数。序列的长度n没有限制,事实上n可以等于0。Abilities的例子有.1.2.3,.4或.10.0.0.5。由于它们的内部结构,abilities集合上存在一个部分排序(偏序,partial ordering)。
定义 集合L上的一个部分排序(是L(L上的一个关系,它是
反身的 对于所有a(L,a(a成立
传递的 对于所有a,b,c(L,如果a(b且b(c,那么a(c
反对称的 对于所有a,b(L,如果a(b且b(a,那么a(b
如果两个元素a,b(L是不可比的,我们记为a(b。(符号(与书上的不一致)
Abilities可通过前缀关系进行排序。
Ability a2是ability a1的一个前缀,如果存在另一个ability a3使得我们有a1(a2a3。这时我们记a2( a1。
有了前缀排序,你就可以比较abilities了,你将得到.1(.1.2(.1.2.3,但.1(.4。一种访问控制策略可用abilities标记主体和客体,并且当主体的ability是客体的ability的一个前缀时允许访问。如果是这样,那么可以访问所有客体的超级用户的ability就是一个空串(。因此,不给一个主体赋予ability,你就可以准许它访问所有的客体。
访问控制算法比较主体和客体的属性,你一定要检查一下如果某些属性缺失会怎么样。万无一失的行为要求拒绝访问,但通常情形不是这样的,你会觉得非常吃惊和不快。
3.6.4 特权
将你的注意力转到操作上,你可以收集以特权执行某些操作的权限。典型地,特权和操作系统功能相联系,并且涉及象系统管理、备份、邮件访问或网络访问等行为。你可以将特权看成是主体和操作之间的一个中间层(图3.9)。
图3.9
3.6.5 基于角色的访问控制
特权通常是和操作系统一起预先确定的。一组应用特定的操作(过程)称为一个角色,主体从它们履行的角色上获得访问权限。基于角色的访问控制(RBAC)将注意力集中在用户和用户执行的任务上。
主体和客体之间的中间层有助于减少管理访问控制的复杂性。中间层可被插入到多个位置上,这样你可以使用多个层次来构造访问控制。你的层次选择包括:
角色:一个角色就是一组过程,角色被分配给用户。一个用户可以有多个角色,多个用户也可以有相同的角色[134]。
过程:过程是语义比读或写更复杂的高层访问控制方法,过程只能被应用于某些数据类型的客体上。作为一个例子,考虑银行帐户之间的资金转移。
数据类型:每个客体属于一种特定的数据类型,只能通过为该数据类型定义的过程来访问。通过限制可以访问客体的过程来控制对客体的访问是一种常见的程序设计惯例。这是抽象数据类型理论的一个基本概念。
尽管这种结构化的访问控制是许多应用非常希望的,但是许多操作系统还不支持它。突出的例外是IBM AS/400[122]中的用户概述(profile)和Windows NT(第七章)中的全局组和本地组。RBAC更常见于数据库管理系统中。
3.7 安全级别的格(Lattice)
领会计算机安全的基本内容并不一定需要弄懂格,不过,在阅读了该课题的许多文献后却有助于理解格。象保护环或者VSTa的abilities一样,安全级别是另一种用来标记主体和客体的安全属性,是表达安全策略的基础。作为一个简单的例子,考虑四个线性排序的安全级别,“非机密的”(unclassified)、“机密的”(confidential)、“秘密的”(secret)和“绝密的”(top secret),如图3.10。强制性访问控制策略(MAC)和橙皮书中的多级安全策略指的是安全级别。下面,我们用L表示安全级别的集合。
图3.10
如果你坚持采用安全级别的线性排序,那么你只能表达有限的一组安全策略,因此最好能有一种更一般的排序结构可以使用。3.6.3引入的安全级别的部分排序(满足我们的部分要求,因为我们不要求L中每两个元素都是可比的。
我们的下一个要求是由标准的机密性策略引起的,仅当主体的安全级别高于客体的安全级别时,这个主体才可以查看这个客体。对以下两个问题我们希望有唯一的答案:
给定两个不同安全级别的客体,一个主体至少必须具有什么样的安全级别才能允许读这两个客体?
给定两个不同安全级别的主体,为使一个客体能被两个主体查看,该客体能够拥有的最高安全级别是多少?
能让我们回答这两个问题的数学结构已经有了,它称为格。格可被形式化地定义如下:
定义 格(L,()由集合L和部分排序(组成,对于自主两个元素a,b(L,存在一个最小上界u(L和一个最大下界l(L,也就是说
a(u,b(u,并且对所有v(L,( a(v ( b(v ) ( ( u(v )
l(a,l(b,并且对所有k(L,( k(a ( k(b ) ( ( k(l )
在安全中,如果a(b,我们说“a受控于b,或者“b控制a”。受控于所有其他级别的安全级别称为系统低,控制所有其他级别的安全级别称为系统高。
图3.11给出了格的一个典型例子。集合L是{a,b,c}的幂集(({a,b,c}),部分排序是子集关系(,系统低时集合为空集(,系统高时集合为{a,b,c}。子集关系通过一个图来描述,节点为(({a,b,c})的元素,节点间的箭头给出了部分排序的“构架”。准确地说,对于A,B((({a,b,c}),当且仅当A( B,A(B,并且不存在一个C((({a,b,c})使得A(C(B和A(C和B(C,我们置一个从A到B的箭头。
图3.11
有了这个约定后,那么,当且仅当从A到B存在一个箭头链时A是B的一个子集。本书中我们将采用这种形式的可视化部分排序。
格的下一个例子要引入一个在橙皮书及相关文档的多级安全策略中具有重要地位(坚固的,firm place)的结构,该结构将在第四章介绍。
令H为一个分类集合,其等级(线性)排序为(H;
令C为一个种类集合,如工程名字、公司部门、学院的系等等;
一个间隔就(compartment,隔室,隔箱;象限,舱)是一组种类;
一个安全标签(安全级别)就是一个二元组(h,c),其中h(H是一个安全级别,而c(C是一个间隔;
安全标签的部分排序(定义为:(h1,c1) ( (h2,c2) 当且仅当h1 (H h2和c1 ( c2。
图3.12说明了这种结构。有两个等级级别public和private,两个种类PERSONNEL和ENGINEERING。在产生的(ensuing,随后的(下一个))格中,以下关系成立:
(public,{PERSONNEL}) ( (private,{PERSONNEL}),
(public,{PERSONNEL}) ( (public,{PERSONNEL,ENGINEERING}),
(public,{PERSONNEL}) ( (private,{ENGINEERING})。
图3.12
有了这个安全标签的格,你就能够实现强制性的需要知道(最小特权)策略。为了说明这一点,按照上面提到的简单的机密性策略,看一下图3.12的格。具有安全标签(private,ENGINEERING)的主体将不能够读任何在其标签的隔间中种类为PERSONNEL的客体,因此,即使是标记为(public,{PERSONNEL,ENGINEERING})的客体也是不能读的。
我们从图3.10中简单的等级格来开始我们的安全格讨论并不是偶然的,等级格在政府部门的多级安全策略中是很典型的,并且这样的系统已经被构造出来以非常高的安全度执行这些策略,然后我们加入间隔来表达更多种类的策略。今天,我们看到使用多级安全系统的应用,因为这种系统安全度高,但在它们的安全级别中完全没有等级成分。比如,一种防火墙方法可以使用图3.13的格实现网络内部和外部的严格隔离,我们甚至不需要知道如何解释部分排序就可以作此声明。
图3.13
进一步的阅读
文献[1,39,125]介绍了基本的访问控制结构和安全格,早期较有影响的访问控制(保护)方面的论文是[82,131],[158]较详细地介绍了60年代开发的操作系统的访问控制,更多关于保护环安全策略的例子在[111,125]中。基于角色的访问控制的最新调查发表在[134],[133]中可以找到更多有关基于格的访问控制模型的信息,以及如何使用它们来处理机密性和完整性问题的描述。
有关QNX/Neutrino微内核和VSTa微内核的网页分别是:
http://www.qnx.com/literature/nto_sysarch/nto_sysarch.html,
http://www.zendo.com/vsta/vsta_intro.html。
练习题练习3.1 给你两个比特来获得目录上的访问操作,你如何使用四种可用的操作?你如何控制文件的创建和删除?你如何使用这些访问操作实现隐藏文件的概念?(隐藏文件只对授权主体是可见的。)
练习3.2 考虑一个具有读、写、准许和取消四种访问操作的系统,你可以使用准许grant来授予其他主体读和写的访问权限,你还可以使用准许grant来授予其他主体对你拥有的客体发布访问准许的权限。你准备使用什么样的数据结构和算法来实现准许和取消操作,以使你能够取消对你拥有的一个客体的所有访问?
练习3.3 讨论:组和角色之间的区别是什么,如果这种区别存在的话?
练习3.4 解释为什么3.6.3中定义的abilities的部分排序不构成格。尝试着在abilities集合中加入任何你需要的元素,将部分排序转换成一个格。
练习3.5 给你一个安全策略,规定当且仅当主体的安全级别控制客体的安全级别时,主体才能够访问客体。图3.14中的格与该策略一起使用的结果是什么?
练习3.6 令(L,()是一个安全级别的格,L是一个有限集合。证明在这样的格中一定存在唯一的系统低和系统高。
练习3.7 为安全级别public、confidential、strictly confidential和种类ADMIN、LECTURERS、STUDENTS构造安全标签的格。在一个需要知道策略中,哪一个客体对于一个具有(confidential,{STUDENTS})安全标签的主体是可见的?从n个安全级别和m个种类可以构造出多少标签?作为例子,考虑n=16,m=64。
练习3.8 给你一个安全策略,使用间隔格作为安全标签,仅当主体的标签是客体标签的一个子集时,访问才被准许。用种类ADMIN、LECTURERS和STUDENTS,哪一个客体可被一个具有标签{STUDENTS}的主体访问?为什么一个具有{ADMIN,STUDENTS}标签的主体比一个具有{STUDENTS}标签的主体受限制更多?说明标签(和{ADMIN,LECTURERS,STUDENTS}在该策略中的角色。
练习3.9 给你一组种类,实现一个基于格的需要限制策略,有选择地从主体收回访问权限。
第四章 安全模型
你的安全策略是什么?哪一条规则决定谁可以访问你的数据?为了制订一个安全策略,你必须描述策略控制的实体,并且陈述构成策略的规则。安全模型正是做这样的事情。本章建立在前一章的基础上,研究一些最有影响力的安全模型。
安全模型为机密性(如Bell-LaPadula)和完整性(如Biba,Clark-Wilson)寻找策略。有些模型适用于策略为静态的环境(Bell-LaPadula),其他一些模型则考虑访问权限的动态变化(Chinese Wall,中国墙)。形式化的安全模型,象Bell-LaPadula,在高保险度安全评估中具有突出地位。非形式化模型,象Clark-Wilson,更大程度上是一种表达安全策略的描述性框架。
目标说明如何用形式化方法来表示安全策略。
介绍计算机安全历史上几个重要的里程碑。
了解不同安全模型的范围和局限性。
理解安全中的一些决策问题本质上是不可判定的。
4.1 状态机模型
状态机(自动机)是为计算系统的许多方面建立模型的一种流行工具,我们假设本书读者已经熟悉了这方面的内容。毫不奇怪,状态机也是一些重要的安全模型的基础。状态机模型的主要特点是状态以及发生在离散时间点上的状态变化的概念。状态就是所研究的系统在某个时刻的一种表现,它能准确捕捉(capture,记录;以影片、文字等保存原状)与我们的问题相关的那些系统方面。可能的状态迁移(转换,transition)可以通过状态迁移(下一个状态)函数来描述,该函数根据当前状态和输入来定义下一个状态,也可能产生出一个输出。
如果我们想用状态机模型来讨论系统的某个特殊性质,如安全,我们首先必须确定达到该性质的所有状态,然后必须检查是否所有的状态迁移保持这种性质。如果是这样,并且系统是从满足这种性质的起始状态开始运行的,那么我们可以通过推理证明这个性质总是成立的。
4.2 Bell-LaPadula模型
在安全系统的设计和分析中安全模型是一个重要的概念,它们体现了系统中应该执行的安全策略。Bell-LaPadula模型(BLP)可能是最著名的安全模型,它由Bell和LaPadula在第一次联合设计安全的多用户操作系统时提出。BLP是描述访问控制的机密性问题的状态机模型,访问许可通过访问控制矩阵和安全级别来定义,安全策略防止信息从高安全级别流向低安全级别,这些策略一般地被称为多级安全(MLS)。BLP只考虑了主体在查看或改变一个客体时发生的信息流动。我们对BLP模型的描述从以下集合开始:
主体集合S;
客体集合O;
访问操作集合A = {execute,read,append,write},直接借鉴了3.3.2的访问权限;
具有部分排序(的安全级别集合L。
我们想用系统的状态来检查系统安全,因此,模型的状态集必须包括当前所有的许可和当前所有主体访问客体的实例。这导致了一个相当复杂的状态集B(((F,其中
B = P(S(O(A)是当前访问的集合。元素b(B是一组三元组(s,o,a),表示主体s当前正在客体o上执行操作a。
(是访问许可矩阵M = (Mso) s(S,o(O的集合。
F( LS(LS(LO是安全级别分配的集合。元素f(F是一个三元组(fS,fC,fO),其中
fS,S→L给出了每个主体可以拥有的最高安全级别,
fC,S→L给出了每个主体当前的安全级别,
fO,O→L给出了所有客体的分类。
一个主体的当前级别不能高于它的最高级别,因此fC(fS,读作“fS控制fC”,很快你会看到引入fC的原因。最高安全级别有时候称为主体的许可(clearance),其他文献只用许可来表示用户的安全级别。
定义状态集是BLP的主要问题,我们不需要描述输入、输出或者状态迁移的精确结构来给出BLP的安全特性。
4.2.1 安全策略
BLP将安全定义为状态特性。多级安全策略仅当主体的安全级别控制客体的分类时允许主体读这个客体,这些多级安全策略也称为强制性安全策略(mandatory security policies)。第一个显而易见的特性是简单安全性(ss-property):
ss-property 如果对于每一个元素(s,o,a)(b,访问操作a是读或写,主体s的安全级别控制客体o的分类,即fO(o) (fS(s),那么状态(b,M,f)满足ss-property。从这个特性获得(capture,俘[捕]获,捕捉)了传统的无向上读安全策略(no read-up security policies)。
然而,ss-property不足以防止一个低级别的主体读一个高级别客体的内容。可以创建一个高级别的特洛伊木马,读高级别的客体并将它拷贝(写它的内容)到一个低级别的客体。因此,我们还必须通过(-property(星特性)控制写访问:
(-property 如果对于每一个元素(s,o,a)(b,访问操作a是添加或写,主体s的当前级别被客体o的分类所控制,即fC(s) (fO(o),那么状态(b,M,f)满足(-property。这是一个无向下写安全策略(no write-down security policies)。此外,如果存在一个元素(s,o,a)(b,访问操作a是添加或写,那么对于所有的客体o',(s,o',a')(b,a'是读或写,我们必须有fO(o') (fO(o)。
这个定义清楚地表明高级别的主体不能发消息给低级别的主体。有两种方法可以避开这个限制:
临时地降低一个高级别主体的等级,这是引入当前安全级别fC的原因。
确定一组允许违背(-property的主体,这些主体称为可信主体(trusted subjects)。
第一种方法假设一个主体被降级时,它忘记了它在较高安全等级上所知道的一切。当你把主体看成人时,这个观点看起来不合情理,但BLP是模拟计算机的,这里主体(进程)没有自己的记忆,它们所“知道”的唯一事情是它们被允许查看的客体(文件)的内容。在这种情况下,临时降级确实解决了问题。
换句话说,fS规定了用户的许可,用户允许以低于许可的级别注册,fC表明了用户实际注册的级别。
当采用第二种方法时,(-property只对不可信的主体有效。按定义,一个可信主体可以违背安全策略。事实上,为集中注意力,你可以很好地用形容词“可信的”来识别那些会伤害你的系统组件。相反,如果你确信一个主体不会伤害你,那么称它为值得信赖的。
橙皮书使用术语自主性(自主)访问控制(discretionary access control,DAC)来表示那些基于指定的用户和指定的客体的访问控制策略,拥有一项访问许可的主体可以将许可传递给其他主体。在BLP中,这种策略通过一个访问控制矩阵表示,并通过自主性安全特性(ds-property)获得。
ds-property 如果对于每一个元素(s,o,a)(b,我们有a(Mso,那么状态(b,M,f)满足ds-property。
如果一个状态满足所有三种安全特性,这个状态则被称为是安全的。
4.2.2 基本安全定理
如果状态v1 = (b1,M1,f1)和状态v2 = (b2,M2,f2)都是安全的,那么称从状态v1到状态v2的迁移是安全。为了弄清楚需要进行什么样的检查才能确定一个新状态是安全的,考虑ss-property例子。状态迁移保持ss-property,当且仅当:
每个(s,o,a)(b2\b1满足关于f2的ss-property;(b2\b1表示b2和b1的差集)及如果(s,o,a)(b1不满足关于f2的ss-property,那么(s,o,a)(b2。
(-property和ds-property特性的保持可以用类似的方法来描述。现在我们能够描述BLP模型的一个重要特性。
基本安全定理 如果系统中所有的状态迁移都是安全,并且系统的初始状态也是安全的,那么不管输入情况如何,其后的每一个状态也都是安全的。
该定理的形式化证明通过对输入序列的长度作归纳来进行。证明建立在这样的事实上,即每个状态迁移保持安全,且不引用特定的BLP安全特性。
基本安全定理是状态机模型的产物,而不是BLP模型中选用的特定安全特性的结果。
实际上,基本安全定理减少了检验系统安全所需的努力。你可以分别地检查每一个状态迁移证明它保持了安全性,并且需要确定一个安全的初始状态。只要你以这种安全的初始状态启动系统,它将一直是安全的。
4.2.3 稳定
McLean在1987的一篇文章[96]中提出了一种包含以下状态迁移的系统,从而引发了一场关于BLP模型的价值的激烈讨论:
将所有的主体降到最低的安全级别,
将所有的客体降到最低的安全级别,
在访问控制矩阵M的所有位置输入全部的访问权限。
按照BLP的定义,这个迁移到达的状态是安全的。但这种状态能被视为是安全的吗?因为BLP是这么说的,因此BLP正确地抓到安全了吗?有两种意见:
反对BLP的(McLean):直观地说,如果一个系统能被带入到一种允许每个人读任何信息的状态,那么这个系统是不安全的。因此,BLP必须改进。
赞成BLP的(Bell):如果用户要求这种状态迁移,那么应当在安全模型中允许这种状态迁移。如果它不被要求,那么就不应该去实现它。这不是BLP的问题,而是正确获取安全需求的问题。
争论的根源是改变访问权限的状态转移。这种改变在BLP的一般性框架中当然是可能的,但是模型的组织者实际上考虑的是访问权限固定的系统。安全级别和访问权限从不改变的这种特性称为稳定性(tranquility),不改变访问权限的操作称为是稳定的(tranquil)。
4.2.4 BLP的各个方面及其局限性
BLP是一个非常重要的安全模型,它在安全操作系统的设计中起着重要的作用,而且几乎任何一种新的模型都要和BLP相比较。在这种情形下,分析BLP的一些特征是很有好处的。
模型的描述能力:BLP状态集描述了当前所有的访问操作和访问许可。
安全策略是以安全级别和访问控制矩阵为基础的,在这些地方很容易引入其他结构。比如这样一个情形,主体只允许通过某些程序来访问客体,要建立这样一个访问控制模型,S(S(O访问控制结构更为合适。
实际的安全特性:在BLP中,我们有ss-property,(-property和ds-property。Biba模型(见4.5)和BLP模型的主要区别在于安全特性。
特殊解决方案:比如,Multics说明(见5.4.3)中的状态迁移。
BLP用访问控制来定义安全性是它深受欢迎的一个主要原因。因此,用BLP来表示操作系统或数据库管理系统的行为是不太困难的。然而,尽管它是一个重要的安全模型,BLP没有涵盖安全的所有方面。对它的批评有:
只涉及机密性,而没有涉及完整性,
没有解决访问控制的管理问题,
包含隐蔽通道。
缺乏完整性策略是BLP的一个特征,而不是一个缺陷。你很快将会看到,对于一个安全模型来说,限制它的目标是非常合理的。BLP没有针对修改访问权限的策略,事实上,BLP最初打算用于没有安全级别改变的系统。
隐蔽通道就是一个不受安全机制控制的信息流[150]。如果低级别的主体可以看见高级别客体的名字,而只被拒绝访问客体的内容,那么客体的名字就是一个明显的隐蔽通道。在BLP中,你可以用访问控制机制本身构造一个隐蔽通道,信息可以像下面所示的那样从一个高安全级别流向一个低安全级别:
一个低级别的主体在本级别上创建一个客体dummy.obj。
它的高级别同谋(一个特洛伊木马?)提高或者不改变dummy.obj的安全级别。
过后,低级别主体试图读dummy.obj。该请求的成功或失败暴露了高级别主体的行为,一比特的信息从高级别流向了低级别。
告诉一个主体某个操作是不允许的,这就构成了信息流。这导致了数据库安全中有趣的解决方案(多实例化),一个客体在不同的安全级别上可能有不同的值,从而避免这类问题的发生(第十五章)。
有时,仅仅隐藏客体的内容是不够的,可能也必须隐藏它们的存在。
4.3 Harrison-Ruzzo-Ullman模型
Bell-LaPadula模型没有就改变访问权限或创建、删除主体与客体规定策略,Harrison-Ruzzo-Ullman(HRU)模型定义了解决这些问题的授权系统[64]。为描述HRU模型,我们需要:
一个主体集合S,
一个客体集合O,
一个访问权限集合R,
一个访问矩阵M = (Mso) s(S,o(O;元素(表目,entry)Mso是R的子集,说明了主体s对客体o拥有的权限。
有六种原语操作用于处理主体集、客体集和访问矩阵:
enter r into Mso
delete r from Mso
create subject s
delete subject s
create object o
delete object o
HRU模型中的命令有以下格式:
command c(x1,…xk)
if r1 in Ms1,o1 and
if r2 in Ms2,o2 and
if rm in Msm,om
then
op1
op2
opn
end
下标s1,…sm和o1,…om是参数表(x1,…,xk)中出现的主体和客体。条件列表检查特定的访问权限是否出现,条件列表可以为空。如果所有的条件成立,那么基本的操作序列被执行。每个命令至少包含一个操作,比如命令
command create_file(s,f)
create f
enter o into Ms,f
enter r into Ms,f
enter w into Ms,f
end
由主体s用来创建一个新的文件f,s是文件的所有者(访问权限o),并且对文件有读和写的许可(访问权限r和w)。文件f的所有者s用以下命令将读访问授予另一个主体p:
command grant_read(s,p,f)
if o in Ms,f
then enter r in Mp,f
end
命令的结果作为访问矩阵的变化被记录下来,因此访问矩阵描述了系统的状态,习惯上用M'表示修改后的访问控制矩阵。HRU模型能够获得控制访问权限分配的安全策略。为了验证一个系统符合这种策略,你必须证明不存在颁授不希望的访问权限的情况。
定义 称一个状态(即访问控制矩阵M)泄露了权限r,如果存在一个命令c将权限r加到了访问矩阵中一个原先不包含r的位置上。更正式地说,存在s和o,使得r( Ms,o和r( M's,o。
定义 称一个状态(即访问控制矩阵M)关于权限r是安全的,如果没有一个命令序列能够将M变换到泄露r的状态。
因此,在HRU模型中验证符合一个安全策略归结为验证安全特性,但是你发现你现在处于一个非常不容乐观的位置。
定理 给定一个访问矩阵M和一个权限r,验证M关于权限r的安全性是一个不可判定的问题。
因此,你不能一般性地解决安全问题,而必须通过约束模型来获得更好的成功机会。比如,你可以只允许单操作命令,即包含单一操作的命令。
定理 给定一个单操作的授权系统、一个访问矩阵M和一个权限r,验证M关于权限r的安全性是一个可判定的问题。
你只需允许每个命令包含多至两个操作就可使安全问题重新变得不可判定。限制授权系统的大小是使得安全问题易于处理的另一种方法。
定理 如果主体的数量是有限的,那么自主授权系统的安全问题是可判定的[89]。
这些关于安全问题可判定性的结论约略解释了第三条设计原则。如果你设计的复杂系统只能用复杂的模型来描述,那么要找到安全证明是困难的,在最坏情况下(不可判定性)不存在一个验证所有问题实例安全性的通用算法。如果你想要可验证的安全特性,最好限制安全模型的复杂性。这样的模型可能无法描述所有希望的安全特性,但是你可以获得有效的验证“安全性”的方法。因此,设计能够用简单模型充分描述的简单系统是明智的。如果系统和模型间存在太大的差距,模型中的安全证明就不太重要了。
安全模型的表达能力越强,包括安全特性和它能够描述的系统,验证安全特性通常也越困难。
4.4 中国墙模型
Brewer和Nash提出的中国墙模型模拟了咨询公司的访问规则,分析员必须保证他们与不同客户(公司)的交易不会引起利益冲突[23]。通俗一点说,冲突的产生是因为客户是同一个市场的直接竞争者或者是不同公司的所有者。分析员必须遵循以下安全策略:
规则 一定不能有引起利益冲突的信息流。
Bell-LaPadula模型的状态集需要一些小小的调整来实现这个策略:
公司的集合用C表示。
客体集合O是有关一个公司的信息条目。显然,分析员是主体,而S是主体的集合。
有关同一个公司的所有客体集中在一个公司数据集(dataset)中,函数y,O(C给出了每个客体的公司数据集。
利益冲突组指出哪些公司在相互竞争,函数x,O(P(C)给出了每个客体的利益冲突组,即不应该知道该客体内容的公司集合。
客体o的安全标签是(x(o),y(o))。
净化的信息被去除了敏感的细节,不受访问限制的控制。对于一个被净化的客体o,我们设x(o)=(。
利益冲突的产生不仅与当前访问的客体有关,也与过去访问过的客体有关,因此我们需要一种记录主体行为历史的方法。为此目的,我们引入了一个布尔矩阵N=S(O,其中
Ns,o =
如果你对于所有的s(S和o(O置Ns,o = false,你将得到一个安全的初始状态。
第一个安全策略涉及直接信息流。我们希望防止一个主体遭受利益冲突,因此仅当被请求的客体属于以下两种集合时访问才被允许:
用户已经拥有的一个公司数据集,或者一个完全不同的利益冲突组。
我们可以将它正式地表示成ss-property,如下:
ss-property 主体s允许访问客体o,仅当对于所有Ns,o' = true的客体o',有y(o)(x(o')或y(o)=y(o')。
该特性本身没有完全实现规定的安全策略,仍有可能发生间接信息流。考虑下面的例子。两个竞争者,A公司和B公司,在同一家银行开有帐户;处理A公司与银行业务的分析员A,用A公司的敏感信息更新银行资产负债表;处理B公司与银行业务的分析员B,现在可以访问到竞争者的经营信息。因此,我们引入(-property来控制写访问。
(-property 主体s允许对客体o进行写访问,仅当s对于y(o)(y(o')和x(o')((的客体o'没有读访问权。
仅当没有其他的位于不同公司数据集且包含非净化信息的客体能被阅读时,对一个客体的写访问才是允许的。
与访问权限通常假设为静态的BLP不同,我们现在面对的是一个在每次状态迁移中访问权限都要重新检查的模型。
4.5 Biba模型
Biba模型[19]使用一种非常类似于BLP的状态机模型,从主体访问客体这个角度来处理完整性问题。有一个完整性级别的格(L,(),函数fs,S(L和fo,O(L将完整性级别赋给主体和客体。这些级别构成了表达完整性策略的基础,完整性策略解决“干净的”高级别实体被“脏的”低级别实体污染的问题。在完整性的格中,信息只能向下流动。和BLP只有一个高级别完整性策略不同,在此你会看到有很多种方法,有些方法甚至产生出互不兼容的策略。
4.5.1 静态完整性级别
对应BLP的稳定性特性,我们可以规定完整性级别不变的策略,以下两个完整性特性是强制性BLP策略的对偶。
简单完整性特性:如果主体s可以修改(改变)客体o,那么fs(s)(fo(o)。(No write-up)。
完整性星特性:如果主体s可以读(查看)客体o,那么仅当fo(p)(fo(o),s可以写访问另一个客体p。
这两个策略防止干净的主体和客体被脏的信息污染。
4.5.2 动态完整性级别
类似于中国墙模型,下面两个完整性特性自动调整一个实体的完整性级别,如果该实体已经接触了低级别的信息。
主体低水印特性:主体s可以读(查看)任何完整性级别上的客体o,主体的新的完整性级别是inf(fs(s),fo(o)),其中fs(s)和fo(o)是操作前的完整性级别。 注释:Inf,下确界客体低水印特性:主体s可以修改(改变)任何完整性级别上的客体o,客体的新的完整性级别是inf(fs(s),fo(o)),其中fs(s)和fo(o)是操作前的完整性级别。
完整性级别inf(fs(s),fo(o))(fs(s)和fo(o)的最低下限)是良(完全地,well)定义的,因为我们处理的是完整性级别的格。
4.5.3 调用的策略
可以扩展Biba模型以包含访问操作调用(invoke)。主体可以调用另一个主体(如一个软件工具)来访问一个客体,这是向在中间层上表达访问控制迈出的第一步。应当用什么样的策略来控制调用?我们想确保调用不会绕过强制性的完整性策略吗?那么,我们可以加入调用特性:主体s1可以调用主体s2,仅当fs(s2)( fs(s1)。
主体只允许在较低级别上调用工具,否则的话,一个脏的主体就能用一个干净的工具去访问和污染一个干净的客体。
另一种情况,我们可能就想为此目的而使用工具。脏的主体应该可以访问干净的客体,只要它使用一个干净的工具来访问,这个工具可以执行许多一致性检查,确保客体仍然保持干净。在这种情形下,我们可能不希望干净的主体使用脏的工具,我们可以采用
环特性:主体s1可以读任何完整性级别上的客体,它只能修改fo(o)(fs(s)的客体o,并且仅当fs(s1)( fs(s2)时可以调用主体s2。
很显然,最后两个特性是不一致的,我们必须根据应用来决定哪种特性更合适。
4.6 Clark-Wilson模型
Clark和Wilson研究商务应用的安全性需求[32]。他们认为这些需求主要是关于数据完整性的,即防止未授权的数据修改、欺骗和错误。这是一个相当广泛的完整性定义,事实上,作者甚至包括了并发控制的问题,该问题超出我们的安全范围。完整性要求被分成两部分:
内部一致性:涉及系统内部状态的特性,可通过计算系统实施;
外部一致性:涉及系统内部状态和真实世界的联系,必须通过计算系统以外的手段来实施,如审计。
实施完整性的一般机制是:
组织良好的事务:数据项只能通过一组特定的程序来操作;用户可以访问程序而不是数据项;
责任分离:用户必须协同起来才能操作数据和穿透(collude to penetrate)安全系统。
责任分离在一个安全系统的操作中反复出现。要求不同的人开发、测试、证明和运作一个系统是合理的。反过来,也可能要求不同的人在操作中必须协同工作才能实现一个事务。
Clark-Wilson模型用程序作为主体和客体(数据项)之间的中间控制层,主体被授权执行某些程序,数据项可通过特定的程序访问。定义可以访问某个特定类型数据的程序集是软件工程的一种常用机制(象在抽象数据类型[39]和面向客体程序设计中),这种机制可以被卓有成效地运用到构造安全的系统中。Clark和Wilson写到“用程序而不是安全级别来标记主体和客体”,这是对BLP影响力的一个有力证明。在Clark-Wilson模型中,完整性意味着:
被授权将一个程序应用到可以被该程序访问的一个数据项上。
Clark和Wilson强调了军事安全与商业安全要求之间的区别,观察表明机密性和完整性的相对重要性在这两个世界中是不同的,但是也存在着有完整性要求的军事应用和有机密性要求的商业应用。对我们来说,还有一个更相关的区别,Clark-Wilson模型中的访问操作是执行复杂的特定应用操作的程序,而BLP中的访问操作是简单的、通用的和适合操作系统的,因此我们看到了通用操作系统(BLP)和面向应用的IT系统(Clark-Wilson)之间的区别。总的说来,Clark-Wilson模型考虑以下几点:
主体必须被识别和认证。
客体只能通过一组规定的程序进行操作。
主体只能执行一组规定的程序。
必须维护一个正确的审计日志。
系统必须被证明能够正确工作。
在该模型的形式化描述中,安全策略所控制的数据项称为约束数据项(CDIs),系统输入作为非约束数据项(UDIs)。UDIs到CDIs的转换是系统的一个关键部分,它不能光靠系统中的安全机制来控制。CDIs只能通过变换程序(TPs)来操作,状态的完整性通过完整性验证程序(IVPs)来检查。
安全特性是通过五条证明(certification,认证,【软】证明,确证;说明书)规则定义的,这些证明规则说明了为使安全策略符合应用需求而应该执行的检查。
IVPs必须确保当IVP运行时所有CDIs处于一种有效状态。
TPs必须被证明是有效的,即有效的CDIs必须总是被变换成有效的CDIs。每个TP被获准访问一组特定的CDIs。
访问规则必须满足任何责任分离要求。
所有TPs必须写入到一个只能添加的日志中。
任何一个接受UDI作为输入的TP,或者必须将UDI转换成CDI,或者必须拒绝该UDI,并且不进行任何变换。
四条实施规则描述了应执行安全策略的计算机系统其内部的安全机制,这些规则同BLP中的自主性访问控制有些类似。
系统必须维护和保护(Tpi:CDIa,CDIb,…)列表,该列表给出了TP获准访问的CDIs。
系统必须维护和保护(UserID,Tpi:CDIa,CDIb,…)列表,该列表规定了用户可以执行的TPs。
系统必须认证每一个请求执行某个TP的用户。
只有一个可以授予TP访问规则的主体才能修改列表中相应的表项,这个主体必须不能拥有在该TP上的执行权限。
最后提请注意,Clark-Wilson模型实际上是设计安全策略的一个框架和指导方针(“模型”),而不是一个特定安全策略的模型。
4.7 信息流模型在Bell-LaPadula模型中,信息可以通过隐蔽通道从一个高安全级别流到一个低安全级别。信息流模型考虑任何形式的信息流,而不光是由BLP模拟的通过访问操作的直接信息流。非正式地,如果我们能够通过观察y获得更多关于x的信息,状态迁移即引起从客体x到客体y的一个信息流。如果我们已经知道了x,那就没有信息能从x流出。你可以区分以下两种情况:
显式信息流:在赋值y:=x后查看y,可以获得x的值;
隐式信息流:在条件语句if x=0 then y:=1后查看y,可以获得有关x的一些信息,即使赋值y:=1没有被执行。比如,如果y=2,你知道x(0。
精确和定量的信息流定义可以用信息论的观点给出,从x到y的信息流用给定y的值后x的条件信息量平均值(条件熵)的变化来度量。信息流模型的组成部分是:
一个安全标签的格(L,(),
一组加了标签的客体,
安全策略:仅当c1( c2时允许从标签为c1的客体到标签为c2的客体的信息流;任何违反该规则的信息流是非法的。
如果没有非法的信息流,系统就被称为是安全的。这种模型的好处是它保护了所有类型的信息流,其缺点是设计安全的系统变得更加困难。比如,已经证明要检查在信息流模型中一个给定的系统是否安全,是一个不可判定的问题。
此外,我们必须区分信息流策略的静态和动态实施。在第一种情形下,系统(程序)被看成是一个静态客体。第二种情形考虑执行中的系统。我们可能发现有些信息流在理论上是可能的(因此应当在静态分析中检测),但却永远不会在执行过程中发生,因此静态分析趋向于生成限制性太强的系统。
不干扰模型是信息流模型的替代方案,它们提供了一种不同的形式(formalism,形式方法,形式论(拘泥形式,体系))来描述主体所知道的系统状态。如果s1的行为对s2的系统视图没有影响,那么主体s1不干扰主体s2。目前,信息流和不干扰模型只是研究领域,而不是设计安全系统的实用方法论基础。
进一步的阅读
安全模型常被看成是形式化的安全策略,这个定义假设我们知道安全策略意味着什么。安全策略可以满足一个企业的安全需求,或者描述为获得安全性必须采取的措施。关于术语安全策略的不同含义的讨论在[147]中给出,商业机构安全策略定义的最新进展在[143]中有适当的描述,风险分析的实际问题见[31]。
要调研安全模型方面的文章,请看[83]和[98],它们相隔了十年。Bell-LaPadula模型的最初报告最近在Journal of Computer Security[12]上重新发表了,在Bell-LaPadula模型中改变访问权限的策略框架在[97]中有讨论。很多研究论文在扩展BLP模型的范围而仍然实施其MLS策略方面作出了贡献。Clark和Wilson的最初论文是大力推荐的读物[32],[75]描述了一种用能力来实现Clark-Wilson模型的实现方法,[87]提出了一种可提供强制性的完整性控制并可用于实现Clark-Wilson模型的Biba模型的一种扩展。
HRU模型和信息流模型的可判定性特性的详细介绍,包括定义、证明和更多的理论,请参见[39]。对于不干扰模型,请参考Goguen和Meseguer的论文[58]。
练习题练习 4.1 用基本访问模式alter和observe描述(-property。
练习 4.2 写一篇短文表明你在Bell和McLean争论中的立场。
练习 4.3 Bell-LaPadula没有规定改变访问权限的策略,你会建议什么样的策略?
练习 4.4 你能将中国墙模型放入Bell-LaPadula框架吗?
练习 4.5 中国墙模型中的(-property应当只指当前的读访问还是指任何过去的读访问?
练习 4.6 Biba模型可以获得很多完整性策略,举出以下策略适合的应用领域的例子:
具有静态完整性标签的策略,
具有动态可变完整性标签的策略,
环特性练习 4.7 你能够用Bell-LaPadula和Biba同时建立机密性和完整性模型吗?你能在两个策略中使用相同的安全性标签吗?
练习 4.8 给出一个描述Clark-Wilson实施规则的形式化模型。
练习 4.9 为30年后解密的文档设计一个安全模型。
练习 4.10 在一个控制对病历和处方访问的医疗信息系统中:
医生可以读写病历和处方,
护士只能读写处方,但是不应当知道病历的内容。
你如何在格模型中得到这个策略,防止信息从病历流到处方?依你看哪一种安全模型最适合这种策略?
第五章 安全内核
你已经被分配了要在一个IT系统中实现“安全性”的任务。前两章已经给了你一个包括设计访问控制策略不同选项的菜单。然后你又研究了你的应用,并且决定了最合适的访问控制结构和安全模型。现在你怎样开始实现你选择的保护机制呢?在我们的分层系统模型框架中,你必须回答两个问题:
访问控制应该位于什么地方?
你的方案迫使你考虑附加的保护要求吗?
本章研究分层模型中最低两层的安全机制。
目标理解主张在系统的低层次上实现安全性的原因。
对于在系统的低层次上可以利用的安全机制有一个全面的了解。
引入身份和控制调用作为两个重要的安全原语。
弄清(理解;领会,see)怎样用安全模型来分析安全内核(security kernel)。
5.1 基本原理
有两个很好的理由将安全性置于系统的较低两层之一(图5.1)。如果攻击者从下面的层次进入,任何给定层上的安全机制将会受到损害。因此,为了评价系统的安全性,你必须证明你的安全机制不会被绕过。你的系统越复杂,这个证明就越困难。在系统的核心上,你有希望找到相当简单的能够经得起全面分析的结构。这个论点指向了将安全置于核心的第一个理由。
安全评价达到一个较高的可靠程度是可能的。
微处理器的设计就是确定哪组操作对于大多数用户是最有用的科学。正确的选择以及通用操作的有效实现决定了整体的性能。在实现安全性时你可以使用同样的方法,确定通用安全机制,并将它们置于系统的核心。这是将安全置于核心的第二个理由。
图5.1
图5.2
将安全机制置于系统的核心减小了由安全引起的性能开销。
本章以Motorola 68000和Intel 80386/486为例查看微处理器的安全特性,然后考虑Multics操作系统的引用监视器。它包括置于人-机标尺(图5.2)上机器这一端的安全机制。在本书的后面部分,我们将向上移动穿过各个层次,举例介绍由操作系统提供的安全机制(第六、七章),和由软件服务(中间件)提供的安全机制,象数据库管理系统(第十四章)。
5.2 操作系统完整性
计算机安全中有三个紧密相关易于混淆的基本概念,应当将它们区分开来。我们用橙皮书[112]中的词汇表作为我们定义的参考。
引用监视器:这是一个访问控制的概念,指一个对所有由主体对客体的访问进行仲裁的抽象机器。
安全内核:实现引用监视器概念的可信计算基的硬件、固件和软件元素。安全内核必须仲裁所有的访问,必须被保护不被修改,并可证明是正确的。
可信计算基(TCB,Trusted Computing Base):一个计算机系统中的全部保护机制(包括硬件、固件和软件(它们结合起来负责实施一项安全策略。一个TCB包含一个或多个部件,在一个产品或系统中实施统一的安全策略。TCB正确实施安全策略的能力完全依赖于TCB内部的机制,以及系统管理员对于安全策略相关参数(如用户许可)的正确输入。
因此,引用监视器是一个抽象的概念,安全内核是它的实现,而TCB包含了安全内核以及其他保护机制。图5.1最低两层中的安全机制大致对应了安全内核。保持一个操作系统的安全内核尽可能简单,对于安全的操作系统的设计与评估是至关重要的。有些文献将TCB和实现类似BLP策略的安全内核几乎视为同义,但是你从定义可以看到,这不是橙皮书作者的意图。
我们提出的支持将安全机制置于系统核心的所有论据将我们推向人-机标尺的机器一端,其结果是可想而知的。
由安全内核作出的访问控制决定和由应用作出的访问控制决定是分开的。
现在让我们概括地确定一下要包含在安全内核中的安全机制。假设你有一个操作系统能够实施你所有的访问控制策略,只要操作系统象我们所预期的那样运作,对资源的非授权访问是不可能的。当然,这正是对攻击者的暗示。为了避开你的保护机制,攻击者可能试图通过修改操作系统使安全控制失去能力。无疑你现在面临的是一个完整性问题,即使你一开始关心的是机密性。操作系统不仅是访问请求的裁决者,它本身也是一个访问控制的客体。新的安全策略是:
规则 用户一定不能修改操作系统。
这是一个通用的安全策略,应该得到坚强和有效的支持。更为困难的是,你必须解决以下两个相互抵触的要求:
用户应能使用(调用)操作系统。
用户不能滥用操作系统。
通常用于实现这些目标的两个重要概念是身份信息和控制调用(也称为有限特权)。这些概念可被用于计算系统的任一层次上,可以是应用软件、操作系统或硬件。但是再次强调,如果攻击者获得对较低层次的访问,这些机制可能会失去作用。
5.2.1 操作模式
操作系统能够保护自己不受用户侵害的第一个必备条件是能够区分“代表”操作系统的计算和“代表”用户的计算。身份标志可用来表示这个意思,允许系统工作在不同的模式。以下两个例子在处理器级上解释了这一点。
Motorola 68000:一个身份比特使得可以区分用户模式和超级用户(系统)模式。
Intel 80386:两个身份比特导致四种模式。
Unix操作系统能够区分超级用户(根)模式和用户模式。
为什么这些模式有用呢?比如,为阻止用户直接写内存和破坏逻辑文件结构,操作系统可以仅在处理器工作于超级用户模式时准许对存储位置进行写访问。
5.2.2 控制调用
继续我们的例子,用户想执行一个要求超级用户模式的操作,如写一个存储位置。为处理这个请求,处理器必须转换模式,但是这种转换应当如何执行呢?简单地将身份比特改到超级用户模式会把与该模式相关联的所有特权都赋予用户,但对用户实际做些什么却没有任何控制。因此,理想的做法是系统在超级用户模式只执行一组预先定义的操作,而在将控制交回给用户前返回用户模式。我们称这个过程为控制调用。
5.3 硬件安全特性
在我们的模型中,硬件是IT系统的最低层,硬件也是计算机安全可与物理安全相联系的地方,因此,硬件级的安全机制是我们研究的自然起点。我们假设读者已经熟悉了计算机体系结构的基本概念,如必要的话,这些背景知识可从象[38,66]的教科书得到。
5.3.1 计算机体系结构的简单概述
就我们的目的而言,用图5.3给出简单的计算机示意性描述就可以了。计算机由一个中央处理单元(CPU)、存储器和连接CPU和存储器的一条总线构成。在现实世界中,所有这三个实体都有非常精细的结构。
图5.3
中央处理单元
核心的CPU部件是:
算术逻辑单元(ALU):执行用机器语言给出的指令;指令执行后可能会在状态寄存器中置位。
寄存器:有通用寄存器和专用寄存器。
重要的专用寄存器是:
程序计数器:指向包含了下一条要执行指令的内存位置;
栈指针:指向系统堆栈的栈顶;
状态寄存器:允许CPU保存重要的状态信息。
系统堆栈是内存中一块特别指定的部分,堆栈可以通过将数据压入栈顶或从栈顶弹出数据来进行访问。为了在不同的进程间切换,CPU执行上下文切换操作,并在将控制交给新进程前将当前进程的状态,如程序计数器、状态寄存器等保存在堆栈中。
已经警告过你抽象的危险性,堆栈是另一个“万一”的例子。在讨论抽象时,可以合理地假设堆栈大小是无限的,但是一个具体的实现肯定会为堆栈分配固定大小的内存区。如果允许堆栈超出它的最大尺寸,安全问题就可能发生,实际上已经发生过,并且今后还会发生。
存储结构
在以下简短的综述中,我们对不同存储结构的安全特性尤其感兴趣。我们有:
RAM(random access memory):这是读/写存储器;你必须考虑完整性和机密性问题。
ROM(read-only memory):你只需要考虑机密性问题;ROM可能是存储(部分)操作系统的好地方。
EPROM(erasable and programmable read-only memory):可用于存储部分操作系统或加密密钥;技术上更复杂的攻击可能会对安全造成威胁。
WROM(write-once memory):与这种存储结构相伴随的一种机制允许你一次性固化存储内容;在硬件中这可以通过熔断写线上的熔丝来做到,但是你还可能遇到“逻辑熔丝”;WROM可能是存储密钥的一个好地方;只写磁盘正被用于记录审计踪迹。
进一步还可以区分易失性存储器和非易失性(永久性)存储器。易失性存储器当断电时会丢失内容,在物理上这个过程既不是瞬间的也不是完全的。如果断电后立即接上电源,老的数据还可能保留在存储器中。即使电源被关闭了一段时间,老的存储内容仍然有可能通过特殊的电子技术被恢复。为了抵抗这些攻击,存储器必须用合适的取决于存储介质的比特模式重复地改写[113]。
永久性存储器在断电时仍然保持其内容。如果敏感数据(如加密密钥)存放在永久存储器中,并且攻击者能够绕过CPU直接访问存储器,那么必须实现象密码保护或物理保护等进一步的措施。比如将一个光传感器放置在一个防篡改模块中,以检测某些操作企图并触发对模块中存储内容的删除。物理保护本身就是一个研究课题,它不在本书讨论的范围之内。我们将注意力集中在用户只能通过CPU访问内存的情形,我们研究CPU如何能实现机密性和完整性。比如,如何能够防止计算机病毒用一个受感染的操作系统版本改写一个干净的操作系统版本。
有一点很重要,就是要提醒自己图5.3中的“存储器”是另一个抽象。逻辑上,存储器可能由主存储器、高速缓冲存储器和缓冲器等组成,即使是备份介质也可以包括在这里。因此,一个数据客体可能同时存在于该存储层次结构的多个位置上,除了在主存储器中有一个永久性的拷贝外,还可能有临时性的拷贝。通常,这些临时拷贝的位置和生存期不在用户的控制之下,如果这些临时拷贝之一被保存在一个未受保护的存储区域,对一个数据客体的安全控制就可以被绕过。
5.3.2 进程和线程
进程就是一个正在执行的程序,因此,对于操作系统来说进程是一个重要的控制单元,当然对于安全来说也是如此。简单地说,一个进程由以下几个部分组成:
可执行代码,
数据,
执行环境,如某些相关的CPU寄存器的内容。
进程工作在它自己的地址空间,并且只能通过操作系统提供的原语同其他进程通信。进程间的这种逻辑分离对于安全来说是一种有用的基础。但另一方面,进程间的上下文转换是一种开销很大的操作,因为操作系统必须将全部的执行环境保存在堆栈中。
线程是一个进程内部的执行流。由于线程间共享一个地址空间,它们避免了完全的上下文转换的开销,但是也逃避了可能的安全机制的控制。
5.3.3 控制调用—中断处理器能够处理由程序错误、用户请求、硬件故障等引起的执行中断,这种处理机制被称为异常、中断、陷阱等不同的名称。不同的术语可能指不同类型的事件,但仍然有相竞争的分类法,可参见[66]、5.6节作进一步了解。
我们将用“陷阱”作为一般术语,并且解释怎样将陷阱用于安全目的。陷阱是CPU的一种特殊输入,它包括中断矢量表中一个称为中断矢量的地址。中断矢量表给出了一些程序的位置,这些程序用于处理陷阱中规定的事件,称为中断句柄。当一个陷阱发生时,系统在堆栈中保存当前状态,然后执行中断句柄(图5.4),用这种方式将控制从用户程序那儿接管过来。中断句柄必须保证在将控制返回给用户程序前,将系统恢复到一个正确的状态,比如清除超级用户状态位。
图5.4
当处理器正在处理当前中断时,可能会有新的中断到来,这时处理器可能必须中断当前的中断句柄。这种情形如果处理得不正确,可能会导致安全缺陷。一个典型的例子就是这样一个系统,用户可以通过键入CTRL-C来中断程序的执行,使得处理器带着当前进程的状态位迅速返回操作系统。于是,用户通过中断一个操作系统调用的执行就可以进入管理员模式,因此,在执行程序前建立中断表使得中断能以一种适当的方式被处理是非常重要的。
从以上讨论可以清楚地看出,中断表是一个特别令人感兴趣的攻击点,必须受到充分的保护。同样地,重定向指针是危及操作系统完整性的一种非常有效的方法,我们在分析计算机病毒时还会再一次遇到这个问题。
5.3.4 Motorola 68000上的保护
Motorola 68000是一个16位处理器,它有一个16位的状态寄存器,其高位部分(系统字节)包含了以下与安全控制相关的位。
T 跟踪位,在位置15上
S 超级用户位,在位置13上
I2I1I0 中断级别号,在位置8到10上
状态寄存器的低位字节是条件代码寄存器(CCR)(图5.5)。68000用超级用户位S区分用户模式和超级用户(系统)模式。复位后68000总是以超级用户模式引导,超级用户模式允许访问状态寄存器的系统字节。一旦S位被置成0且当前处于用户模式,那么只有中断和错误异常才能将S位切换回1,并以超级用户模式运行。操作系统调用是通过TRAP #n指令实现的,并能以超级用户模式运行和访问超级用户存储器,操作数#n指示了32和47之间的一个异常矢量。退出时,操作系统调用通过RTE指令切换回用户模式。
图5.5
68000有7个中断优先级,当前的中断级别保存在状态寄存器的I2I1I0位中。当68000正在处理一个中断而另一个具有较高优先级的中断到来时,新的中断得到优先处理,第一个中断被中断。较低优先级的中断则被忽略。为保护一个中断句柄被进一步中断,我们必须通过在状态寄存器中设置中断级别号来屏蔽中断,因此中断级别7屏蔽所有其他的中断。
处理器使用内存映像I/O,即将输入/输出端口地址看成是内存地址空间的一部分,因此输入/输出操作和内存访问可用统一的方式处理。处理器有64根连线(管脚),其中的三根管脚被指定为功能代码输出FC2、FC1和FC0,这些功能代码向地址译码器指示处理器的状态,地址译码器可以使用这些代码在用户存储器和超级用户存储器之间或者在数据和程序之间进行选择(图5.6)。
图5.6
区分数据和程序的能力是一种非常有用的安全特性,它为保护程序不被修改提供了基础。
从较为抽象的观点来看,存储器已经被分成了不同的区域,于是访问控制就可以指一个数据客体或一个程序来自的位置。
现在你有了一个在微观世界中基于位置的访问控制的例子,在分布式系统或计算机网络中,你经常需要微观世界中基于位置的访问控制。
5.3.5 Intel 80386/80486上的保护
Intel 80386/80486是32位的微处理器,80386/80486上的保护模式支持多任务操作系统的完整性和机密性要求。
Intel 80386/80486在状态寄存器中有一个2比特的域,定义了四种特权级别(保护环),特权级别只能被运行在级别0上的单指令(POPF)修改。软件可以被指派到如下各个级别上:
操作系统核心操作系统的其余部分
I/O驱动程序等应用软件不是所有的操作系统都使用全部四个级别,比如Unix只使用级别0和3。80386/80486实现了以下安全策略。
规则 程序只能访问位于自己环内或外环中的客体。程序只能在自己的环内调用子例程。
80386/80486保存系统客体的信息,如存储器段、访问控制表或描述符中的门。描述符保存在描述符表中,通过选择器进行访问,一个客体的特权级别保存在它的描述符的DPL域中。选择器是一个16位的域,包含一个指向描述符表中客体入口的索引以及一个被请求的特权级别(RLP)域(图5.7),RLP域的使用后面马上会解释。只有操作系统能够访问选择器。
图5.7
包含关于主体(即进程)信息的系统客体当然也有描述符和选择器(符)。当一个主体请求访问一个客体时,相关的选择器被装入专用的段寄存器中。比如,当前进程的特权级别,称为当前特权级别(CPL),就是保存在代码段(CS)寄存器中的选择器的特权级别。
毫不奇怪,我们又一次面对了这样的问题,就是必须对那些要求较高特权的操作进行访问管理。假设环3中的一个应用程序需要环1中一个操作系统例程的服务,在80386/486中这个问题是通过使用门来解决的。门是一个指向某个程序(在某个代码段中)的系统客体,这里门具有与它所指向的代码不同的特权级别。门允许对内环中的程序进行只执行访问,但仍限制向外的调用。
为使程序(过程,procedure)使用门,门必须和程序位于同一个环内。当通过门调用一个子例程时,当前特权级别变为门正指向的代码的级别。当从子例程返回时,特权级别恢复到调用程序的特权级别。子例程调用也在堆栈中保存指示调用程序状态的信息或返回地址。为了确定堆栈的合适的特权级别,记住调用程序不能写入内环。但是由于安全的原因,将堆栈留在外环也是不能解决问题的,因为它使得返回地址完全没有保护。因此,一部分堆栈(大小在门的描述符中规定)要拷贝到一个更有特权的堆栈段中。
通过允许外环程序调用内环程序,我们制造了一个潜在的安全漏洞,外环程序可以请求内环程序将位于内环上的一个客体拷贝到外环上。迄今为止我们给出的任何安全机制都不能防止这种做法,事实上它也没有违反我们规定的安全策略。因此,我们可能希望扩展原来的安全策略,使其不仅考虑到当前的特权级别,也考虑到调用程序的级别。在80386/486中,可以使用选择器中的RLP域和调整被请求的特权级别(ARPL)指令支持这种策略。ARPL指令将所有选择器的RLP域改为调用程序的CPL,然后系统可以比较RPL(在选择器中)和客体的DPL(在描述符中),如果它们不同的话,拒绝完成被请求的操作(图5.8)。
图5.8
5.4 引用监视器
操作系统管理对数据和资源的访问,通常不涉及对用户数据的解释。多任务操作系统交替执行属于不同用户的进程,因此操作系统不仅必须保护它自己的完整性,还必须防止用户有意或无意地访问其他用户的数据。操作系统本身的完整性通过隔离用户空间和操作系统空间来保护,用户的逻辑隔离防止用户间有意和无意的干扰。隔离可以发生在两个层次上:
文件管理 ,处理逻辑存储客体,和
存储管理,处理物理存储客体。
对于安全来说,这种区分是非常重要的。为了说明这一点,考虑两种最主要的组织存储方式,分段和分页。分段是将数据划分成逻辑单元,每个段有一个唯一的名字,段内的数据项通过给出段名和适当的段内偏移量来寻址。操作系统维护一个段表,其中包括段名以及各个段在存储器中的真实地址。Multics操作系统用分段来进行逻辑访问控制。
分段是逻辑单元的一种划分,它是实施安全策略的良好基础。另一方面,段具有可变长度,这使得存储管理较为困难。
分页是将存储器划分成相同大小的页,同样地址由两部分组成,页号和页内偏移。
分页很流行,因为它允许高效的存储管理。Multics的段实际上是分页的。另一方面,
分页对于访问控制来说不是一个好基础,因为页不是逻辑单元。因此一个页可能包含要求不同保护的客体。
更糟的是,分页可能会打开一个隐蔽通道。逻辑客体可以跨越页边界存储,当这样的客体被访问时,操作系统在某个时候会要求一个新页,这时产生缺页。如果缺页可以被观察到,就象大多数操作系统中那样,那么用户就获得了比正确的访问请求结果更多的信息。
作为例子,考虑一个口令方案。用户输入一个口令,该口令被逐个字符地扫描,并同保存在存储器中的一个参考口令进行比较,当发现不匹配时访问被拒绝。如果一个口令跨越页边界存放,那么攻击者可从观察到缺页推断出第一页上的口令片段已被正确猜测出来。如果攻击者可以控制将口令存放在页的什么地方,口令猜测就变得相当容易了。
5.4.1 存储器保护
当你希望操作系统保护自己的完整性,并且将每个进程限制在分开的地址空间,那么你的任务之一就是控制对存储器中数据客体的访问。这样一个数据客体在物理上被表示成存放在某个存储位置的比特集合,访问一个逻辑客体最终被转换成机器语言级上的访问操作。在这一层上,控制对存储位置的访问可以有三种选择方法:
操作系统修改从用户进程收到的地址;
操作系统利用从用户进程收到的相对地址构造有效地址;
操作系统检查从用户进程收到的地址是否在给定的界限内。
地址沙箱法是第一种方法的一个例子。一个地址由一个段标识苻和一个偏移量组成,当操作系统收到一个地址时,它设置正确的段标识。图5.9显示如何用两个寄存器操作来完成地址修改。首先,用地址与mask_1的按位与(AND)操作清除段标识,然后用与mask_2的按位或(OR)操作将段标识设置成希望的值,SEG-ID。
图5.9
在第二种方法中,编址方式的巧妙使用可避免进程进入禁止的存储区域。如果你需要更多关于编址方式的背景知识,请查阅有关操作系统或计算机体系结构的书[38,66,100]。在各种各样的编址方式中,相对编址特别引起我们的注意:地址是用相对于某个给定的基地址的偏移量来指明的。比如,在Motorola 68000中相对编址是通过寄存器间接置换编址方式支持的。汇编语言指令
MOVE.L 8(A1),D3
将常数8加到寄存器A1的内容上获得一个存储器地址,将存放在该存储地址上的长字(16位)放入寄存器D3。
相对编址允许位置无关的编码,这样程序可以存放在存储器的任何地方,给了存储管理程序很大的灵活性,也方便栅栏寄存器的使用。栅栏寄存器包含了分配给操作系统的存储区域的边界地址,用户程序中的地址被解释为相对地址(偏移量,置换),操作系统使用关于栅栏寄存器的相对编址(基础寄存器编址(寄存器基址寻址))来计算有效地址(见图5.10)。用这种方式,只有操作系统空间以外的位置可被用户程序访问。类似的方法可被操作系统用来隔离分配给不同用户的存储区域。
图5.10
这种方法可以通过用基础寄存器和边界寄存器来定义分配给进程的存储空间而得到进一步的改进,我们甚至可以再进一步,分别为用户的程序空间和数据空间引入基础和边界(基址和界限)寄存器。为了正确使用这种工具,处理器必须能够检测一个给定的存储位置存放的是数据还是程序代码,然而大多数的指令集没有办法使指令检查其操作数的类型。如果没有这样的方法,类型信息可以通过在程序中指出不同存储访问操作必须使用的地址寄存器来提供,这种方法要求正确的编程规则。
另一种方法,在一个标记体系统结构中,每个数据项有一个说明其类型的标签(tag),执行前CPU可以从保存在存储器中的值直接检测出任何的类型违背。此标签也可用于实施安全策略。历史上,标记体系结构在理论描述中非常流行,但很少用于实际的实现。标记体系结构为数很少的几个例子包括Burroughs B6500-7500系统和IBM System/38[17]。(对计算历史感兴趣的读者,1945年冯?诺伊曼在他的First Draft of a Report on the EDVAC中描述了一个标记体系结构[154])。
图5.11给出了一个标记体系结构,它指示存储客体的类型,如整数(INT)、位串(STR)或操作数(OP)。标签也可被用来指示在一个存储位置上可以执行哪一种访问操作,如读、写或执行。
图5.11
5.4.2 Multics操作系统
在历史上有重要影响的Multics操作系统的例子能说明安全核心(内核,kernel)如何实施访问控制。Multics是一个雄心勃勃的研究计划的产物,该计划旨在开发安全的、可靠的等等多用户操作系统[13,119]。安全方面的许多研究,象BLP,都是由Multics计划引发的。[119]的第四章给出了Multics保护机制的一个概述。由于它范围广泛的目标和安全需求(?),该计划的一些成员觉得它太笨重了,于是建立了更简单的操作系统,就是Unix。就商业成功而言,这两个系统的历史就是可用性与安全性之间相平衡的一种表现。
5.4.3 BLP的Multics解释
研究Multics给了我们一个机会,看看安全模型是如何用于一个安全的操作系统的设计的,本例中是Bell-LaPadula模型。作为访问控制的一个抽象模型,BLP非常适合于捕捉操作系统的安全需求,事实上它正是为此目的而开发的。BLP中关于安全的归纳定义使它比较容易建立一个安全的系统,我们只需正确地定义状态迁移来保证安全性。为了证明Multics是安全的,我们必须找到一种与BLP相一致的Multics描述,我们将基本上按照[13]中的介绍来说明BLP的安全概念是如何映射到Multics的。
Multics中的主体是进程,每个主体有一个包含进程信息的描述符段,其中包括进程当前访问的客体的信息。对于每一个这样的客体,在主体的描述符段中有一个段描述符字(SDW)。SDW的格式在图5.12中给出,包括客体名、指向客体的指针以及读、执行和写访问的指示器标志,这些指示器涉及3.3.2所规定的访问属性。主体的安全级别保存在一个进程级别表和一个当前级别表中,活跃段表记录所有运行态(活跃的,active)的进程,只有运行态的进程能够访问客体。
图5.12
Multics中的客体是存储段、I/O设备等,客体按层次组织在一棵目录树中。目录也是段,有关一个客体的信息,像它的安全级别或访问控制列表(ACL),保存在客体的父目录中。因此,改变一个客体的访问控制参数以及建立或删除一个客体,需要对父目录写或者添加访问权限。
为访问一个客体,进程必须遍历从根目录到目标客体的目录树,如果路径中任何一个目录对于进程是不可访问的,那么目标客体也不可访问。换句话说,一个保密目录中的非保密客体不能被一般性用户阅读。因此,将客体放入具有较高安全级别的目录是没有意义的,我们总是要求客体的安全级别控制其父目录的安全级别,这个特性称为兼容性。你在现代操作系统(如Unix)中必须处理同样的问题,如果你想使你的文件对于其他用户是可访问的,你也必须完全获得对目录路径的访问控制设置。
现在我们有了全部所需的信息,可以用Multics系统表和描述符段中的数据来确定BLP状态集的组成(component)。
当前访问b:保存在运行态进程的描述符段的SDW中;运行态进程可以在活跃段表中找到。
访问控制矩阵M:用ACL表示;对于每个客体,ACL保存在它的父目录中;每个ACL表项列出一个进程以及进程对该客体的访问权限。
级别函数f:主体的安全级别保存在专门的进程安全级别表中,即进程级别表和当前级别表;客体的安全级别保存在其父目录中。
在3.3.2中,我们已经介绍了Multics对数据段和目录段的访问属性,也解释了这些访问属性如何对应Bell-LaPadula模型的访问权限。作为提示,我们在图5.13中重新叙述了对数据段的访问属性。
图5.13
现在我们用进程和数据段的安全级别以及SDW中的指示器重新描述BLP的安全特性。比如星特性写成如下形式,对于一个运行态进程的描述符段中的任何SDW,进程的当前级别:
控制段级别,如果读或执行指示器打开而写指示器关闭;
被段级别控制,如果读指示器关闭而写指示器打开;
等于段级别,如果读指示器打开而写指示器也打开。
图5.14说明如何验证与星特性的一致性。当前进程的安全级别Lc保存在当前级别表中,描述符段基础寄存器(DSBR)的内容指向当前进程的描述符段的头部,这个描述符段恰好包含了一个访问属性为只写的客体的SDW,因此,写指示器打开而读指示器关闭。客体的安全级别Lo从其父目录中得到,并与Ls比较来证明Ls(Lo成立。
图5.14
5.4.4 核心原语
最后必须规定一组核心原语。这些核心原语是Multics核心抽象模型中的状态迁移,我们必须证明它们保持BLP的安全策略。这样,基本安全定理的前提条件成立,我们就证明了Multics的“安全性”。当然,这不是安全性的一个完整证明,你还必须证明核心原语的实现以及最后它们在一个给定硬件平台上的执行符合它们的规范。
我们选择get-read来详细地看一个核心原语。get-read原语用process-id和segment-id作为参数,操作系统必须检查:
segment-id的ACL(保存在段的父目录中)是否列出了带有读允许的process-id;
process-id的安全级别是否控制segment-id的安全级别;
process-id是否是一个信任的主体,或者process-id的当前安全级别是否控制segment-id的安全级别。
如果所有三个条件都满足,访问被允许。如果没有segment-id的SDW存在,一个对应的SDW被添加到process-id的描述符段中,且读指示器打开。如果segment-id的一个SDW已经存在于process-id的描述符段中,则打开SDW中的读指示器。如果以上三个条件中任何一个不满足,访问被拒绝。
以下是另外一些已经提出来要在Multics核心中实现的原语:
release-read 进程释放一个客体;对应SDW中的读标志被清除;如果此后没有指示器打开,SDW被从描述符段中删除。
give-read 进程向另一个进程授予读访问权限(自主性访问控制)。
rescind-read 进程将赋予另一个进程的读权限收回。
create-object 进程创建一个客体;操作系统必须保证对客体目录段的写访问是允许的,并且段的安全级别控制进程的安全级别。
delete-object 当删除一个客体时,必须执行与create-object中一样的检查。
Change-subject-current-security-level 操作系统必须保证变化没有造成安全违背;这个核心原语以及原语
change-object-security-level不打算用于实现(稳定性)。
理想的情况是,开发处理器时使它的指令集与操作系统的核心原语相吻合。相反地,核心原语可以设计成与现有处理器提供的支持相匹配。
进一步的阅读
主要的访问控制范例应归功于Lampson[82]。[39]全面论述了针对第一个多用户操作系统而进行的计算机安全研究的成果。[84]汇集了对保护技术的进一步研究。[56]对于在设计安全的多用户操作系统中使用的技术作了极好的说明,这本书包含了许多指向该领域技术报告的有用链接。在[131]中可以找到对Multics安全性的评论,特别是对安全管理的复杂性以及对设计的正确性进行评估的复杂性评论。
Motorola 68000微处理器在[33]中作为例子有详细的解释。对Intel 80386/486上的保护机制的详细描述见[111],较简短的介绍见[49]。用Intel 80x86处理器构造安全核心在[141]中有讨论。
地址沙箱法和相关技术在[155]中有描述。需要存储管理方面的实用资料,请查看QNX网页:http://www.qnx.com/literature/nto_sysarch/nto_sysarch.html。有关Multics的信息可以在http://www.lilli.com/multics.html上找到。
安全计算机系统的早期开发历史在[93]中有比较。最近有人针对TCB(安全核心)在安全系统的构造中是否仍然是一个适当的范例提出了疑问,这场争论中相反的两种意见可以在[21](反对)和[11](赞成)中找到。
练习题练习5.1 在Motorola 68000中,如果状态寄存器中的跟踪位置位,每条指令执行后都会产生一个异常(中断),允许程序员运行一个异常处理例程(中断句柄),比如用于调试程序。设置跟踪位隐含的安全问题是什么?为什么在处理异常时跟踪位必须清除?
练习5.2 寄生病毒感染可执行程序(见8.8)。区分程序和数据的能力怎样才能有助于构造一道抵御这类病毒的防线?
练习5.3 智能卡上的微处理器通常将全部的卡操作系统置于ROM中,现在有一种趋势,就是部分的操作系统可以下载到EPROM中。将操作系统放在ROM中的优点和缺点是什么?将部分操作系统移入EPROM隐含的安全问题是什么?
练习5.4 证明5.4.3中星特性的重新描述是正确的。为什么我们只要考虑提到的三种情形?
练习5.5 应当给多级安全操作系统的根目录分配什么样的标签?
练习5.6 考虑多级安全操作系统中的一个目录,保存文件的安全级别有三种可供选择的方法:
将文件的安全级别和文件名一起保存在目录中。
将文件的安全级别和文件本身存放在一起,目录仅包含文件名。
将目录划分成若干区,每个安全级别对应一个区,文件名放入与它们的安全级别相对应的区中。
分析每一种方法隐含的安全问题和可用性问题。
练习5.7 没有安全核心你能获得安全性吗?讨论拥有一个象TCB那样的安全核心的优点与缺点。
练习5.8 寻找一些例子说明以下三条原则如何应用到构造安全的系统上:责任分开,抽象数据类型和原子操作。(为保持安全性,原子操作必须被全部执行。如果操作被中断,系统将终止在一种不安全的状态。)
练习5.9 当你注册到一个系统上后,你启动一个进程以你的身份运行。以你的身份运行的进程在你退出系统后能够继续运行吗?在你正在使用的操作系统上研究这个问题。
Authenticity 可靠性
In data security,controls that either prevent or detect the tampering and/or accidental destruction of data,If the data to be protected is already encrypted,then authenticity requires that a cryptanalyst would not be able to substitute a false ciphertext without detection.
数据安全技术中的一种控制功能,用以防止或能检测出故意和/或意外的数据破环。若待保护的数据已被译成密码,则可靠性要求密码分析员不能代之以伪造的密码电文而不被发现。参阅accidental destruction,digital signature,masquerading。
Accountability 责任
In computer security,the quality or state that enables violations or attempted violations of ADP system security to be traced to individuals who may then be held responsible.
计算机安全学中,指可以追查对自动数据处理系统的侵害或试图侵害的责任者的性质或状态。
Dependency 相关性
The condition in which the accuracy of results from one program depend upon the accuracy of results from another; for example,if the first program updates a file and the second uses it.
一种程序所得结果的精度取决于另一个程序所得结果精度的条件。例如,若第一个程序修改了一个文件,而第二个程序要用此文件。
Reliability 可靠性;[可靠度]
The ability of a functional unit to perform a required function under stated conditions for a stated period of time.
操作[功能]部件在规定条件下和规定时间内完成规定操作[功能]的能力。
在对计算机安全进行有针对性的讨论之前,我们必须先定义这个研究领域,必须有一些通用的准则来帮助我们将今天可能遇到的大量概念和安全机制进行分类整理。因此,我们的第一项任务就是要寻找“计算机安全”的定义。为避免孤立地讨论一个个单独的安全系统,我们将提出一组通用的工程性原则,这组原则可用于指导安全的信息处理系统的设计。我们鼓励大家在阅读本书时,时刻留心书中所介绍的各类安全系统中的这些原则。
目标提出计算机安全的一种定义,介绍机密性、完整性和可用性。
解释计算机安全最根本的一个两难处境。
简述在构造安全系统时通常必须做出的一些设计决定。
指出计算机安全机制必须依赖于有效的物理或机构保护措施。
1.1 定义按照一种良好的学术传统,我们将通过定义我们的研究目标来开始我们的研究,至少我们会努力这么做。计算机安全研究在计算机系统中维护安全所使用的技术。我们不打算去区分计算机系统(不确切地说,内有处理器和存储器的装置)和信息技术(IT)系统(不确切地说,紧密耦合的计算机系统网络),因为随着技术的不断飞速发展,现代的计算机已经是一种由各部件紧密耦合而成的网络了,曾经是应用程序的软件也可能成为操作系统的一部分。Web浏览器就是当前这种趋势的一个鲜明例子,在你机器上运行的软件不需要存储在你的机器上,它可以来自于一个本地服务器,或者甚至来自于Internet上的一个web服务器。因此,你可以将“计算机安全”和“IT安全”作为同义词来使用,而不会引起太多的误解。
乍一看,计算机安全好象是一个相当显而易见的概念。然而不幸的是,安全属于这样一类概念,当你试图讲清楚它的确切含义的时候,它似乎离显而易见越来越远了。在起草计算机安全的定义以及随后对这些定义进行修正方面已经做了大量的努力。但是这些文档的编写者几乎无一例外地都被批评为眼光过于狭窄,或过多地介入了从严格意义上来说不属于计算机安全的一些计算机科学领域。
1.1.1 安全
安全是关于财产的保护。这个定义意味着你必须知道你的财产和它们的价值。这种带有普遍性的看法当然也适用于计算机安全,因此风险分析也是综合性的信息安全策略的一部分。但是,这个话题不在本书的范围之内,本书的重点在于保护措施。对保护措施的一种大致的分类如下:
预防:采取措施防止你的财产遭到破坏。
发现:采取措施使你能够发觉什么时候财产被破坏了,它是怎么被破坏的,以及是谁造成的破坏。
反应:采取措施使你能够重新获得财产,或者使财产从破坏中恢复。
为了说明这一点,考虑你家中贵重物品的保护。
预防:门窗上的锁,使盗贼难以闯入你家;保护家产的墙,或者在中世纪可以增加另一层保护,就是城堡的护城河。
发现:当某样东西不在那儿了,你将会发现它被偷了;当入室事件发生时报警器响了(希望如此);闭路电视提供的信息可以确定入侵者。
反应:你可以打电话报警;你可能决定替换被偷的物品;警察可能追回被偷的物品并送还给你。
来自物理世界的例子有助于解释计算机安全的原则,然而,将物理安全与计算机安全进行类比并不总是可能的或是可取的,事实上,有些术语应用于信息技术环境时很容易引起误解。举一个与我们讨论的领域有密切关系的例子,考虑使用信用卡号码在Internet上购物。一个骗子可能使用你的信用卡号码购物,而费用从你卡上扣除。你怎么来保护你自己呢?
预防:下订单时使用密码;依靠贸易商行在接受信用卡购物订单前对购物者进行某些检查;不要在Internet上使用你的卡号。
发现: 一项你没有授权的交易出现在你的信用卡帐单上。
反应:你可以申请一个新的卡号;欺诈交易的损失可以由持卡人、骗子购物的商行或者信用卡的发行商承担。
在这个例子中,骗子“窃取”了你的卡号,但你依然持有这张卡,这和你的卡被盗的情况是不同的。因此在某些法律框架下,比如在英国,骗子不能被起诉为盗窃你的信用卡卡号。必须制定新的律法来解决这个新的问题。
考虑保护机密信息的选择,我们继续关于保护问题的讨论。有可能仅当秘密被揭露时你才发现已经泄密了,而在某些情况下,损失是无法挽回的。你的竞争对手可能已经得到了你耗费数年功夫完成的产品设计,在你之前占领了市场,并获取了全部的利润,而你却歇业了。在这种情形下,预防是唯一的选择。这也解释了为什么历来计算机安全相当重视对机密信息泄露的预防。
1.1.2 计算机安全
为了首先获得计算机安全的概念,我们分析一下信息财富是如何受到损害的。最常给出的定义包括以下三个方面:
机密性(Confidentiality):防止未经授权的信息透露。
完整性(Integrity):防止未经授权的信息修改。
可用性(Availability):防止未经授权的信息或资源截留。
读者可以立即就这些话题的优先顺序展开讨论,并且给出一个重新排序的例子。或者读者可以论证说这个列表不完整——因为列表永远不会完整——并再增加一些内容,比如读者关心通信,可以增加真实性(可靠性,authenticity),若感兴趣电子商务类应用,则可以增加可审计性(accountability)。
即使在这样一般的层次上,你仍会发现对于某些安全方面的精确定义有不同意见。因此,我们通常会给出定义的出处,这样定义的背景就比较清楚了。象美国可信赖计算机系统评价标准(橙皮书[112])、欧洲信息技术安全评价标准(ITSEC[117])和加拿大可信赖计算机产品评价标准(CTCPEC[150])等,就是安全评价标准(第9章)的主要来源。上面的定义就出自ITSEC。
1.1.3 机密性
历史上,安全和保密是紧密联系在一起的。即使在今天,许多人仍然觉得计算机安全的主要目的是阻止未授权的用户阅读敏感信息。更一般地说,未授权的用户不应该获悉敏感信息。机密性(隐私,机密)即要解决计算机安全的这个方面的问题。术语“隐私”(privacy)和“机密”(secrecy)有时候用来区分个人数据的保护(隐私)和机构数据的保护(机密)。机密性概念已经被很好地定义了,并且计算机安全中的研究通常集中在这个题目上,因为最起码它提出了与物理安全不相类似的新问题。有时候安全性(security)和机密性(confidentiality)甚至被用作同义词。
在一个纸质文档的世界中,控制对一个文档的访问是很简单的,你只要列出那些允许阅读这个文档的人就可以了。然而稍微有些不同的是,计算机安全为实现机密性还必须控制写操作。读者将在4.2节看到更多有关这方面的内容。
1.1.4 完整性
很难给出一个简洁的完整性定义。一般来说,完整性是要确保每个事物保持它该有的状态。(很抱歉给出这样一个毫无帮助的但却反映了现实的定义。)在计算机安全的范围内,我们可能会满足于这样一个定义,即完整性研究如何防范未授权的写操作。按照这种解释,完整性是双重机密性,而我们可以指望用类似的技术来同时达到两个目的。
然而,更进一步的问题象“被授权做某人做的事”和“遵循正确的程序”也已经被包含进完整性术语中。Clark和Wilson在他们的颇有影响力的论文[32]中采用了这个方法,该论文声称完整性就是这样一种特性:
完整性 系统中的任何用户,即使被授权,也不允许以一种会使得公司的资产或帐目记录丢失或被讹误的方式来修改数据项。
如果将完整性与防止所有未授权的行为等同起来,则机密性就成为了完整性的一部分。
迄今为止,我们是通过指出必须控制的用户行为来确定安全性问题。从系统的观点来看,在定义完整性时最好把注意力集中在系统状态上。橙皮书中关于数据完整性的定义正好就是这种类型的:
数据完整性 当被计算机处理的数据与源文件中的数据一样,且没有受到意外的或恶意的修改或破坏时所呈现的状态。
在这里,完整性是外部一致性的同义词。存储在计算机系统中的数据应当正确地反映计算机系统外的某些事实。非常理想的当然是存储在任何计算机系统中的信息都正确地反映事实,然而,仅靠计算机系统内部的机制来保证这个特性是不可能的。
更为混乱的是,信息安全的其他领域有它们自己关于完整性的概念。比如,在通信安全中,完整性是指:
对因蓄意操作或随机的传输错误而引起的传输数据的修改、插入、删除或重放而进行
的检测和纠正。
当没有人被授权进行修改时,你可以把有意的修改看作是未授权修改的一种特殊情形。但是,采取这种观点并没有多大帮助,因为授权体系的有或无对于需要解决的问题的本质以及相应的安全机制都有影响。
完整性通常是其他安全特性的先决条件。比如,攻击者可能试图通过修改操作系统或操作系统引用的访问控制列表来挫败机密性控制。因此,我们必须保护操作系统的完整性或者访问控制列表的完整性来实现机密性。
最后,我们应当注意的是还有更一般的完整性定义,它把安全性和可用性都当作是完整性的一部分。
1.1.5 可用性
我们采用CTCPEC中给出的定义:
可用性 产品的服务在需要时不经太多延迟即可使用的特性。
国际标准ISO 7498-2[51],通信安全的ISO/OSI安全体系结构,给出了几乎相同的定义:
可用性 需要时可被一个授权实体访问和使用的特性。
可用性是超出传统的计算机安全范围的一个非常令人关注的问题。用于改善可用性的工程技术来自于其他领域,象容错计算。在安全领域,我们想要保证的是,恶意的攻击者不能阻止合法用户合法访问他们的系统。也就是说,我们希望防止拒绝服务(denial of service)。对此,我们引用ISO 7498-2的定义:
拒绝服务 阻止对资源的授权访问或者延误时间关键性的操作。
近来,因特网上已经出现了洪泛攻击(flooding attacks)的事件,攻击者用大量的连接请求淹没服务器,从而有效地使服务器瘫痪。在许多情形下,可用性可能是计算机安全最重要的特性,但处理这类问题的安全机制却是特别缺乏。事实上,限制太多的安全机制本身就可能导致拒绝服务。
1.1.6 可审计性
现在我们已经讨论了计算机安全的三个传统领域。回想一下,你可以看到它们都研究了访问控制的不同方面,并且把重点放在了预防令人讨厌的事件上面。我们必须接受这样的事实,即我们几乎从来都无法防止所有不正确的行为。首先,我们可能会发现授权行为可以导致安全违背;其次,我们可能会在我们的安全系统中发现一个缺陷,使得攻击者可以找到绕过我们的控制的办法。因此,你可能需要在你的安全列表中加入新的安全要求。用户应当为他们的行为负责,这个要求在正在出现的电子商务世界中尤为重要,而你已经能在象橙皮书这样历史性的文档中找到它了:
可审计性 审计信息必须有选择地保存和保护,以便影响安全的行为可以被追溯到责任方。
为了做到这一点,系统必须识别和认证用户,必须保存一份安全相关事件的审计记录。如果发生了安全违背事件,审计记录中的信息可以帮助确认作恶者,以及作恶者损害系统所采取的步骤。
1.1.7 可靠性和安全性(Safety)(安全(保险),安全,安全措施)
在进行安全性(security)讨论时,还必须提及计算的其他领域,象可靠性,它涉及(意外)故障,和安全性(safety),它涉及系统故障对环境的影响,也涉及到系统在不利条件下必须正确运行的情形。
提及这些领域的原因之一是概念上有重叠。依你首选的观点而定,安全性(security)可以是可靠性的一个方面,或者反之亦然。IFIP WG 10.4试图避免这种两难的处境,它引入可信任性(dependability)作为一个统一的概念,并将安全性(security)、可靠性、完整性和可用性当作可信任性的各个方面。
可信任性(Dependability,可靠性(强度,坚固度),相依性,依赖性) 指计算机系统的这样一种性质,它使得系统提供的服务有理由被信任。这里,系统提供的服务就是它的用户所能感知到的它的行为;用户是与系统相互作用的另一个系统(物质,人)。
原因之二是有些应用必须同时解决多个问题。比如,考虑安全紧要(safety-critical)应用中的一个计算机系统。有时系统用户必须对紧急事件作出反应,安全(security)控制应当防止入侵者恶意造成意外事故。入侵检测系统试图通过寻找陌生的行为模式来识别攻击,对紧急事件的反应有时候看上去也是陌生的——但愿紧急事件很少发生——因此入侵检测可能会将紧急情况下的合法行为误解为攻击,并启动安全(security)机制,这可能会把问题搞糟,因为安全(security)机制会干扰应急人员的行动。一般来说,你不能孤立地解决安全性(security)的问题,而不考虑你想要保护的应用的其他要求。
最后,应用于这两个领域的工程方法是类似的。比如,评价安全(security)软件的标准和评价安全紧要(safety-critical)软件的标准有许多相似之处,有些安全专家希望最终将只有一个标准。
1.1.8 我们的计算机安全定义
在本书中,我们将采用以下的计算机安全定义:
计算机安全 计算机安全研究如何预防和检测计算机系统用户的非授权行为。
正确授权和访问控制这两个概念对于本定义是至关重要的。正确授权假设存在一个安全策略,即一组声明什么行为是允许的和什么行为是禁止的规则。安全策略域即是由策略所控制的用户、数据客体、机器等实体组成的集合。
你可以将纠正不正确行为的影响包括到安全定义中,但这个方面对于我们进一步的讨论作用不大。
从对术语的初步讨论得出的主要结论是:
不存在单一的安全定义;
当你阅读文档时,注意不要将你自己的安全概念与文档中使用的概念相混淆;
大量的时间正被花费(和浪费)在试图定义明确的安全概念上。
计算机安全最根本的两难处境随着依赖计算机安全的用户数量从处理机密数据的少数公司发展到与因特网相连的每个人,人们对计算机安全的需求已经发生了巨大的变化。最起码,这种变化已经导致了一种根本性的两难处境的出现:
不懂安全的用户有特殊的安全需求,却常常不具备安全的专门知识。
这种两难处境在当前的安全评估策略中是显而易见的。通俗地说,安全评估检查产品是否提供了它所承诺的安全服务。因此,必须规定安全系统的功能,我们需要确保安全控制是有效的,并且能够抵抗渗透的企图。
橙皮书是第一本评估安全产品(操作系统)的指南,在计算机安全的发展中有着巨大的影响力。在橙皮书中,功能性和承诺(assurance,(质量)保证,担保)被捆绑成预定义的类,用户只能从这个固定的菜单中选择。许多提供商还通过给出产品的橙皮书分类来说明产品的安全等级。但是橙皮书相当刻板,并且在解决计算机网络和数据库管理系统的安全评估上还不是非常成功。因此,迫切要求有一套更灵活的标准集。
ITSEC适应了这种需要,它将功能性和承诺分开,以便规定特定的评估目标(targets of evaluation,TOE)。不懂安全的用户现在只要搞清楚特定的TOEs,并且针对不同的TOEs去比较被评估的产品。
计算机安全的这个两难处境会以不同的形式出现,解决它是目前计算机安全中最为紧迫的挑战。不足为怪的是,这个难题不存在简单的答案。
同这个根本性的两难处境相比较,安全与易于使用之间的冲突采用了简单的工程上的折衷。安全对性能的影响是多方面的。
安全机制需要额外的计算资源,这个代价容易被量化。
安全干扰用户熟悉的工作模式,繁琐或不合适的安全限制导致生产力的浪费。
必须花费精力去管理安全,因此安全系统的购买者经常选择具有最好的图形用户界面的产品。
安全是一种需要论证的代价。评估没有安全的代价属于风险分析的范围,风险分析是安全管理的一个重要方面,但它不在本书讨论的范围内。
数据对信息计算机安全是关于控制对信息和资源的访问。然而,控制对信息的访问有时是很难描述的,因此常常用更加直截了当的目标,即控制对数据的访问来代替。数据和信息之间的区别是很微妙的,但它也是计算机安全中某些更加困难的问题的根源。数据代表了信息,信息是数据的(主观)解释。
数据 依照约定所选择的用来表现我们概念上和真实世界中某些方面的物理现象。我们赋予数据的含意称为信息。数据用来传输和存储信息,以及依照形式化规则处理数据之后获取新的信息[24]。
当信息和相应的数据之间存在紧密联系时,这两种方法可能会产生非常相似的结果。但事情并不总是这样的。将信息通过一个隐蔽信道(见4.2.4)传输是可能的,在这里,数据是对访问请求的“是”或“否”的回答,而收到的信息却是一个敏感文件的内容。另一个例子是统计数据库的推理(inference)问题(见14.4)。我们来扼要地看一下这个问题,考虑一个纳税申报单的国内税收数据库,这个数据库不仅被税务稽查员使用(他们访问个人记录),也被财政部官员使用以便进行总体规划。财政部官员必须能够访问纳税申报单的统计概要,但是没有权利访问个人记录。假定数据库管理系统仅允许对足够大的数据集进行统计查询以保护个人数据,但是仍然可能对两个仅相差一条记录的足够大的数据集进行统计查询,并将查询结果结合起来。这样,即使没有对数据进行直接访问,仍然可以获得关于某条个人记录的信息。
计算机安全的原则你可能会听到这样一些话,说计算机安全是一个非常复杂的问题,“象火箭科学”。你千万不要让这样的看法把你吓倒。如果你有机会用系统化的方法去实现一个计算机系统的安全特性,那么一套行之有效的软件(系统)开发方法以及对一些基本的安全原则的良好理解,将会使你省力不少。然而,如果你事后才想起来要在一个已经非常复杂的系统上再加上安全特性,那么当你被该系统已经采取的各种并未考虑安全要求的设计决定所限制时,你就非常艰难了。不幸的是,后者的情形是经常发生的。
现在我们要提出一些基本的计算机安全设计要素(design parameters),这些设计决定提供了编排本书内容的框架。图1.1说明了计算机安全设计空间中的主要维度,横轴代表安全策略的重点(见1.4.1),纵轴代表一种保护机制被实现的计算机系统层次(见1.4.2)。
控制重点让我们重新描述1.1.4中给出的完整性定义。我们可以说完整性与服从(compliance,一致(符合,顺从))一组给定的规则有关。我们可以在以下方面定出规则:
数据项的格式和内容(内部一致性);比如,一条规则可以规定帐目数据库中的余额域必须包含一个整数;这个规则不依赖于访问数据项的用户或者作用在数据项上的操作。
可能作用在一个数据项上的操作;比如,一条规则可以规定只有“开户”、“查余额”、“取款”和“存款”操作可以访问帐目数据库中的余额项,并且只有银行工作人员允许执行“开户”操作;这样的规则可能依赖于用户和数据项。
允许访问一个数据项的用户;比如,一条规则可以规定只有帐户的持有者和银行工作人员可以访问帐目数据库中的余额项。
我们刚才已经进行了一项重要的和一般性的观察,得出了我们的第一个设计原则。
第1个设计决定(决策,decision) 在一个给定的应用中,一个计算机系统中的保护机制应该集中在数据、操作还是用户上?
在实施安全控制时,这个选择是一个基本的设计决定。操作系统传统上集中在保护数据(资源)方面,而在现代应用中则更多地与控制用户的行为有关。
1.4.2 人-机标尺
图1.2给出了一个计算机系统的简单的分层模型。这个模型只准备用作一个一般性的指导,你不应该指望在你分析的每一个计算机系统中发现所有这些层次,而当你发现一个系统有多于我们模型中给出的五个层次时也不要觉得吃惊。
用户运行应用程序,这些应用程序被定制成满足非常明确的应用需求。
应用程序可以使用像数据库管理系统(DBMS)或客体访问经纪人(ORB,object reference broker)这样的通用软件包提供的服务。
这些软件包运行在操作系统之上,操作系统执行文件和内存管理,并控制对打印机和I/O设备等资源的访问。
操作系统可能有一个协调对处理器和内存访问的内核。
硬件,即处理器和内存,物理上存储和处理计算机系统拥有的数据。
安全控制可以被合理地放置于任何一个层次上。我们现在已经解释了我们的第二个基本安全原则的各个方面。
第2个设计决定(决策,decision) 一个安全机制应该被放置在计算机系统的哪一个层次上?
当你研究已有的安全产品时,你将观察到从硬件到应用软件每一层上的安全机制。设计者的任务就是为每一个机制寻找合适的层次,以及为每一个层次寻找合适的机制。
再来看一下我们的新的安全原则,将一个计算机系统的安全机制想象成一些同心的保护环,其中硬件机制位于中心,应用机制位于外围(图1.3)。靠近中心的机制趋向于更通用、更面向计算机和更关心控制对数据的访问,外围的机制则更适合解决个别的用户需求。结合我们的前两个安全原则,我们将用人-机标尺来指放置安全机制,图1.4。
1.4.3 复杂性对保险性一个安全机制在人-机标尺上的位置常常同它的复杂性密切相关,在中心你看到简单的通用机制,而应用通常要求功能丰富的安全机制。因此,你还必须作出第三个决定。
第3个设计决定(决策,decision) 你偏爱简单性和更高的保险性(assurance,确信(保证,信心)),还是更希望一个功能丰富的(feature-rich)安全环境?
这个决定和计算机安全的两难处境相关联,一个简单的通用机制无法满足特殊的保护需要,但是要在一个功能丰富的安全环境中选择一个合适的选项,用户必须是安全专家,无疑地安全知识缺乏的用户就被置于了一个不利的位置。
为了获得高度的保险性,安全系统必须经过尽可能彻底的详细检查,因此在复杂性和保险性之间显然有一个折衷。你想要的保险程度越高,你的系统就应该越简单。因此,你将会立即注意到以下原则:
功能丰富的安全系统和高保险性(保证,assurance)是很难相互匹配的。
不难理解,高保险性要求遵从系统化的设计原则(practice,惯例;常规;准则)。事实上,计算机安全是较早利用形式化方法为工具来寻求最高程度保险性的领域之一。
1.4.4 集中式控制还是分布式控制
在一个安全策略域内,应该执行相同的控制。如果有一个唯一的中央实体负责安全,那么很容易获得一致性,但是这个中央实体可能成为性能瓶颈。反过来,一个分布式的解决方案可能更有效,但我们必须格外小心,保证不同的成员执行一致的策略。
第4个设计决定(决策,decision) 定义和执行安全的任务是应该交给一个中央实体,还是应该托付给系统中的各个成员?
这个问题出现在分布式系统安全中是很自然的,你将会看到这两种方法的例子。但是,正象Bell-LaPadula模型(见4.2)中必选和任选的安全策略所论证的那样,这个问题在大型机系统的环境下也是很有意义的。
下面的层次到目前为止,我们已经简要地谈到了保险性,但是我们主要研究了为表达最恰当的安全策略所要做的选择。现在我们该来考虑一下试图绕过我们的保护机制的攻击者了。每一个保护机制定义了一个安全周界(边界),那些失效后也不会损害保护机制的系统部分位于周界的外部,那些可被用来使保护机制失效的系统部分位于周界的里面。这个观察导致了对1.4.2中提出的第二个设计原则的一个直接和重要的扩展。
第5个设计决定(决策,decision) 你如何防止攻击者访问位于保护机制下面的层次?
可以访问“下面层次”的攻击者处于一个能够摧毁保护机制的位置。比如,如果你在操作系统中获得了系统特权,通常你就能够改变那些包含有服务层和应用层安全机制控制数据的程序或文件。操作系统的逻辑访问控制可以通过对物理存储设备的直接访问而绕过去。下面我们将进一步给出5个例子来说明这一点。安全机制有易于攻击的软肋,并易于遭受来自下面层次的攻击,这些事实表明我们必须关注这些问题,但没有必要为此而悲观失望。当你达到了一个无法运用计算机安全机制的阶段,或不想使用计算机安全机制时,你仍然能够采取适当的物理的或机构的安全措施(图1.5)。
恢复工具如果内存的逻辑组织由于某些物理的内存故障而损坏,那文件就无法访问了,即使这些文件的物理表示仍然是完整的。恢复工具,象诺顿实用程序(Norton Utilities),可通过直接读(物理)内存来帮助恢复数据,进而恢复文件结构。这样的工具当然也可以用来绕过逻辑访问控制,因为它不关心逻辑存储结构。
Unix设备
Unix将I/O设备和物理内存设备作为文件来管理,因此同样的访问控制机制也可用于这些设备,就象用于文件一样。如果访问许可定义得不好,比如将读访问授予一个包含读保护文件的磁盘,那么攻击者就可以读磁盘内容,然后重建文件。读者可以在第6章Unix安全中找到更多的信息。
客体重用(内存释放)
在一个单处理器多道程序设计系统中,几个进程可以被同时执行,但是任何时刻只有一个进程能够“占有”处理器。任何时候当操作系统挂起一个运行着的进程而去激活下一个进程时,必须执行一个上下文切换,被挂起的进程以后要继续执行时所需的全部信息必须保存下来,而与新进程相关的信息必须建立起来。出于安全的考虑,必须避免存储残留,即在分配给新进程的内存区域中遗留数据。这可以通过用一个固定的位模式重写所有被释放的存储位置或者只允许新进程对它已经写入的存储位置进行读访问来解决。
备份一个尽责的系统管理员会定期地进行备份。谁能够得到备份磁带,谁就能够访问磁带上的所有数据。逻辑访问控制在此毫无帮助,备份磁带必须被安全地锁藏起来以保护数据。
内核转储当系统崩溃时,它会创建一个其内部状态的内核转储,这样可便于确定崩溃的原因。如果内部状态包含敏感信息,如密钥,而内核转储存放在一个任何人都可以访问的文件中,那么一个警觉的攻击者可以毫无困难地破坏系统的安全。
进一步的阅读
如果你想更多地了解计算机安全,你有许多书可以作参考。文献[130]提供了对该学科的一个非常通俗易懂的介绍。如果你想一般性地了解计算机安全,特别是你想更多地了解安全管理,文献[145]是一本不错的书。在本领域的另一个方面,文献[1]介绍了计算机安全的理论基础。文献[56]详细讨论了设计安全操作系统的技术细节,综述了Gasser在上世纪80年代建立安全的操作系统的经验。文献[125]对信息安全进行了综合性的介绍,并为进一步阅读提供了许多有价值的指导。
为进一步阅读与本介绍性章节相关的内容,文献[163]中对访问路径的讨论是特别相关的。这本书还对财务部门中常用的操作系统的安全特性作了有趣而实用的描述。介绍专用操作系统安全特性的书一般比较昂贵,而且大多关注与管理这类系统有关的问题,如要调用的窗口及可选择的选项等,对安全实现的方法没有作太多深入的介绍。Park关于AS/400[122]的书是一个例外,这本书深入讨论了操作系统的技术细节,并且说明了较低层的代码怎样损害由操作系统提供的安全。关于Unix安全较好的书是[36,50,55,162],对于Windows NT你可以参考[63,139,149],象上面所说的那样,这些书也都有自己相应的读者群。对于更专门的话题,你可以在相关章节的后面找到更多资源的指导。
为了正确认识一个研究领域的现状,你还应该了解它的历史。文献[156]和[2]是两篇很有影响力的报告,它们引发了计算机安全中的许多研究。如果你无法得到这些报告,文献[93]提供了对计算机安全早期历史的一个概要。
练习题练习1.1 收集安全概念的定义。可以从美国TCSEC计划、英国ITSEC计划和加拿大 CTCPEC网站开始:
http://www.radium.ncsc.mil/tpep/process/faq.html
http://www.itsec.gov.uk
http://ftp.cse-cst.gc.ca/pub/criteria/CTCPEC
许多大的IT公司在他们自己的网站上也有关于安全的网页。
练习1.2 写一篇短文讨论数据与信息之间的区别,并用你自己的例子证明控制对数据的访问并不一定意味着就是控制对信息的访问。
练习1.3 医疗记录引起独特的安全问题。假定你的医疗记录可以被在线访问到,一方面这个信息是敏感的,应该保护不让泄漏;另一方面在危急情况下,救治你的医生必须能够访问到你的医疗记录。你如何使用预防、发现和恢复措施来保护你的记录?
练习1.4 设计一个安全策略用于保护存放在计算机系统中的考试成绩,你的策略至少应该考虑学生、主讲老师和管理人员的访问需求。
练习1.5 在你正在使用的计算系统上,找出可能包含安全机制的软件组件。
练习1.6 讨论:一个好的图形用户界面是购买安全产品的恰当的判断标准吗?
练习1.7 再找出一些例子,说明某一层的安全机制可以被能够访问较低层次的攻击者绕过。
练习1.8 确定在分析个人计算机(PC)安全时可能适用的安全周界。在你的分析中,考虑什么时候我们可以正确地假设放置PC的屋子、PC本身或者PC中的某些安全模块位于安全周界之内。
身份识别与认证安全系统有时必须检查请求服务的用户的身份,认证就是验证用户身份的过程。用户认证有如下两个理由:
用户身份是访问控制决策的一个参数;
在将安全相关事件记入审计日志时,用户身份要被记录下来。
将访问控制建立在用户身份的基础上并不总是必需的或是合适的,然而在审计日志中使用身份却有非常充分的理由。本章研究身份识别和认证,因为它是目前计算机系统的标准。分布式系统中的认证是第十章的内容。
目标重温一种相当熟悉的机制,以此来了解一些一般性的经验。
获得口令保护的入门知识。
懂得安全机制有赖于管理措施才能有效实施。
理解在计算机安全中使用抽象的危险性。
2.1 用户名和口令
确切地说,你接触计算机安全是从你注册到一台计算机上并被要求输入你的用户名和口令开始的。第一步称为识别,声明你是谁;第二步称为认证,你证明你就是你所声称的那个人。为了将“认证”这个词的用法与其他解释区分开来,我们特别指:
实体认证 验证一个被声称的身份的过程。
一旦你输入了用户名和口令,计算机就把你的输入和存在口令文件中的相应条目进行比较。当你输入了一个有效的用户名和相应的口令后,注册就成功了。如果用户名或口令不正确,注册失败。通常注册画面会再次显示出来,你可以重试一次。有些系统记录失败的注册次数,并当次数达到某门限值时锁住用户帐号。为了减少攻击者使用已有用户注册但无人看管的计算机的可能性,可以不仅在会话开始时要求认证,也可以在会话期间定期要求认证(重复认证)。你也可以选择锁住屏幕,或当某个用户空闲太久时自动关闭其会话。
重复认证解决了计算机安全中一个熟悉的问题,称为TOCTTOU(time of check to time of use),即操作系统在会话开始时检查用户的身份,而随后在会话过程中使用身份作访问控制决策。
以前,你可能会在一个包含友好欢迎词和你将要使用的某些系统信息的屏幕上输入用户名和口令。如今,警惕的系统管理员不会让外界获得太多的信息,并且将欢迎词换成了警告非授权用户不要进入。比如,Windows NT提供有一个显示法律公告的选项,用户必须接受这些警告信息,注册才能进行下去。
今天,大多数计算机系统使用基于用户名和口令的身份识别和认证作为它们的第一道防线。对于大多数用户来说,这个机制已经成为在计算机上启动一个会话过程所不可缺少的组成部分。这样,我们就有了一个广泛接受而又不难实现的机制;然而另一方面,获取有效的口令又是获得对计算机系统未授权访问的一种极其普通的方法。因此,让我们来分析一下作为认证机制的口令的实际安全性。我们将考虑以下三种威胁:
口令猜测口令欺骗口令文件泄漏不要忘了用户在口令保护中起着重要的作用。当你泄漏了口令,比如告诉了同事,或者写在便笺上并贴在计算机上,都会危及到认证的安全。
选择口令口令选择是一个重要的安全问题。尽管你无法完全避免攻击者意外地猜测出有效的口令,但你可以努力使这种事件的发生率尽可能的低。为说明如何做,你必须知道攻击者基本上遵循以下两种猜测策略:
穷尽搜索(强力):尝试有效符号所有可能的组合,直到一定的长度。
智能搜索:通过一个受限的名字空间进行搜索,比如,尝试那些与用户有联系的口令,像名字、朋友和亲戚的名字、汽车商标、车牌号、电话号码等,或者尝试那些较常流行的口令。这种方法的一个典型例子是字典攻击,它尝试来自于一个在线字典的所有口令。
那么,你的防卫措施是什么?
设置口令:如果系统管理员或者用户忘了为用户帐户设置口令,攻击者甚至免除了猜测口令的麻烦。
改变缺省口令:当系统被交付使用时,它们通常带有缺省的帐户,像具有缺省口令manager(“管理员”)的缺省帐户system(“系统”)。这有助于现场工程师安装系统,但是如果口令不改,攻击者可以很容易地进入系统。在刚才举的例子中,攻击者甚至可以获得一个非常有特权的帐户。
口令长度:为了挫败穷尽搜索,必须规定一个最小口令长度。不幸的是,许多Unix系统的最大口令长度只设到8个字符而已。
口令格式:在你的口令中混合使用大、小写字母,并且包含数字和其他非字母符号。
避免易于猜测的口令:当你发现攻击者配备有流行口令的清单,并且字典攻击已经大大扩展了“易于猜测”的范围时,你不要觉得吃惊。今天,几乎针对每一种语言你都可以找到一本在线字典。
系统怎样进一步地帮助改善口令的安全性呢?
口令检查器:作为一个系统管理员,你可以使用针对某些“脆弱”口令字典的口令检查工具来检查口令。这样可以模仿并先发制人地对付针对系统的字典攻击。
口令生成:某些操作系统包含有口令发生器,能够生成随机的和可发音的口令。用户不允许选择自己的口令,而必须采用系统建议的口令。
口令老化:许多系统可以设置口令到期的日期,迫使用户定期改变口令。可以有附加机制防止用户回复到老的口令,比如,使用一个保存有最近用过的10个口令的列表。当然,通过足够多次的改变直至老的口令又被接受,坚定的用户还是能够回复到他们喜爱的口令的。
限制注册尝试:系统可以监视不成功的注册企图并作出反应,完全锁住用户帐户,或至少锁住一段时间,以防止或阻止进一步的尝试。
通知用户:在成功注册之后,系统可以显示上一次注册的时间以及从那以后失败的注册企图次数,从而提醒用户有关最近的攻击企图。
依照刚才所说的,似乎只要用户使用由系统产生的长口令、口令中混合使用大小写字母和数字符号、并定期改变口令,我们就可以获得最高的安全性。这种方法真的奏效吗?在实际中我们获得希望的安全性了吗?
用户不太可能记住长而复杂的口令,因而,这样的口令将被记在纸上,并放在靠近计算机的地方,而这对合法用户和潜在的入侵者都是最有用的,因此留心贴在计算机终端上的口令是安全管理员的本职工作。当口令频繁改变时也有类似需要考虑的问题。发现难以按照这种严格的口令管理方案去做的用户,可能试探着去使用更易于记忆从而也更易于被猜测的口令。他们可能很快回复到他们喜爱的口令,或对口令作一些简单的和易于推断的改变。比如,如果你必须每个月改变口令,将月份(两个数字,从1到12,或三个字母,从JAN到DEC,依你的选择)加到你所选择的口令上,就提供了你可以记住的口令。当然,攻击者只要发现了其中的一个口令,他就很容易猜测下一个。
还有另外一个方面的问题你必须考虑。假定你的用户非常认真地采取了所有的安全预防措施,避免使用易于猜测的脆弱口令,不把口令写下来,但是不可避免地经常忘记口令,这会影响用户的工作。为了获得一个新的口令,用户必须同系统管理员联系,这又会影响系统管理员的工作,并为新的攻击开辟途径。如果用户和系统管理员不能亲自见面,他们可能需要通过电话协商新的口令。系统管理员能够正确地认证用户吗?威逼操作员发布口令被证明是一种可靠的侵入系统的方法。成功的攻击更多地依赖于社交能力而不是技术的精巧。
你一定不能孤立地考虑安全机制。事实上,在一种安全机制上强调太多可能会削弱系统,因为至少用户会找出绕过安全机制的途径去做他们的工作。通过口令,你已经注意到口令的复杂性和人的记忆本领之间的折衷。
欺骗攻击通过用户名和口令的身份识别和认证提供了单向认证(unilateral,一方的(单向的))。用户输入口令,计算机验证用户的身份。但是,用户知道谁接收了这个口令吗?到目前为止,这个答案是否定的。用户不能保证线路另一端当事人的身份。
这是一个现实的问题,它导致了第二种类型的口令泄漏。在欺骗攻击中,攻击者(他可能是一个合法用户)运行一个程序,在某些终端或工作站上给出一个假的注册画面。一个毫无戒备的用户来到这个终端试图注册。这个受害者通过标准注册菜单的引导被要求输入用户名和口令,这些信息被攻击者保存下来。然后执行可能被移交给用户,或者用一个(假的)出错消息中止注册,欺骗程序终止运行。控制被返回到操作系统,操作系统用一个真的注册请求提示用户,用户重试,第二次注册成功,并可能完全不知道口令已经泄漏的事实。针对这样的欺骗攻击该怎么办呢?
显示失败的注册次数可以暗示用户已经发生过这样的攻击。如果你的第一次注册失败了,但在你进行第二次注册时,你被告知自上一次会话以来没有不成功的注册,那么你就应该有所怀疑了。
可信任路径:保证用户是与操作系统通信而不是与一个欺骗程序在通信。比如,Windows NT有一个安全注意序列CTRL+ALT+DEL,它调用Windows NT的操作系统注册画面。你应该按这样的安全注意键开始一个会话,即使这时屏幕上已经显示了注册画面。
相互认证:如果用户要求更有力地确信与之通信的系统的身份,如在一个分布式系统中,那么可以要求系统向用户认证自己。
除了欺骗攻击,入侵者还可以有其他“找到”口令的方法。上面我们对于注册的描述是相当抽象的,口令直接从用户传递给口令检查例程。实际上,口令会被临时存放在中间存储位置,如缓冲器、高速缓存,或者甚至是一个网页。这些存储位置的管理通常超出用户的可控范围,而口令在这些位置的存放时间可能会比用户预料的要长。
在开发基于web的在线银行服务[5]时,开发者遇到的一个问题很好地说明了这一点。Web浏览器会缓存信息,以便用户能够返回到他们最近访问过的页面。为使用在线银行服务,你在一个web页上输入你的口令。你处理完你的事务,关闭银行应用,但是没有终止浏览器进程。该终端上的下一个用户能够回退到有你口令的那一页,并以你的名义注册。
作为一种防范措施,建议在完成银行事务后退出浏览器。注意到现在用户被要求参与到内存管理活动中来,这在其他地方是不会涉及到的。这是客体重用(见1.5)的又一个例子。
抽象是有用的,同时又是危险的。用抽象的术语来讨论口令安全是有用的;你可以研究关于口令格式或口令老化的策略,而不需要知道在你的IT系统中口令是怎么处理的。仅在这样抽象的层次上讨论口令安全是危险的,实现方面的缺陷会损害最好的安全策略。
保护口令文件为了验证用户的身份,系统将用户输入的口令同保存在口令文件中的一个值进行比较。对于攻击者来说,这样的口令文件当然是极具吸引力的一个目标。未加密的口令文件内容的泄漏或者对口令文件内容的修改,构成了口令泄漏的第三种可能。你甚至可能还要关心加密口令的泄漏,那样字典攻击可以离线进行,而象(像)限制失败的注册次数这样的保护措施将不会起作用。为保护口令文件,我们可以有以下选择:
密码保护,
操作系统执行访问控制,
密码保护和访问控制相结合,或者可能有更强的保护措施来减慢字典攻击的速度。
对于密码保护,我们甚至不需要加密算法,有一个单向函数就行了。目前,你可以使用以下的初步定义:
单向函数就是易于计算但很难逆推的函数,也就是说,给定x很容易计算f(x),但给定f(x)很难计算x。
第12章有关于单向函数的更详细的介绍。单向函数早就用于保护存储的口令了([158],p.91ff),口令文件中保存的不是口令x 而是f(x)。当用户注册并输入口令(设为x')时,系统调用单向函数f,并将f(x')与用户的f(x)相比较,如果两个值相同,用户就被成功认证。下面我们将使用“加密的”口令这个词,即使实际上我们只是对口令使用了一个单向函数。
如果不担心字典攻击的话,口令文件现在谁都可以看了。如果f是一个真正的单向函数,从f(x)重建口令x是不可行的。在字典攻击中,攻击者“加密”字典中的所有单词,并与口令文件中的各个加密表项进行比较,如果找到匹配的表项,攻击者就知道了那个用户的口令。单向函数可以用来减慢字典攻击的速度,这种考虑指导了在Unix系统中选择使用单向函数crypt(3),该函数使用略加修改的DES算法,用全零的数据块作为初始值,用口令作为密钥,重复运行算法25次[104]。当然,这会给合法用户注册带来一点点性能损失,但是如果你优化了单向函数的速度,你同时也提高了字典攻击的性能。
操作系统中的访问控制机制只允许拥有适当权限的用户访问文件和其他资源。只有特权用户才能写口令文件,否则的话,即使口令被加密保护了,攻击者也可以简单地通过修改用户的口令来访问这些用户的数据。如果只有特权用户才能读口令文件,那么从理论上说口令可以不用加密保存。如果口令文件中包含了非特权用户也需要的信息,那么口令文件必须包含加密的口令。然而,这样的文件仍然可被用于字典攻击,一个典型的例子是Unix的/etc/passwd。因此,最近的Unix版本将加密的口令保存在一个不可公开访问的文件中,这样的文件被称为影子口令文件(shadow password files)。比如,HP-UX可以使用一个影子口令文件/.secure/etc/passwd。
专用存储格式提供了一种较弱的读保护形式,比如Windows NT以专门的二进制格式保存加密的口令。一般用户的攻击企图会被挫败,但是一个意志坚定的攻击者将能获得或推断出必要的信息,从而找到安全相关数据存储的位置。“通过隐匿而获得的安全性”本身不是非常强壮,但可以把它加到其他机制上,如口令加密。
但是,存在着这样一种危险,就是对这种外围防线的成功突破会摧毁其他所有的部分。1997年初,有人声称Windows NT的口令安全已被突破了。听上去很严重,是吗?实际情况是发布了一个程序,能将加密的口令从二进制格式转换成另一种易于阅读的表示形式。激动之余发现根本不是什么大事情。
如果你担心字典攻击,但又不能隐藏口令文件,你可以考虑口令加盐。当一个口令需要加密保存时,加密前将一些附加信息(盐)附加到口令上,盐同加密的口令保存在一起。如果两个用户有相同的口令,它们在加密口令的文件中将有不同的表项。加盐减慢了字典攻击的速度,因为不可能同时搜索几个用户的口令。
你已经看到了三个安全设计的问题:
几种机制结合起来可以增强保护。加密和访问控制用来保护口令文件。
通过隐匿而获得的安全性只能防御不经心的入侵者。不要对这种策略抱太多的信任。
如果可能的话,将安全相关的数据和那些要被公开访问的数据隔离开来。在Unix中,/etc/passwd包含有以上两种数据。影子口令文件能够获得所希望的隔离性。
2.5 一次签到
用口令来区分朋友和敌人已经有几个世纪了。在IT环境中,它们控制对计算机、网络、程序和文件等的访问。但作为用户,如果你为获取一点信息而在信息空间漫游时必须一遍又一遍地输入口令,你会觉得很不方便。当你坐在计算机前,需要网络中某台数据库服务器中的信息时,如果你必须做以下一些事情,你会觉得愉快吗:
向计算机输入第一个口令,
输入第二个口令进入网络,
输入第三个口令访问服务器,
输入第四个口令访问数据库管理系统,
输入第五个口令打开数据库中的一张表。
且不去想可能需要记忆五个不同的口令,并需要在每一种场合选择一个正确的口令输入,就是将相同的口令重复输入五遍也是够糟糕的了。
一次签到服务解决了这个问题。你只要输入一次口令,系统保存这个口令,并在你需要重新认证的时候为你取出口令做这件事。
这样一种一次签到服务为你增加了方便,但它也引起了新的安全问题。你如何保护存储的口令?前面提到的一些技术不再有用,因为系统现在需要你的明文形式的口令。
系统设计者必须均衡考虑方便性和安全性。易于使用是使得IT系统真正有用的一个重要因素,不幸的是,许多方便的举措也引入了新的弱点。后面还会遇到这样的问题。
可供选择的方法如果你不满足于口令提供的安全等级,你还可以做什么呢?从一般观点来看,以下选择都是可取的。作为用户,你可以基于以下信息进行认证:
你知道的事,
你拥有的东西,
你是谁,
你做什么,
你在哪里。
你知道的事
用户必须知道一些“秘密”才能被认证。你已经看到了这种认证模式的第一个例子,口令就是你知道的事情。另一个例子是同银行卡一起使用的个人识别号码(PIN)或者类似标记(tokens)。第三个例子,考虑你打电话查询银行帐户的情形,接听电话的银行职员在告诉你任何信息之前可能会向你询问更多的个人信息,像家庭住址、出生日期、配偶名字等。
在这种认证模式中,获知你秘密的任何人就“是你”,另一方面,如果你把你的秘密告诉其他人,你不会留下痕迹。考虑以下情形,在你单位发生了滥用计算机的事件,有人用你的用户名和口令注册了。你能证明你是无辜的吗?你能证明你没有泄漏口令吗?
你拥有的东西
用户必须出示一个物理标记才能被认证。能打开锁的钥匙就是你拥有的东西,这种标记的另一个例子是用于控制进入公司大门的卡片或身份标签。在将来,一旦智能卡的读卡机成为工作站的标准部件,智能卡可能成为口令的替代物。
物理标记可能会遗失或被盗。如前所述,任何拥有标记的人将具有与合法拥有者相同的权利。为了增加安全性,物理标记通常与你知道的事结合起来使用,如银行卡与PIN一起使用,或者它们包含能够识别合法用户的信息,如银行卡上的照片。然而,就是将这些机制结合起来也不能防止骗子获得必要的信息去假冒合法用户,也不能阻止用户自愿传递这些信息。
你是谁
如果你真的必须准确无误地认证每一个人,你可以使用生物测定技术。刚才已经提到了带有照片的卡片,更复杂的方法使用掌纹、指纹、虹膜图案或视网膜图案来辨别一个人。
口令认证每一次都给出明确的拒绝或接受。在生物测定中,一个存储的图案与实际测量的图案进行比较,但这些图案几乎从来都不能精确匹配。因此,我们必须面对一个新的问题,就是假阳性(false positives)和假阴性(false negatives)。错误地接受一个用户(假阳性)显然是一个安全问题,而拒绝一个合法用户(假阴性)则会造成尴尬的及低效的工作环境。生物测定认证系统的设计者必须在这两种错误之间找到合理的平衡,而这种平衡极其依赖于找到这种平衡的应用。
还有一个问题,用户会接受这样一个机制吗?在被提取指纹时,他们可能感觉象被当成了罪犯一样,他们可能也不喜欢用一束激光扫描视网膜的做法。
你做什么
人们往往以一种独特的和可重复的方式做一些机械性的工作。检查手写签名就是来自纸质文档世界的一个例子,在这里伪造并不是那么困难的。为了获得更高的安全性,用户可以在一个特殊的垫子上签名,垫子可以测量出像书写速度和书写力度这样的特征。在一个键盘上,打字速度以及击键之间的间隔被用来认证用户个人。如前所述,认证系统必须建立起来,使得假阳性和假阴性减少到相关应用可以接受的程度。
你在哪里当你注册时,系统可能还要考虑你在哪里。一些操作系统已经这样做了,并且仅当你是从某个特定的终端注册时才允许访问。比如,系统管理员只可以从操作员控制台注册,而不能从任何一台用户终端注册。类似地,作为用户你只允许从你办公室的工作站上注册。这类决定在移动和分布式计算中将会更加频繁。如果在认证过程中必须建立精确的地理位置,系统可以使用全球定位系统(GPS)的服务。在处理一个请求的注册时确定用户的位置,也有助于解决过后关于用户真实身份的争端。
口令并不能认证人:成功的认证只意味着用户知道一个特定的秘密。没有办法区分合法用户和获得了该用户的口令的入侵者。
进一步的阅读
文献[104]介绍了Unix口令安全的历史,在上面还可以找到非常有趣的关于典型口令选择的统计,文献[48]介绍了Unix口令安全后来的发展。文献[63,139]描述了Windows NT的口令方案。几乎所有关于计算机安全的书都包含有大量的有关正确选择口令的建议,并且阐述了口令安全的重要性。Pfaffenberger关于因特网隐私的书[124]有一章介绍了自动口令生成,并附有指向相关软件产品的链接。
你可以在因特网上找到大量的口令破解程序,分析这样的一个程序将使你对破解程序搜索的口令类型以及所使用的字典的长度和复杂性有一个清楚的了解,但未经明确授权而运行这样一个程序可能与你单位的规章制度以及许多国家的刑法相抵触。
练习题练习2.1 检查你计算机系统上的口令方案。它在口令长度、口令格式以及口令期限方面有规定吗?口令在你系统上是怎么存储的?
练习2.2 假定只允许使用26个字母来构造口令:
如果口令最多为n个字符,n=4,6,8,不区分大小写,可能有多少个不同的口令?
如果口令最多为n个字符,n=4,6,8,区分大小写,可能有多少个不同的口令?
练习2.3 假定口令的长度为6个字符,可以使用字母和数字字符,区分大小写。在以下条件下,强力攻击平均所需的时间分别为多少?
检查一个口令需要1/10秒时间;
检查一个口令需要1微秒时间。
练习2.4 假定你只允许使用26个字母来构成长度为n的口令,进一步假设你在区分大小写和不区分大小写的两个系统中使用了相同的口令,给出猜测出大小写区分的口令所需的最多尝试次数。
练习2.5 编程:写一个口令生成程序,以一个长度为s的随机二进制种子作为输入。在下面的实验中取s=8,16,32,64:
让不同的用户用你的方案生成口令,记录不同的用户选择了相同口令的事件。
生成一个口令并加密之。通过尝试随机种子的所有值试图找出原来的口令。在找到口令之前你需要的猜测次数的期望值是多少?
练习2.6 讨论:口令由用户输入并由计算机检查,因此,在用户和计算机之间一定有通信的通道。到目前为止,我们一直是非常抽象地看待这个通道,假设它存在并且足够安全。什么时候这种假设是合理的?什么时候是不合理的?
练习2.7 如果你每次都要求使用几个口令,你可能考虑将它们保存在一个口令簿里。口令簿是一个含有你口令的受保护文件,对口令簿的访问可以通过一个主口令来控制。这样一个方案能够提供实际的好处吗?
练习2.8 [65]中描述的口令猜测在时间和内存之间存在一个折衷。令N为可能的口令数目,在一个使用N次试编码的预计算步骤中,构造出一个具有N2/3个表项的表。如果你过后想找出一个给定的加密口令,你需要N2/3次试编码。当长度为6的口令选自于5-比特字符集时,你需要多少内存空间?如果一次试编码耗时1毫秒,你多快能找到口令?
练习2.9 对商用生物测定认证系统进行一次调查,你发现用户对此系统的接受程度如何?
访问控制现在你已经登录到了系统上,创建了新的文件,并且想保护你的文件。你的有些文件可能是公用的,有些仅打算给有限的用户使用,而有些可能是私有的。你需要一种语言来表达你想要的访问控制策略,并且需要执行访问控制的机制。本章介绍一些讨论访问控制的词汇,第四章将详细讨论访问控制策略。
目标介绍访问控制的基本模型。
考虑几组访问操作,明白用直觉来代替术语的实际定义是危险的。
给出独立于特定安全策略的基本的访问控制结构。
定义部分排序(order)和格(lattice),这是经常用来表达安全策略的数学概念。
3.1 背景
在深入到访问控制的细节之前,先来考虑一下计算机系统以及计算机系统的使用在过去的几十年中发展的方式。计算机系统处理数据,并且协调(mediate,处于中间的(作为引起...的媒介,调停))对内存、打印机等共享资源的访问。它们必须提供对数据和资源的访问控制,尽管主要是为了完整性而不是机密性的缘故。传统的多用户操作系统为众多不同的用户提供普通服务,就其本质来说,这些操作系统具有简单和通用的访问操作,并且不牵涉到它们所处理的文件的意义。现代桌面操作系统支持单个用户完成他们的工作,在这种情形下,你会发现非常复杂并且极其依赖于特定应用的访问操作。用户并不关心他们程序执行时较低层的细节,因此可以想象,将高层的安全需求映射到低层的安全控制上可能是十分困难的。简而言之,你将会目睹从通用计算机系统到(灵活的)专用计算机系统的转变,在比较本书介绍的不同的访问控制模型时将这个趋势牢牢地记在心里。
3.2 主体和客体 注:大多安全方面的书在涉及安全模型时把object译为客体;在面向对象程序设计时,则译为对象。
为了讨论访问控制,我们首先必须给出一个合适的术语。“访问”的本质含义是一个主动的主体使用某种特定的访问操作去访问一个被动的客体,同时有一个引用监视程序(reference monitor)(第五章)准许或拒绝访问。这个基本的访问控制模型(见图3.1)是由Lampson[82]提出的。
典型的主体是用户或进程,典型的客体是文件或资源,象内存、打印机或计算机网络中的节点。但这并不是要把系统中的每个实体都明确地分为主体或客体,根据不同的情况,一个实体可以是一个访问请求的主体,而又是另一个访问请求的客体。术语“主体”和“客体”只是区分一个访问请求中的主动方和被动方。主体和客体给出了关注控制的两个选项,你可以规定以下任一种:
一个主体允许做什么,或者可以对一个客体做什么。
这是1.4.1中第一个设计原则的例子。传统上,一个操作系统的主要任务是管理文件和资源,也就是客体。在这样一种环境下,你主要遇到的是使用第二种方法的访问控制机制。然而,我们刚才已经提到了面向应用的IT系统,象数据库管理系统,直接面向终端用户提供服务。这种系统可以适当地加入控制主体行为的机制。
3.3 访问操作
访问操作是不同的,取决于你如何看待一个计算机系统,可以从基本的内存访问到面向客体系统中的方法调用。类似的系统可能使用不同的访问操作,更糟的是,在看似相同的操作上可能附加不同的含义。我们将研究一些典型的访问操作集,并从该领域早期的重要成果中确定我们的术语。
3.3.1 访问方式
在最基本的层面上,一个主体可以观察一个客体或者改变一个客体,因此,我们定义两种访问方式:
观察: 查看客体的内容
改变: 改变客体的内容
尽管大多数访问控制策略可以按照观察和改变的观点来表示,但这种策略描述通常离它们正在处理的应用太远了,难以检查正确的策略是否已经执行了。因此,你通常会发现一组较为丰富的访问操作。
3.3.2 访问权限和访问属性
在下一个复杂度上,你会发现4.2中讨论的Bell-LaPadula安全模型的访问权限,和Multics操作系统[119]中的访问属性,这是计算机安全历史上的两个里程碑。
有四种访问权限,执行、读、添加(有时也称为盲写)和写。图3.2给出了这些访问权限与观察和改变这两个基本访问方式之间的关系。
为了弄懂这样定义的原因,考虑一个多用户操作系统如何控制对文件的访问。用户在允许存取前必须先打开文件,通常文件可以被打开用于读或写。在这种方式下,操作系统可以避免象两个用户同时写同一个文件这种可能的冲突。为了效率的缘故,写访问通常包括读访问,比如一个编辑文件的用户不应该要求打开文件两次,一次用于读,一次用于写。因此,定义写命令是有意义的,以便它可以包括观察和改变这两种方式。
几乎没有一个系统真正实现了添加操作。在大多数的应用中,允许用户不观察客体的内容而去改变客体是一种不可行的操作。审计日志是添加权限有用的一个例子,写日志文件的进程不需要读文件,并且可能根本就不应该读文件。
操作系统可以根本不打开文件而使用文件,如程序,因此引入了既不包括观察也不包括改变方式的执行权限。你可能要问计算机怎么能够不读程序的指令就执行程序呢?你当然是对的,而且Multics执行属性确实要求执行和读权限。但是存在一些操作,客体的内容不读就可以用于执行中。考虑一个加密引擎,它在一个特殊的防篡改寄存器(图3.3)中存有一个主密钥,物理上没有办法可以读出这个主密钥,但是访问控制规则可以决定谁能使用这个密钥加密。我们可以不读这个密钥而调用它,执行权限刚好是解决这样一个问题所需要的。
在解释其他人定义的访问操作时,小心使用你自己的直觉。
Multics操作系统区分数据部分的访问属性和目录部分的访问属性。根据客体的类型用不同的方法解释一组给定的访问权限实际上是一种普遍的做法,在命名这些访问属性时我们仍然要使用象“读”或“写”这样的术语。为了使我们的表示法保持清晰,我们将用e,r,a,w来表示Bell-LaPadula访问权限。图3.4显示了访问属性和访问权限之间的对应关系。
3.3.3 Unix
一个较常用的例子是Unix操作系统的访问控制,访问控制策略用三种操作来表示:
读(read):从一个文件读;
写(write):写进一个文件;
执行(execute):执行一个(程序)文件。
这些操作同Bell-LaPadula模型中的那些操作不同,比如,在Unix中写访问并不意味着读访问。当应用于目录时,访问操作采用以下含义:
读:列出目录内容;
写:创建或重命名目录中的一个文件;
执行:搜索目录。
如你所见,Unix通过控制对文件目录的写访问来控制谁可以创建和删除文件,其他操作系统包含一个特殊的删除操作用于该目的。Unix中为文件规定的访问权限是通过修改文件在目录中的表项被改变的,其他操作系统则包含特殊的操作用于此目的。
3.3.4 Windows NT
作为最后一个例子,我们来看一下Windows NT操作系统的新技术文件系统(NTFS)用作访问控制基础的许可(permission,许可,容许,同意,【WIN,NT】权限)[63],它们是:
读
写
执行
删除
改变许可
改变所有权(ownership)
在这里,我们不依赖对目录的操作来处理文件的删除或访问权限的改变。修改访问权限是你在设置安全策略时可能想使用的一种操作,这种修改主体访问权限的操作在主体的权限被其他方修改时倾向于称为准许(grant)和取消,而在主体改变自己的访问权限时称为声明(assert,宣称(声明,维护),断言)和否认(deny)。在授权(delegation,授权;代理;代表团)策略中,当一个主体调用另一个主体且需要建立被调用主体的权限时,这一类操作是令人感兴趣的。
3.4 所有权
我们已经提到了控制主体如何访问客体的策略,并将在下一章中讨论这样的策略。我们还必须规定谁负责制定这些策略,有两个基本的选择:
资源的所有者规定谁可以访问。这类策略可称为是自主性的(自主的,discretionary),因为访问控制任由所有者来处理。
一个系统范围的策略规定谁可以访问。显然,这类策略可称为是强制性的(mandatory)。
大多数操作系统支持资源所有权的概念,并且在作访问控制决策时考虑所有权。它们可能包含重定义资源所有权的操作。
上面给出了自主性/强制性访问控制的直观解释,这仅是为了说明不应该将它们同计算机安全中常用的自主/强制性访问控制的定义相混淆。在计算机安全中,这些术语指的是橙皮书[112]中所规定的特定的安全策略。再一次声明,你必须小心不要让你的直觉误导你。
3.5 访问控制结构
下面,我们必须声明哪些访问操作是允许的。访问权限可为每个主体和客体的组合单独定义,对于数量众多的主体和客体,这种结构管理起来很不方便,而采用中间控制层是较为可取的。在下面的段落中,我们要涉及到:
主体集合S,
客体集合O,
访问操作集合A。
我们不需要对这些集合作更详细的解释了。
3.5.1 访问控制矩阵
访问控制(access rights)用一个访问控制矩阵(表)很简单地定义:
M = (Mso)s(S,o(O 且 Mso(A,
表项Mso规定了主体s可以施加于客体o上的访问操作的集合。这种方法回到了计算机安全的早期[82]。访问控制矩阵也被称为访问许可矩阵。访问控制矩阵是一个抽象的概念,当主体和客体的数量很大或者主体和客体的集合频繁改变时不太适合于直接实现。
Bell-LaPadula模型(4.2)使用访问控制矩阵建立橙皮书中的自主性访问控制策略模型。图3.5给出了一个具有两个用户和三个文件的访问控制矩阵的简单例子。
bill.doc可以被Bill读和写,但完全不允许Alice访问。
edit.exe可以被Bill和Alice执行,但除此以外他们不能访问。
fun.com可以被两个用户读和执行;只有Bill能够写这个文件。
3.5.2 能力(capabilities)
你几乎不会去直接实现一个访问控制矩阵。访问权限可以和主体保存在一起也可以和客体保存在一起,这之间有一个选择。在第一种情况下,每个主体被赋予一个能力(capability),这是一个说明该主体访问权限的不可忘却的标记,这个能力对应于访问控制矩阵中的主体行。我们前一个例子中作为能力给出的访问权限是:
Alice的能力:edit.exe,execute; fun.com,execute,read
Bill的能力:bill.doc,read,write; edit.exe,execute; fun.com,execute,read,write
典型地,能力是同自主性访问控制相联系的。当一个主体创建一个新的客体时,它可以通过授予其他主体合适的能力来允许它们访问这个客体。同样,当一个主体(进程)调用另一个主体时,它可以将它的能力,或者它的部分能力传递给被调用的主体。
能力决不是一个新的概念,但是到目前为止它们还没有成为一个广泛使用的安全机制,其原因如下,主要与安全管理的复杂性以及操作系统面向管理客体的传统定位有关。
对于谁可被获准访问一个给定的客体难以得到一个全面的了解;
取消一个能力非常困难,或者操作系统必须被授以这个任务,或者用户必须清楚它们已经传递的所有能力,当能力中的权限包括向第三方传递该能力时,这个问题尤其棘手。
然而,分布式系统的出现重新引起了人们对基于能力的访问控制的兴趣,在分布式环境中安全策略必须处理在计算机网络的节点间进行物理地或虚拟地漫游的用户。
当你决定使用能力时,你还必须花费一些心思考虑它们的保护问题。你将能力存放在什么地方?如果能力仅在一个单独的计算机系统中使用,那么仅依靠操作系统的完整性保护(第五章)就可以了。当能力在网络中传播时,你还需要加密保护(第十二章)。
3.5.3 访问控制列表
访问控制列表(ACL)将客体的访问权限同客体本身存放在一起,因此,一个ACL对应了访问控制矩阵中的一列,声明谁可以访问一个给定的客体。ACL是橙皮书C2类[112]安全操作系统的一个典型特征。我们前一个例子中的访问权限用ACL的形式表示为:
bill.doc的ACL Bill,read,write
edit.exe的ACL Alice,execute; Bill,execute
fun.com的ACL Alice,execute,read; Bill,execute,read,write.
访问权限的管理仅依靠单个主体是相当麻烦的,因此通常将用户置于组中,并也可以从用户组取得访问权限。在UNIX中,你见到过附在文件上的简单的ACL,它允许对三类主体规定其基本访问模式,即用户、组和其他(见6.4)。
对于主要配合客体访问管理的操作系统来说,ACL是一个合适的概念。但是,如果你想总的了解一个用户有哪些许可,比如要取消那个用户的许可,你需要费力地搜索所有的ACL。
3.6 中间控制
不管你如何实现访问控制矩阵,在一个大型的系统中管理用这种矩阵表示的安全策略是一项复杂的任务,尤其是,要确保矩阵中的每一项正确表示我们的意愿是繁琐和易于出错的。另外,仅依靠主体和客体的访问控制只支持相当有限的安全策略。可以被适当地包含进一个访问控制决策的其他信息可以是主体用来访问客体的程序,这完全不是一个新的思想,你可以从以下对Titan操作系统[109]的访问控制所作的评论看到这一点,该操作系统是牛津大学于60年代早期开发的。
特别地,使用一个程序标识作为访问控制决策的一个参数,和用户标识一起使用或者替代用户标识使用是可能的,这是牛津的人们一直以来觉得不可思议而没有采用的特性。
不要认为新技术必然引起新的安全问题,“新”问题时常是老问题的化身,而它们的解决原则都已是知道的。
3.6.1 分组和否定的许可
组作为一种简化访问控制策略定义的方法已经被提及到。具有类似访问权限的用户被集合成组,组被授予访问客体的许可。一些安全策略要求一个用户只能是一个组的成员,其他一些安全策略则允许是多个组的成员。
图3.6显示了一种理想状况,所有的访问许可可以通过组成员关系来传达(be mediated,处于中间的(作为引起...的媒介,调停),处在中间调解,斡旋,介于)。通常,安全策略有一些特殊的场合,在这些场合中直接给某些主体访问一个客体的许可,或者否认一个主体从它的组成员关系中获得的许可是较为方便的。一个否定的许可(negative permission)就是访问控制结构中的一个表项,它规定了一个主体不允许执行的访问操作。图3.7中,主体s1不允许访问客体o1,而主体s3被准许访问客体o5。
图3.6
3.6.2 保护环
保护环是用于说明主体和客体之间中间层的一个特别简单的例子。每个主体(进程)和每个客体依照其“重要性”被赋予一个数字,在一个典型的例子中,这些数字可以是0、1、2和3。进程按照以下规则获得它们的数字:
操作系统内核,
操作系统,
实用程序,
用户进程。
要进行访问控制决策,就比较主体和客体的数字。(决策的结果依赖于你使用保护环想要执行的安全策略。)这些数字对应同心保护环,其中环0位于中心,提供最高程度的保护(图3.8)。如果一个进程被赋予数字i,那么我们说进程“运行在环i”。
保护环主要被用于完整性保护。QNX/Neutrino微内核的系统/用户保护是说明这种保护机制的一个最新例子,它将软件组件分配给保护环,如下:
Neutrino微内核运行在环0。
Neutrino进程管理器运行在环1。
所有其他程序运行在环3。
包含敏感数据(如操作系统代码)的内存位置只能被运行在环0或环1的进程访问。
Unix使用一种类似的保护模型,但只使用级0和级3。保护环已经用于Multics操作系统中,并且开发了特殊的硬件来支持这种安全机制[138]。Intel 80386和80486微处理器在机器语言级上提供了类似的特性。然而,保护环是一种一般性的工具,可用来实现不同于这儿或者文献中提到的访问控制策略。
3.6.3 VSTa微内核中的能力(Abilities)
为了表达更复杂的访问控制策略,你需要中间层上的概念,这样更灵活,并且具有更多的内部结构。VSTa微内核的能力是这种概念的一个很好的例子,因为它们不完全是3.5.2中定义的能力(capability),所以我们使用abilities来表示。一个ability就是一个数据结构,它从一个点开始,后面跟有n个整数的一个序列,即一个ability就是一个串.i1.i2.….in,其中i1…in是整数。序列的长度n没有限制,事实上n可以等于0。Abilities的例子有.1.2.3,.4或.10.0.0.5。由于它们的内部结构,abilities集合上存在一个部分排序(偏序,partial ordering)。
定义 集合L上的一个部分排序(是L(L上的一个关系,它是
反身的 对于所有a(L,a(a成立
传递的 对于所有a,b,c(L,如果a(b且b(c,那么a(c
反对称的 对于所有a,b(L,如果a(b且b(a,那么a(b
如果两个元素a,b(L是不可比的,我们记为a(b。(符号(与书上的不一致)
Abilities可通过前缀关系进行排序。
Ability a2是ability a1的一个前缀,如果存在另一个ability a3使得我们有a1(a2a3。这时我们记a2( a1。
有了前缀排序,你就可以比较abilities了,你将得到.1(.1.2(.1.2.3,但.1(.4。一种访问控制策略可用abilities标记主体和客体,并且当主体的ability是客体的ability的一个前缀时允许访问。如果是这样,那么可以访问所有客体的超级用户的ability就是一个空串(。因此,不给一个主体赋予ability,你就可以准许它访问所有的客体。
访问控制算法比较主体和客体的属性,你一定要检查一下如果某些属性缺失会怎么样。万无一失的行为要求拒绝访问,但通常情形不是这样的,你会觉得非常吃惊和不快。
3.6.4 特权
将你的注意力转到操作上,你可以收集以特权执行某些操作的权限。典型地,特权和操作系统功能相联系,并且涉及象系统管理、备份、邮件访问或网络访问等行为。你可以将特权看成是主体和操作之间的一个中间层(图3.9)。
图3.9
3.6.5 基于角色的访问控制
特权通常是和操作系统一起预先确定的。一组应用特定的操作(过程)称为一个角色,主体从它们履行的角色上获得访问权限。基于角色的访问控制(RBAC)将注意力集中在用户和用户执行的任务上。
主体和客体之间的中间层有助于减少管理访问控制的复杂性。中间层可被插入到多个位置上,这样你可以使用多个层次来构造访问控制。你的层次选择包括:
角色:一个角色就是一组过程,角色被分配给用户。一个用户可以有多个角色,多个用户也可以有相同的角色[134]。
过程:过程是语义比读或写更复杂的高层访问控制方法,过程只能被应用于某些数据类型的客体上。作为一个例子,考虑银行帐户之间的资金转移。
数据类型:每个客体属于一种特定的数据类型,只能通过为该数据类型定义的过程来访问。通过限制可以访问客体的过程来控制对客体的访问是一种常见的程序设计惯例。这是抽象数据类型理论的一个基本概念。
尽管这种结构化的访问控制是许多应用非常希望的,但是许多操作系统还不支持它。突出的例外是IBM AS/400[122]中的用户概述(profile)和Windows NT(第七章)中的全局组和本地组。RBAC更常见于数据库管理系统中。
3.7 安全级别的格(Lattice)
领会计算机安全的基本内容并不一定需要弄懂格,不过,在阅读了该课题的许多文献后却有助于理解格。象保护环或者VSTa的abilities一样,安全级别是另一种用来标记主体和客体的安全属性,是表达安全策略的基础。作为一个简单的例子,考虑四个线性排序的安全级别,“非机密的”(unclassified)、“机密的”(confidential)、“秘密的”(secret)和“绝密的”(top secret),如图3.10。强制性访问控制策略(MAC)和橙皮书中的多级安全策略指的是安全级别。下面,我们用L表示安全级别的集合。
图3.10
如果你坚持采用安全级别的线性排序,那么你只能表达有限的一组安全策略,因此最好能有一种更一般的排序结构可以使用。3.6.3引入的安全级别的部分排序(满足我们的部分要求,因为我们不要求L中每两个元素都是可比的。
我们的下一个要求是由标准的机密性策略引起的,仅当主体的安全级别高于客体的安全级别时,这个主体才可以查看这个客体。对以下两个问题我们希望有唯一的答案:
给定两个不同安全级别的客体,一个主体至少必须具有什么样的安全级别才能允许读这两个客体?
给定两个不同安全级别的主体,为使一个客体能被两个主体查看,该客体能够拥有的最高安全级别是多少?
能让我们回答这两个问题的数学结构已经有了,它称为格。格可被形式化地定义如下:
定义 格(L,()由集合L和部分排序(组成,对于自主两个元素a,b(L,存在一个最小上界u(L和一个最大下界l(L,也就是说
a(u,b(u,并且对所有v(L,( a(v ( b(v ) ( ( u(v )
l(a,l(b,并且对所有k(L,( k(a ( k(b ) ( ( k(l )
在安全中,如果a(b,我们说“a受控于b,或者“b控制a”。受控于所有其他级别的安全级别称为系统低,控制所有其他级别的安全级别称为系统高。
图3.11给出了格的一个典型例子。集合L是{a,b,c}的幂集(({a,b,c}),部分排序是子集关系(,系统低时集合为空集(,系统高时集合为{a,b,c}。子集关系通过一个图来描述,节点为(({a,b,c})的元素,节点间的箭头给出了部分排序的“构架”。准确地说,对于A,B((({a,b,c}),当且仅当A( B,A(B,并且不存在一个C((({a,b,c})使得A(C(B和A(C和B(C,我们置一个从A到B的箭头。
图3.11
有了这个约定后,那么,当且仅当从A到B存在一个箭头链时A是B的一个子集。本书中我们将采用这种形式的可视化部分排序。
格的下一个例子要引入一个在橙皮书及相关文档的多级安全策略中具有重要地位(坚固的,firm place)的结构,该结构将在第四章介绍。
令H为一个分类集合,其等级(线性)排序为(H;
令C为一个种类集合,如工程名字、公司部门、学院的系等等;
一个间隔就(compartment,隔室,隔箱;象限,舱)是一组种类;
一个安全标签(安全级别)就是一个二元组(h,c),其中h(H是一个安全级别,而c(C是一个间隔;
安全标签的部分排序(定义为:(h1,c1) ( (h2,c2) 当且仅当h1 (H h2和c1 ( c2。
图3.12说明了这种结构。有两个等级级别public和private,两个种类PERSONNEL和ENGINEERING。在产生的(ensuing,随后的(下一个))格中,以下关系成立:
(public,{PERSONNEL}) ( (private,{PERSONNEL}),
(public,{PERSONNEL}) ( (public,{PERSONNEL,ENGINEERING}),
(public,{PERSONNEL}) ( (private,{ENGINEERING})。
图3.12
有了这个安全标签的格,你就能够实现强制性的需要知道(最小特权)策略。为了说明这一点,按照上面提到的简单的机密性策略,看一下图3.12的格。具有安全标签(private,ENGINEERING)的主体将不能够读任何在其标签的隔间中种类为PERSONNEL的客体,因此,即使是标记为(public,{PERSONNEL,ENGINEERING})的客体也是不能读的。
我们从图3.10中简单的等级格来开始我们的安全格讨论并不是偶然的,等级格在政府部门的多级安全策略中是很典型的,并且这样的系统已经被构造出来以非常高的安全度执行这些策略,然后我们加入间隔来表达更多种类的策略。今天,我们看到使用多级安全系统的应用,因为这种系统安全度高,但在它们的安全级别中完全没有等级成分。比如,一种防火墙方法可以使用图3.13的格实现网络内部和外部的严格隔离,我们甚至不需要知道如何解释部分排序就可以作此声明。
图3.13
进一步的阅读
文献[1,39,125]介绍了基本的访问控制结构和安全格,早期较有影响的访问控制(保护)方面的论文是[82,131],[158]较详细地介绍了60年代开发的操作系统的访问控制,更多关于保护环安全策略的例子在[111,125]中。基于角色的访问控制的最新调查发表在[134],[133]中可以找到更多有关基于格的访问控制模型的信息,以及如何使用它们来处理机密性和完整性问题的描述。
有关QNX/Neutrino微内核和VSTa微内核的网页分别是:
http://www.qnx.com/literature/nto_sysarch/nto_sysarch.html,
http://www.zendo.com/vsta/vsta_intro.html。
练习题练习3.1 给你两个比特来获得目录上的访问操作,你如何使用四种可用的操作?你如何控制文件的创建和删除?你如何使用这些访问操作实现隐藏文件的概念?(隐藏文件只对授权主体是可见的。)
练习3.2 考虑一个具有读、写、准许和取消四种访问操作的系统,你可以使用准许grant来授予其他主体读和写的访问权限,你还可以使用准许grant来授予其他主体对你拥有的客体发布访问准许的权限。你准备使用什么样的数据结构和算法来实现准许和取消操作,以使你能够取消对你拥有的一个客体的所有访问?
练习3.3 讨论:组和角色之间的区别是什么,如果这种区别存在的话?
练习3.4 解释为什么3.6.3中定义的abilities的部分排序不构成格。尝试着在abilities集合中加入任何你需要的元素,将部分排序转换成一个格。
练习3.5 给你一个安全策略,规定当且仅当主体的安全级别控制客体的安全级别时,主体才能够访问客体。图3.14中的格与该策略一起使用的结果是什么?
练习3.6 令(L,()是一个安全级别的格,L是一个有限集合。证明在这样的格中一定存在唯一的系统低和系统高。
练习3.7 为安全级别public、confidential、strictly confidential和种类ADMIN、LECTURERS、STUDENTS构造安全标签的格。在一个需要知道策略中,哪一个客体对于一个具有(confidential,{STUDENTS})安全标签的主体是可见的?从n个安全级别和m个种类可以构造出多少标签?作为例子,考虑n=16,m=64。
练习3.8 给你一个安全策略,使用间隔格作为安全标签,仅当主体的标签是客体标签的一个子集时,访问才被准许。用种类ADMIN、LECTURERS和STUDENTS,哪一个客体可被一个具有标签{STUDENTS}的主体访问?为什么一个具有{ADMIN,STUDENTS}标签的主体比一个具有{STUDENTS}标签的主体受限制更多?说明标签(和{ADMIN,LECTURERS,STUDENTS}在该策略中的角色。
练习3.9 给你一组种类,实现一个基于格的需要限制策略,有选择地从主体收回访问权限。
第四章 安全模型
你的安全策略是什么?哪一条规则决定谁可以访问你的数据?为了制订一个安全策略,你必须描述策略控制的实体,并且陈述构成策略的规则。安全模型正是做这样的事情。本章建立在前一章的基础上,研究一些最有影响力的安全模型。
安全模型为机密性(如Bell-LaPadula)和完整性(如Biba,Clark-Wilson)寻找策略。有些模型适用于策略为静态的环境(Bell-LaPadula),其他一些模型则考虑访问权限的动态变化(Chinese Wall,中国墙)。形式化的安全模型,象Bell-LaPadula,在高保险度安全评估中具有突出地位。非形式化模型,象Clark-Wilson,更大程度上是一种表达安全策略的描述性框架。
目标说明如何用形式化方法来表示安全策略。
介绍计算机安全历史上几个重要的里程碑。
了解不同安全模型的范围和局限性。
理解安全中的一些决策问题本质上是不可判定的。
4.1 状态机模型
状态机(自动机)是为计算系统的许多方面建立模型的一种流行工具,我们假设本书读者已经熟悉了这方面的内容。毫不奇怪,状态机也是一些重要的安全模型的基础。状态机模型的主要特点是状态以及发生在离散时间点上的状态变化的概念。状态就是所研究的系统在某个时刻的一种表现,它能准确捕捉(capture,记录;以影片、文字等保存原状)与我们的问题相关的那些系统方面。可能的状态迁移(转换,transition)可以通过状态迁移(下一个状态)函数来描述,该函数根据当前状态和输入来定义下一个状态,也可能产生出一个输出。
如果我们想用状态机模型来讨论系统的某个特殊性质,如安全,我们首先必须确定达到该性质的所有状态,然后必须检查是否所有的状态迁移保持这种性质。如果是这样,并且系统是从满足这种性质的起始状态开始运行的,那么我们可以通过推理证明这个性质总是成立的。
4.2 Bell-LaPadula模型
在安全系统的设计和分析中安全模型是一个重要的概念,它们体现了系统中应该执行的安全策略。Bell-LaPadula模型(BLP)可能是最著名的安全模型,它由Bell和LaPadula在第一次联合设计安全的多用户操作系统时提出。BLP是描述访问控制的机密性问题的状态机模型,访问许可通过访问控制矩阵和安全级别来定义,安全策略防止信息从高安全级别流向低安全级别,这些策略一般地被称为多级安全(MLS)。BLP只考虑了主体在查看或改变一个客体时发生的信息流动。我们对BLP模型的描述从以下集合开始:
主体集合S;
客体集合O;
访问操作集合A = {execute,read,append,write},直接借鉴了3.3.2的访问权限;
具有部分排序(的安全级别集合L。
我们想用系统的状态来检查系统安全,因此,模型的状态集必须包括当前所有的许可和当前所有主体访问客体的实例。这导致了一个相当复杂的状态集B(((F,其中
B = P(S(O(A)是当前访问的集合。元素b(B是一组三元组(s,o,a),表示主体s当前正在客体o上执行操作a。
(是访问许可矩阵M = (Mso) s(S,o(O的集合。
F( LS(LS(LO是安全级别分配的集合。元素f(F是一个三元组(fS,fC,fO),其中
fS,S→L给出了每个主体可以拥有的最高安全级别,
fC,S→L给出了每个主体当前的安全级别,
fO,O→L给出了所有客体的分类。
一个主体的当前级别不能高于它的最高级别,因此fC(fS,读作“fS控制fC”,很快你会看到引入fC的原因。最高安全级别有时候称为主体的许可(clearance),其他文献只用许可来表示用户的安全级别。
定义状态集是BLP的主要问题,我们不需要描述输入、输出或者状态迁移的精确结构来给出BLP的安全特性。
4.2.1 安全策略
BLP将安全定义为状态特性。多级安全策略仅当主体的安全级别控制客体的分类时允许主体读这个客体,这些多级安全策略也称为强制性安全策略(mandatory security policies)。第一个显而易见的特性是简单安全性(ss-property):
ss-property 如果对于每一个元素(s,o,a)(b,访问操作a是读或写,主体s的安全级别控制客体o的分类,即fO(o) (fS(s),那么状态(b,M,f)满足ss-property。从这个特性获得(capture,俘[捕]获,捕捉)了传统的无向上读安全策略(no read-up security policies)。
然而,ss-property不足以防止一个低级别的主体读一个高级别客体的内容。可以创建一个高级别的特洛伊木马,读高级别的客体并将它拷贝(写它的内容)到一个低级别的客体。因此,我们还必须通过(-property(星特性)控制写访问:
(-property 如果对于每一个元素(s,o,a)(b,访问操作a是添加或写,主体s的当前级别被客体o的分类所控制,即fC(s) (fO(o),那么状态(b,M,f)满足(-property。这是一个无向下写安全策略(no write-down security policies)。此外,如果存在一个元素(s,o,a)(b,访问操作a是添加或写,那么对于所有的客体o',(s,o',a')(b,a'是读或写,我们必须有fO(o') (fO(o)。
这个定义清楚地表明高级别的主体不能发消息给低级别的主体。有两种方法可以避开这个限制:
临时地降低一个高级别主体的等级,这是引入当前安全级别fC的原因。
确定一组允许违背(-property的主体,这些主体称为可信主体(trusted subjects)。
第一种方法假设一个主体被降级时,它忘记了它在较高安全等级上所知道的一切。当你把主体看成人时,这个观点看起来不合情理,但BLP是模拟计算机的,这里主体(进程)没有自己的记忆,它们所“知道”的唯一事情是它们被允许查看的客体(文件)的内容。在这种情况下,临时降级确实解决了问题。
换句话说,fS规定了用户的许可,用户允许以低于许可的级别注册,fC表明了用户实际注册的级别。
当采用第二种方法时,(-property只对不可信的主体有效。按定义,一个可信主体可以违背安全策略。事实上,为集中注意力,你可以很好地用形容词“可信的”来识别那些会伤害你的系统组件。相反,如果你确信一个主体不会伤害你,那么称它为值得信赖的。
橙皮书使用术语自主性(自主)访问控制(discretionary access control,DAC)来表示那些基于指定的用户和指定的客体的访问控制策略,拥有一项访问许可的主体可以将许可传递给其他主体。在BLP中,这种策略通过一个访问控制矩阵表示,并通过自主性安全特性(ds-property)获得。
ds-property 如果对于每一个元素(s,o,a)(b,我们有a(Mso,那么状态(b,M,f)满足ds-property。
如果一个状态满足所有三种安全特性,这个状态则被称为是安全的。
4.2.2 基本安全定理
如果状态v1 = (b1,M1,f1)和状态v2 = (b2,M2,f2)都是安全的,那么称从状态v1到状态v2的迁移是安全。为了弄清楚需要进行什么样的检查才能确定一个新状态是安全的,考虑ss-property例子。状态迁移保持ss-property,当且仅当:
每个(s,o,a)(b2\b1满足关于f2的ss-property;(b2\b1表示b2和b1的差集)及如果(s,o,a)(b1不满足关于f2的ss-property,那么(s,o,a)(b2。
(-property和ds-property特性的保持可以用类似的方法来描述。现在我们能够描述BLP模型的一个重要特性。
基本安全定理 如果系统中所有的状态迁移都是安全,并且系统的初始状态也是安全的,那么不管输入情况如何,其后的每一个状态也都是安全的。
该定理的形式化证明通过对输入序列的长度作归纳来进行。证明建立在这样的事实上,即每个状态迁移保持安全,且不引用特定的BLP安全特性。
基本安全定理是状态机模型的产物,而不是BLP模型中选用的特定安全特性的结果。
实际上,基本安全定理减少了检验系统安全所需的努力。你可以分别地检查每一个状态迁移证明它保持了安全性,并且需要确定一个安全的初始状态。只要你以这种安全的初始状态启动系统,它将一直是安全的。
4.2.3 稳定
McLean在1987的一篇文章[96]中提出了一种包含以下状态迁移的系统,从而引发了一场关于BLP模型的价值的激烈讨论:
将所有的主体降到最低的安全级别,
将所有的客体降到最低的安全级别,
在访问控制矩阵M的所有位置输入全部的访问权限。
按照BLP的定义,这个迁移到达的状态是安全的。但这种状态能被视为是安全的吗?因为BLP是这么说的,因此BLP正确地抓到安全了吗?有两种意见:
反对BLP的(McLean):直观地说,如果一个系统能被带入到一种允许每个人读任何信息的状态,那么这个系统是不安全的。因此,BLP必须改进。
赞成BLP的(Bell):如果用户要求这种状态迁移,那么应当在安全模型中允许这种状态迁移。如果它不被要求,那么就不应该去实现它。这不是BLP的问题,而是正确获取安全需求的问题。
争论的根源是改变访问权限的状态转移。这种改变在BLP的一般性框架中当然是可能的,但是模型的组织者实际上考虑的是访问权限固定的系统。安全级别和访问权限从不改变的这种特性称为稳定性(tranquility),不改变访问权限的操作称为是稳定的(tranquil)。
4.2.4 BLP的各个方面及其局限性
BLP是一个非常重要的安全模型,它在安全操作系统的设计中起着重要的作用,而且几乎任何一种新的模型都要和BLP相比较。在这种情形下,分析BLP的一些特征是很有好处的。
模型的描述能力:BLP状态集描述了当前所有的访问操作和访问许可。
安全策略是以安全级别和访问控制矩阵为基础的,在这些地方很容易引入其他结构。比如这样一个情形,主体只允许通过某些程序来访问客体,要建立这样一个访问控制模型,S(S(O访问控制结构更为合适。
实际的安全特性:在BLP中,我们有ss-property,(-property和ds-property。Biba模型(见4.5)和BLP模型的主要区别在于安全特性。
特殊解决方案:比如,Multics说明(见5.4.3)中的状态迁移。
BLP用访问控制来定义安全性是它深受欢迎的一个主要原因。因此,用BLP来表示操作系统或数据库管理系统的行为是不太困难的。然而,尽管它是一个重要的安全模型,BLP没有涵盖安全的所有方面。对它的批评有:
只涉及机密性,而没有涉及完整性,
没有解决访问控制的管理问题,
包含隐蔽通道。
缺乏完整性策略是BLP的一个特征,而不是一个缺陷。你很快将会看到,对于一个安全模型来说,限制它的目标是非常合理的。BLP没有针对修改访问权限的策略,事实上,BLP最初打算用于没有安全级别改变的系统。
隐蔽通道就是一个不受安全机制控制的信息流[150]。如果低级别的主体可以看见高级别客体的名字,而只被拒绝访问客体的内容,那么客体的名字就是一个明显的隐蔽通道。在BLP中,你可以用访问控制机制本身构造一个隐蔽通道,信息可以像下面所示的那样从一个高安全级别流向一个低安全级别:
一个低级别的主体在本级别上创建一个客体dummy.obj。
它的高级别同谋(一个特洛伊木马?)提高或者不改变dummy.obj的安全级别。
过后,低级别主体试图读dummy.obj。该请求的成功或失败暴露了高级别主体的行为,一比特的信息从高级别流向了低级别。
告诉一个主体某个操作是不允许的,这就构成了信息流。这导致了数据库安全中有趣的解决方案(多实例化),一个客体在不同的安全级别上可能有不同的值,从而避免这类问题的发生(第十五章)。
有时,仅仅隐藏客体的内容是不够的,可能也必须隐藏它们的存在。
4.3 Harrison-Ruzzo-Ullman模型
Bell-LaPadula模型没有就改变访问权限或创建、删除主体与客体规定策略,Harrison-Ruzzo-Ullman(HRU)模型定义了解决这些问题的授权系统[64]。为描述HRU模型,我们需要:
一个主体集合S,
一个客体集合O,
一个访问权限集合R,
一个访问矩阵M = (Mso) s(S,o(O;元素(表目,entry)Mso是R的子集,说明了主体s对客体o拥有的权限。
有六种原语操作用于处理主体集、客体集和访问矩阵:
enter r into Mso
delete r from Mso
create subject s
delete subject s
create object o
delete object o
HRU模型中的命令有以下格式:
command c(x1,…xk)
if r1 in Ms1,o1 and
if r2 in Ms2,o2 and
if rm in Msm,om
then
op1
op2
opn
end
下标s1,…sm和o1,…om是参数表(x1,…,xk)中出现的主体和客体。条件列表检查特定的访问权限是否出现,条件列表可以为空。如果所有的条件成立,那么基本的操作序列被执行。每个命令至少包含一个操作,比如命令
command create_file(s,f)
create f
enter o into Ms,f
enter r into Ms,f
enter w into Ms,f
end
由主体s用来创建一个新的文件f,s是文件的所有者(访问权限o),并且对文件有读和写的许可(访问权限r和w)。文件f的所有者s用以下命令将读访问授予另一个主体p:
command grant_read(s,p,f)
if o in Ms,f
then enter r in Mp,f
end
命令的结果作为访问矩阵的变化被记录下来,因此访问矩阵描述了系统的状态,习惯上用M'表示修改后的访问控制矩阵。HRU模型能够获得控制访问权限分配的安全策略。为了验证一个系统符合这种策略,你必须证明不存在颁授不希望的访问权限的情况。
定义 称一个状态(即访问控制矩阵M)泄露了权限r,如果存在一个命令c将权限r加到了访问矩阵中一个原先不包含r的位置上。更正式地说,存在s和o,使得r( Ms,o和r( M's,o。
定义 称一个状态(即访问控制矩阵M)关于权限r是安全的,如果没有一个命令序列能够将M变换到泄露r的状态。
因此,在HRU模型中验证符合一个安全策略归结为验证安全特性,但是你发现你现在处于一个非常不容乐观的位置。
定理 给定一个访问矩阵M和一个权限r,验证M关于权限r的安全性是一个不可判定的问题。
因此,你不能一般性地解决安全问题,而必须通过约束模型来获得更好的成功机会。比如,你可以只允许单操作命令,即包含单一操作的命令。
定理 给定一个单操作的授权系统、一个访问矩阵M和一个权限r,验证M关于权限r的安全性是一个可判定的问题。
你只需允许每个命令包含多至两个操作就可使安全问题重新变得不可判定。限制授权系统的大小是使得安全问题易于处理的另一种方法。
定理 如果主体的数量是有限的,那么自主授权系统的安全问题是可判定的[89]。
这些关于安全问题可判定性的结论约略解释了第三条设计原则。如果你设计的复杂系统只能用复杂的模型来描述,那么要找到安全证明是困难的,在最坏情况下(不可判定性)不存在一个验证所有问题实例安全性的通用算法。如果你想要可验证的安全特性,最好限制安全模型的复杂性。这样的模型可能无法描述所有希望的安全特性,但是你可以获得有效的验证“安全性”的方法。因此,设计能够用简单模型充分描述的简单系统是明智的。如果系统和模型间存在太大的差距,模型中的安全证明就不太重要了。
安全模型的表达能力越强,包括安全特性和它能够描述的系统,验证安全特性通常也越困难。
4.4 中国墙模型
Brewer和Nash提出的中国墙模型模拟了咨询公司的访问规则,分析员必须保证他们与不同客户(公司)的交易不会引起利益冲突[23]。通俗一点说,冲突的产生是因为客户是同一个市场的直接竞争者或者是不同公司的所有者。分析员必须遵循以下安全策略:
规则 一定不能有引起利益冲突的信息流。
Bell-LaPadula模型的状态集需要一些小小的调整来实现这个策略:
公司的集合用C表示。
客体集合O是有关一个公司的信息条目。显然,分析员是主体,而S是主体的集合。
有关同一个公司的所有客体集中在一个公司数据集(dataset)中,函数y,O(C给出了每个客体的公司数据集。
利益冲突组指出哪些公司在相互竞争,函数x,O(P(C)给出了每个客体的利益冲突组,即不应该知道该客体内容的公司集合。
客体o的安全标签是(x(o),y(o))。
净化的信息被去除了敏感的细节,不受访问限制的控制。对于一个被净化的客体o,我们设x(o)=(。
利益冲突的产生不仅与当前访问的客体有关,也与过去访问过的客体有关,因此我们需要一种记录主体行为历史的方法。为此目的,我们引入了一个布尔矩阵N=S(O,其中
Ns,o =
如果你对于所有的s(S和o(O置Ns,o = false,你将得到一个安全的初始状态。
第一个安全策略涉及直接信息流。我们希望防止一个主体遭受利益冲突,因此仅当被请求的客体属于以下两种集合时访问才被允许:
用户已经拥有的一个公司数据集,或者一个完全不同的利益冲突组。
我们可以将它正式地表示成ss-property,如下:
ss-property 主体s允许访问客体o,仅当对于所有Ns,o' = true的客体o',有y(o)(x(o')或y(o)=y(o')。
该特性本身没有完全实现规定的安全策略,仍有可能发生间接信息流。考虑下面的例子。两个竞争者,A公司和B公司,在同一家银行开有帐户;处理A公司与银行业务的分析员A,用A公司的敏感信息更新银行资产负债表;处理B公司与银行业务的分析员B,现在可以访问到竞争者的经营信息。因此,我们引入(-property来控制写访问。
(-property 主体s允许对客体o进行写访问,仅当s对于y(o)(y(o')和x(o')((的客体o'没有读访问权。
仅当没有其他的位于不同公司数据集且包含非净化信息的客体能被阅读时,对一个客体的写访问才是允许的。
与访问权限通常假设为静态的BLP不同,我们现在面对的是一个在每次状态迁移中访问权限都要重新检查的模型。
4.5 Biba模型
Biba模型[19]使用一种非常类似于BLP的状态机模型,从主体访问客体这个角度来处理完整性问题。有一个完整性级别的格(L,(),函数fs,S(L和fo,O(L将完整性级别赋给主体和客体。这些级别构成了表达完整性策略的基础,完整性策略解决“干净的”高级别实体被“脏的”低级别实体污染的问题。在完整性的格中,信息只能向下流动。和BLP只有一个高级别完整性策略不同,在此你会看到有很多种方法,有些方法甚至产生出互不兼容的策略。
4.5.1 静态完整性级别
对应BLP的稳定性特性,我们可以规定完整性级别不变的策略,以下两个完整性特性是强制性BLP策略的对偶。
简单完整性特性:如果主体s可以修改(改变)客体o,那么fs(s)(fo(o)。(No write-up)。
完整性星特性:如果主体s可以读(查看)客体o,那么仅当fo(p)(fo(o),s可以写访问另一个客体p。
这两个策略防止干净的主体和客体被脏的信息污染。
4.5.2 动态完整性级别
类似于中国墙模型,下面两个完整性特性自动调整一个实体的完整性级别,如果该实体已经接触了低级别的信息。
主体低水印特性:主体s可以读(查看)任何完整性级别上的客体o,主体的新的完整性级别是inf(fs(s),fo(o)),其中fs(s)和fo(o)是操作前的完整性级别。 注释:Inf,下确界客体低水印特性:主体s可以修改(改变)任何完整性级别上的客体o,客体的新的完整性级别是inf(fs(s),fo(o)),其中fs(s)和fo(o)是操作前的完整性级别。
完整性级别inf(fs(s),fo(o))(fs(s)和fo(o)的最低下限)是良(完全地,well)定义的,因为我们处理的是完整性级别的格。
4.5.3 调用的策略
可以扩展Biba模型以包含访问操作调用(invoke)。主体可以调用另一个主体(如一个软件工具)来访问一个客体,这是向在中间层上表达访问控制迈出的第一步。应当用什么样的策略来控制调用?我们想确保调用不会绕过强制性的完整性策略吗?那么,我们可以加入调用特性:主体s1可以调用主体s2,仅当fs(s2)( fs(s1)。
主体只允许在较低级别上调用工具,否则的话,一个脏的主体就能用一个干净的工具去访问和污染一个干净的客体。
另一种情况,我们可能就想为此目的而使用工具。脏的主体应该可以访问干净的客体,只要它使用一个干净的工具来访问,这个工具可以执行许多一致性检查,确保客体仍然保持干净。在这种情形下,我们可能不希望干净的主体使用脏的工具,我们可以采用
环特性:主体s1可以读任何完整性级别上的客体,它只能修改fo(o)(fs(s)的客体o,并且仅当fs(s1)( fs(s2)时可以调用主体s2。
很显然,最后两个特性是不一致的,我们必须根据应用来决定哪种特性更合适。
4.6 Clark-Wilson模型
Clark和Wilson研究商务应用的安全性需求[32]。他们认为这些需求主要是关于数据完整性的,即防止未授权的数据修改、欺骗和错误。这是一个相当广泛的完整性定义,事实上,作者甚至包括了并发控制的问题,该问题超出我们的安全范围。完整性要求被分成两部分:
内部一致性:涉及系统内部状态的特性,可通过计算系统实施;
外部一致性:涉及系统内部状态和真实世界的联系,必须通过计算系统以外的手段来实施,如审计。
实施完整性的一般机制是:
组织良好的事务:数据项只能通过一组特定的程序来操作;用户可以访问程序而不是数据项;
责任分离:用户必须协同起来才能操作数据和穿透(collude to penetrate)安全系统。
责任分离在一个安全系统的操作中反复出现。要求不同的人开发、测试、证明和运作一个系统是合理的。反过来,也可能要求不同的人在操作中必须协同工作才能实现一个事务。
Clark-Wilson模型用程序作为主体和客体(数据项)之间的中间控制层,主体被授权执行某些程序,数据项可通过特定的程序访问。定义可以访问某个特定类型数据的程序集是软件工程的一种常用机制(象在抽象数据类型[39]和面向客体程序设计中),这种机制可以被卓有成效地运用到构造安全的系统中。Clark和Wilson写到“用程序而不是安全级别来标记主体和客体”,这是对BLP影响力的一个有力证明。在Clark-Wilson模型中,完整性意味着:
被授权将一个程序应用到可以被该程序访问的一个数据项上。
Clark和Wilson强调了军事安全与商业安全要求之间的区别,观察表明机密性和完整性的相对重要性在这两个世界中是不同的,但是也存在着有完整性要求的军事应用和有机密性要求的商业应用。对我们来说,还有一个更相关的区别,Clark-Wilson模型中的访问操作是执行复杂的特定应用操作的程序,而BLP中的访问操作是简单的、通用的和适合操作系统的,因此我们看到了通用操作系统(BLP)和面向应用的IT系统(Clark-Wilson)之间的区别。总的说来,Clark-Wilson模型考虑以下几点:
主体必须被识别和认证。
客体只能通过一组规定的程序进行操作。
主体只能执行一组规定的程序。
必须维护一个正确的审计日志。
系统必须被证明能够正确工作。
在该模型的形式化描述中,安全策略所控制的数据项称为约束数据项(CDIs),系统输入作为非约束数据项(UDIs)。UDIs到CDIs的转换是系统的一个关键部分,它不能光靠系统中的安全机制来控制。CDIs只能通过变换程序(TPs)来操作,状态的完整性通过完整性验证程序(IVPs)来检查。
安全特性是通过五条证明(certification,认证,【软】证明,确证;说明书)规则定义的,这些证明规则说明了为使安全策略符合应用需求而应该执行的检查。
IVPs必须确保当IVP运行时所有CDIs处于一种有效状态。
TPs必须被证明是有效的,即有效的CDIs必须总是被变换成有效的CDIs。每个TP被获准访问一组特定的CDIs。
访问规则必须满足任何责任分离要求。
所有TPs必须写入到一个只能添加的日志中。
任何一个接受UDI作为输入的TP,或者必须将UDI转换成CDI,或者必须拒绝该UDI,并且不进行任何变换。
四条实施规则描述了应执行安全策略的计算机系统其内部的安全机制,这些规则同BLP中的自主性访问控制有些类似。
系统必须维护和保护(Tpi:CDIa,CDIb,…)列表,该列表给出了TP获准访问的CDIs。
系统必须维护和保护(UserID,Tpi:CDIa,CDIb,…)列表,该列表规定了用户可以执行的TPs。
系统必须认证每一个请求执行某个TP的用户。
只有一个可以授予TP访问规则的主体才能修改列表中相应的表项,这个主体必须不能拥有在该TP上的执行权限。
最后提请注意,Clark-Wilson模型实际上是设计安全策略的一个框架和指导方针(“模型”),而不是一个特定安全策略的模型。
4.7 信息流模型在Bell-LaPadula模型中,信息可以通过隐蔽通道从一个高安全级别流到一个低安全级别。信息流模型考虑任何形式的信息流,而不光是由BLP模拟的通过访问操作的直接信息流。非正式地,如果我们能够通过观察y获得更多关于x的信息,状态迁移即引起从客体x到客体y的一个信息流。如果我们已经知道了x,那就没有信息能从x流出。你可以区分以下两种情况:
显式信息流:在赋值y:=x后查看y,可以获得x的值;
隐式信息流:在条件语句if x=0 then y:=1后查看y,可以获得有关x的一些信息,即使赋值y:=1没有被执行。比如,如果y=2,你知道x(0。
精确和定量的信息流定义可以用信息论的观点给出,从x到y的信息流用给定y的值后x的条件信息量平均值(条件熵)的变化来度量。信息流模型的组成部分是:
一个安全标签的格(L,(),
一组加了标签的客体,
安全策略:仅当c1( c2时允许从标签为c1的客体到标签为c2的客体的信息流;任何违反该规则的信息流是非法的。
如果没有非法的信息流,系统就被称为是安全的。这种模型的好处是它保护了所有类型的信息流,其缺点是设计安全的系统变得更加困难。比如,已经证明要检查在信息流模型中一个给定的系统是否安全,是一个不可判定的问题。
此外,我们必须区分信息流策略的静态和动态实施。在第一种情形下,系统(程序)被看成是一个静态客体。第二种情形考虑执行中的系统。我们可能发现有些信息流在理论上是可能的(因此应当在静态分析中检测),但却永远不会在执行过程中发生,因此静态分析趋向于生成限制性太强的系统。
不干扰模型是信息流模型的替代方案,它们提供了一种不同的形式(formalism,形式方法,形式论(拘泥形式,体系))来描述主体所知道的系统状态。如果s1的行为对s2的系统视图没有影响,那么主体s1不干扰主体s2。目前,信息流和不干扰模型只是研究领域,而不是设计安全系统的实用方法论基础。
进一步的阅读
安全模型常被看成是形式化的安全策略,这个定义假设我们知道安全策略意味着什么。安全策略可以满足一个企业的安全需求,或者描述为获得安全性必须采取的措施。关于术语安全策略的不同含义的讨论在[147]中给出,商业机构安全策略定义的最新进展在[143]中有适当的描述,风险分析的实际问题见[31]。
要调研安全模型方面的文章,请看[83]和[98],它们相隔了十年。Bell-LaPadula模型的最初报告最近在Journal of Computer Security[12]上重新发表了,在Bell-LaPadula模型中改变访问权限的策略框架在[97]中有讨论。很多研究论文在扩展BLP模型的范围而仍然实施其MLS策略方面作出了贡献。Clark和Wilson的最初论文是大力推荐的读物[32],[75]描述了一种用能力来实现Clark-Wilson模型的实现方法,[87]提出了一种可提供强制性的完整性控制并可用于实现Clark-Wilson模型的Biba模型的一种扩展。
HRU模型和信息流模型的可判定性特性的详细介绍,包括定义、证明和更多的理论,请参见[39]。对于不干扰模型,请参考Goguen和Meseguer的论文[58]。
练习题练习 4.1 用基本访问模式alter和observe描述(-property。
练习 4.2 写一篇短文表明你在Bell和McLean争论中的立场。
练习 4.3 Bell-LaPadula没有规定改变访问权限的策略,你会建议什么样的策略?
练习 4.4 你能将中国墙模型放入Bell-LaPadula框架吗?
练习 4.5 中国墙模型中的(-property应当只指当前的读访问还是指任何过去的读访问?
练习 4.6 Biba模型可以获得很多完整性策略,举出以下策略适合的应用领域的例子:
具有静态完整性标签的策略,
具有动态可变完整性标签的策略,
环特性练习 4.7 你能够用Bell-LaPadula和Biba同时建立机密性和完整性模型吗?你能在两个策略中使用相同的安全性标签吗?
练习 4.8 给出一个描述Clark-Wilson实施规则的形式化模型。
练习 4.9 为30年后解密的文档设计一个安全模型。
练习 4.10 在一个控制对病历和处方访问的医疗信息系统中:
医生可以读写病历和处方,
护士只能读写处方,但是不应当知道病历的内容。
你如何在格模型中得到这个策略,防止信息从病历流到处方?依你看哪一种安全模型最适合这种策略?
第五章 安全内核
你已经被分配了要在一个IT系统中实现“安全性”的任务。前两章已经给了你一个包括设计访问控制策略不同选项的菜单。然后你又研究了你的应用,并且决定了最合适的访问控制结构和安全模型。现在你怎样开始实现你选择的保护机制呢?在我们的分层系统模型框架中,你必须回答两个问题:
访问控制应该位于什么地方?
你的方案迫使你考虑附加的保护要求吗?
本章研究分层模型中最低两层的安全机制。
目标理解主张在系统的低层次上实现安全性的原因。
对于在系统的低层次上可以利用的安全机制有一个全面的了解。
引入身份和控制调用作为两个重要的安全原语。
弄清(理解;领会,see)怎样用安全模型来分析安全内核(security kernel)。
5.1 基本原理
有两个很好的理由将安全性置于系统的较低两层之一(图5.1)。如果攻击者从下面的层次进入,任何给定层上的安全机制将会受到损害。因此,为了评价系统的安全性,你必须证明你的安全机制不会被绕过。你的系统越复杂,这个证明就越困难。在系统的核心上,你有希望找到相当简单的能够经得起全面分析的结构。这个论点指向了将安全置于核心的第一个理由。
安全评价达到一个较高的可靠程度是可能的。
微处理器的设计就是确定哪组操作对于大多数用户是最有用的科学。正确的选择以及通用操作的有效实现决定了整体的性能。在实现安全性时你可以使用同样的方法,确定通用安全机制,并将它们置于系统的核心。这是将安全置于核心的第二个理由。
图5.1
图5.2
将安全机制置于系统的核心减小了由安全引起的性能开销。
本章以Motorola 68000和Intel 80386/486为例查看微处理器的安全特性,然后考虑Multics操作系统的引用监视器。它包括置于人-机标尺(图5.2)上机器这一端的安全机制。在本书的后面部分,我们将向上移动穿过各个层次,举例介绍由操作系统提供的安全机制(第六、七章),和由软件服务(中间件)提供的安全机制,象数据库管理系统(第十四章)。
5.2 操作系统完整性
计算机安全中有三个紧密相关易于混淆的基本概念,应当将它们区分开来。我们用橙皮书[112]中的词汇表作为我们定义的参考。
引用监视器:这是一个访问控制的概念,指一个对所有由主体对客体的访问进行仲裁的抽象机器。
安全内核:实现引用监视器概念的可信计算基的硬件、固件和软件元素。安全内核必须仲裁所有的访问,必须被保护不被修改,并可证明是正确的。
可信计算基(TCB,Trusted Computing Base):一个计算机系统中的全部保护机制(包括硬件、固件和软件(它们结合起来负责实施一项安全策略。一个TCB包含一个或多个部件,在一个产品或系统中实施统一的安全策略。TCB正确实施安全策略的能力完全依赖于TCB内部的机制,以及系统管理员对于安全策略相关参数(如用户许可)的正确输入。
因此,引用监视器是一个抽象的概念,安全内核是它的实现,而TCB包含了安全内核以及其他保护机制。图5.1最低两层中的安全机制大致对应了安全内核。保持一个操作系统的安全内核尽可能简单,对于安全的操作系统的设计与评估是至关重要的。有些文献将TCB和实现类似BLP策略的安全内核几乎视为同义,但是你从定义可以看到,这不是橙皮书作者的意图。
我们提出的支持将安全机制置于系统核心的所有论据将我们推向人-机标尺的机器一端,其结果是可想而知的。
由安全内核作出的访问控制决定和由应用作出的访问控制决定是分开的。
现在让我们概括地确定一下要包含在安全内核中的安全机制。假设你有一个操作系统能够实施你所有的访问控制策略,只要操作系统象我们所预期的那样运作,对资源的非授权访问是不可能的。当然,这正是对攻击者的暗示。为了避开你的保护机制,攻击者可能试图通过修改操作系统使安全控制失去能力。无疑你现在面临的是一个完整性问题,即使你一开始关心的是机密性。操作系统不仅是访问请求的裁决者,它本身也是一个访问控制的客体。新的安全策略是:
规则 用户一定不能修改操作系统。
这是一个通用的安全策略,应该得到坚强和有效的支持。更为困难的是,你必须解决以下两个相互抵触的要求:
用户应能使用(调用)操作系统。
用户不能滥用操作系统。
通常用于实现这些目标的两个重要概念是身份信息和控制调用(也称为有限特权)。这些概念可被用于计算系统的任一层次上,可以是应用软件、操作系统或硬件。但是再次强调,如果攻击者获得对较低层次的访问,这些机制可能会失去作用。
5.2.1 操作模式
操作系统能够保护自己不受用户侵害的第一个必备条件是能够区分“代表”操作系统的计算和“代表”用户的计算。身份标志可用来表示这个意思,允许系统工作在不同的模式。以下两个例子在处理器级上解释了这一点。
Motorola 68000:一个身份比特使得可以区分用户模式和超级用户(系统)模式。
Intel 80386:两个身份比特导致四种模式。
Unix操作系统能够区分超级用户(根)模式和用户模式。
为什么这些模式有用呢?比如,为阻止用户直接写内存和破坏逻辑文件结构,操作系统可以仅在处理器工作于超级用户模式时准许对存储位置进行写访问。
5.2.2 控制调用
继续我们的例子,用户想执行一个要求超级用户模式的操作,如写一个存储位置。为处理这个请求,处理器必须转换模式,但是这种转换应当如何执行呢?简单地将身份比特改到超级用户模式会把与该模式相关联的所有特权都赋予用户,但对用户实际做些什么却没有任何控制。因此,理想的做法是系统在超级用户模式只执行一组预先定义的操作,而在将控制交回给用户前返回用户模式。我们称这个过程为控制调用。
5.3 硬件安全特性
在我们的模型中,硬件是IT系统的最低层,硬件也是计算机安全可与物理安全相联系的地方,因此,硬件级的安全机制是我们研究的自然起点。我们假设读者已经熟悉了计算机体系结构的基本概念,如必要的话,这些背景知识可从象[38,66]的教科书得到。
5.3.1 计算机体系结构的简单概述
就我们的目的而言,用图5.3给出简单的计算机示意性描述就可以了。计算机由一个中央处理单元(CPU)、存储器和连接CPU和存储器的一条总线构成。在现实世界中,所有这三个实体都有非常精细的结构。
图5.3
中央处理单元
核心的CPU部件是:
算术逻辑单元(ALU):执行用机器语言给出的指令;指令执行后可能会在状态寄存器中置位。
寄存器:有通用寄存器和专用寄存器。
重要的专用寄存器是:
程序计数器:指向包含了下一条要执行指令的内存位置;
栈指针:指向系统堆栈的栈顶;
状态寄存器:允许CPU保存重要的状态信息。
系统堆栈是内存中一块特别指定的部分,堆栈可以通过将数据压入栈顶或从栈顶弹出数据来进行访问。为了在不同的进程间切换,CPU执行上下文切换操作,并在将控制交给新进程前将当前进程的状态,如程序计数器、状态寄存器等保存在堆栈中。
已经警告过你抽象的危险性,堆栈是另一个“万一”的例子。在讨论抽象时,可以合理地假设堆栈大小是无限的,但是一个具体的实现肯定会为堆栈分配固定大小的内存区。如果允许堆栈超出它的最大尺寸,安全问题就可能发生,实际上已经发生过,并且今后还会发生。
存储结构
在以下简短的综述中,我们对不同存储结构的安全特性尤其感兴趣。我们有:
RAM(random access memory):这是读/写存储器;你必须考虑完整性和机密性问题。
ROM(read-only memory):你只需要考虑机密性问题;ROM可能是存储(部分)操作系统的好地方。
EPROM(erasable and programmable read-only memory):可用于存储部分操作系统或加密密钥;技术上更复杂的攻击可能会对安全造成威胁。
WROM(write-once memory):与这种存储结构相伴随的一种机制允许你一次性固化存储内容;在硬件中这可以通过熔断写线上的熔丝来做到,但是你还可能遇到“逻辑熔丝”;WROM可能是存储密钥的一个好地方;只写磁盘正被用于记录审计踪迹。
进一步还可以区分易失性存储器和非易失性(永久性)存储器。易失性存储器当断电时会丢失内容,在物理上这个过程既不是瞬间的也不是完全的。如果断电后立即接上电源,老的数据还可能保留在存储器中。即使电源被关闭了一段时间,老的存储内容仍然有可能通过特殊的电子技术被恢复。为了抵抗这些攻击,存储器必须用合适的取决于存储介质的比特模式重复地改写[113]。
永久性存储器在断电时仍然保持其内容。如果敏感数据(如加密密钥)存放在永久存储器中,并且攻击者能够绕过CPU直接访问存储器,那么必须实现象密码保护或物理保护等进一步的措施。比如将一个光传感器放置在一个防篡改模块中,以检测某些操作企图并触发对模块中存储内容的删除。物理保护本身就是一个研究课题,它不在本书讨论的范围之内。我们将注意力集中在用户只能通过CPU访问内存的情形,我们研究CPU如何能实现机密性和完整性。比如,如何能够防止计算机病毒用一个受感染的操作系统版本改写一个干净的操作系统版本。
有一点很重要,就是要提醒自己图5.3中的“存储器”是另一个抽象。逻辑上,存储器可能由主存储器、高速缓冲存储器和缓冲器等组成,即使是备份介质也可以包括在这里。因此,一个数据客体可能同时存在于该存储层次结构的多个位置上,除了在主存储器中有一个永久性的拷贝外,还可能有临时性的拷贝。通常,这些临时拷贝的位置和生存期不在用户的控制之下,如果这些临时拷贝之一被保存在一个未受保护的存储区域,对一个数据客体的安全控制就可以被绕过。
5.3.2 进程和线程
进程就是一个正在执行的程序,因此,对于操作系统来说进程是一个重要的控制单元,当然对于安全来说也是如此。简单地说,一个进程由以下几个部分组成:
可执行代码,
数据,
执行环境,如某些相关的CPU寄存器的内容。
进程工作在它自己的地址空间,并且只能通过操作系统提供的原语同其他进程通信。进程间的这种逻辑分离对于安全来说是一种有用的基础。但另一方面,进程间的上下文转换是一种开销很大的操作,因为操作系统必须将全部的执行环境保存在堆栈中。
线程是一个进程内部的执行流。由于线程间共享一个地址空间,它们避免了完全的上下文转换的开销,但是也逃避了可能的安全机制的控制。
5.3.3 控制调用—中断处理器能够处理由程序错误、用户请求、硬件故障等引起的执行中断,这种处理机制被称为异常、中断、陷阱等不同的名称。不同的术语可能指不同类型的事件,但仍然有相竞争的分类法,可参见[66]、5.6节作进一步了解。
我们将用“陷阱”作为一般术语,并且解释怎样将陷阱用于安全目的。陷阱是CPU的一种特殊输入,它包括中断矢量表中一个称为中断矢量的地址。中断矢量表给出了一些程序的位置,这些程序用于处理陷阱中规定的事件,称为中断句柄。当一个陷阱发生时,系统在堆栈中保存当前状态,然后执行中断句柄(图5.4),用这种方式将控制从用户程序那儿接管过来。中断句柄必须保证在将控制返回给用户程序前,将系统恢复到一个正确的状态,比如清除超级用户状态位。
图5.4
当处理器正在处理当前中断时,可能会有新的中断到来,这时处理器可能必须中断当前的中断句柄。这种情形如果处理得不正确,可能会导致安全缺陷。一个典型的例子就是这样一个系统,用户可以通过键入CTRL-C来中断程序的执行,使得处理器带着当前进程的状态位迅速返回操作系统。于是,用户通过中断一个操作系统调用的执行就可以进入管理员模式,因此,在执行程序前建立中断表使得中断能以一种适当的方式被处理是非常重要的。
从以上讨论可以清楚地看出,中断表是一个特别令人感兴趣的攻击点,必须受到充分的保护。同样地,重定向指针是危及操作系统完整性的一种非常有效的方法,我们在分析计算机病毒时还会再一次遇到这个问题。
5.3.4 Motorola 68000上的保护
Motorola 68000是一个16位处理器,它有一个16位的状态寄存器,其高位部分(系统字节)包含了以下与安全控制相关的位。
T 跟踪位,在位置15上
S 超级用户位,在位置13上
I2I1I0 中断级别号,在位置8到10上
状态寄存器的低位字节是条件代码寄存器(CCR)(图5.5)。68000用超级用户位S区分用户模式和超级用户(系统)模式。复位后68000总是以超级用户模式引导,超级用户模式允许访问状态寄存器的系统字节。一旦S位被置成0且当前处于用户模式,那么只有中断和错误异常才能将S位切换回1,并以超级用户模式运行。操作系统调用是通过TRAP #n指令实现的,并能以超级用户模式运行和访问超级用户存储器,操作数#n指示了32和47之间的一个异常矢量。退出时,操作系统调用通过RTE指令切换回用户模式。
图5.5
68000有7个中断优先级,当前的中断级别保存在状态寄存器的I2I1I0位中。当68000正在处理一个中断而另一个具有较高优先级的中断到来时,新的中断得到优先处理,第一个中断被中断。较低优先级的中断则被忽略。为保护一个中断句柄被进一步中断,我们必须通过在状态寄存器中设置中断级别号来屏蔽中断,因此中断级别7屏蔽所有其他的中断。
处理器使用内存映像I/O,即将输入/输出端口地址看成是内存地址空间的一部分,因此输入/输出操作和内存访问可用统一的方式处理。处理器有64根连线(管脚),其中的三根管脚被指定为功能代码输出FC2、FC1和FC0,这些功能代码向地址译码器指示处理器的状态,地址译码器可以使用这些代码在用户存储器和超级用户存储器之间或者在数据和程序之间进行选择(图5.6)。
图5.6
区分数据和程序的能力是一种非常有用的安全特性,它为保护程序不被修改提供了基础。
从较为抽象的观点来看,存储器已经被分成了不同的区域,于是访问控制就可以指一个数据客体或一个程序来自的位置。
现在你有了一个在微观世界中基于位置的访问控制的例子,在分布式系统或计算机网络中,你经常需要微观世界中基于位置的访问控制。
5.3.5 Intel 80386/80486上的保护
Intel 80386/80486是32位的微处理器,80386/80486上的保护模式支持多任务操作系统的完整性和机密性要求。
Intel 80386/80486在状态寄存器中有一个2比特的域,定义了四种特权级别(保护环),特权级别只能被运行在级别0上的单指令(POPF)修改。软件可以被指派到如下各个级别上:
操作系统核心操作系统的其余部分
I/O驱动程序等应用软件不是所有的操作系统都使用全部四个级别,比如Unix只使用级别0和3。80386/80486实现了以下安全策略。
规则 程序只能访问位于自己环内或外环中的客体。程序只能在自己的环内调用子例程。
80386/80486保存系统客体的信息,如存储器段、访问控制表或描述符中的门。描述符保存在描述符表中,通过选择器进行访问,一个客体的特权级别保存在它的描述符的DPL域中。选择器是一个16位的域,包含一个指向描述符表中客体入口的索引以及一个被请求的特权级别(RLP)域(图5.7),RLP域的使用后面马上会解释。只有操作系统能够访问选择器。
图5.7
包含关于主体(即进程)信息的系统客体当然也有描述符和选择器(符)。当一个主体请求访问一个客体时,相关的选择器被装入专用的段寄存器中。比如,当前进程的特权级别,称为当前特权级别(CPL),就是保存在代码段(CS)寄存器中的选择器的特权级别。
毫不奇怪,我们又一次面对了这样的问题,就是必须对那些要求较高特权的操作进行访问管理。假设环3中的一个应用程序需要环1中一个操作系统例程的服务,在80386/486中这个问题是通过使用门来解决的。门是一个指向某个程序(在某个代码段中)的系统客体,这里门具有与它所指向的代码不同的特权级别。门允许对内环中的程序进行只执行访问,但仍限制向外的调用。
为使程序(过程,procedure)使用门,门必须和程序位于同一个环内。当通过门调用一个子例程时,当前特权级别变为门正指向的代码的级别。当从子例程返回时,特权级别恢复到调用程序的特权级别。子例程调用也在堆栈中保存指示调用程序状态的信息或返回地址。为了确定堆栈的合适的特权级别,记住调用程序不能写入内环。但是由于安全的原因,将堆栈留在外环也是不能解决问题的,因为它使得返回地址完全没有保护。因此,一部分堆栈(大小在门的描述符中规定)要拷贝到一个更有特权的堆栈段中。
通过允许外环程序调用内环程序,我们制造了一个潜在的安全漏洞,外环程序可以请求内环程序将位于内环上的一个客体拷贝到外环上。迄今为止我们给出的任何安全机制都不能防止这种做法,事实上它也没有违反我们规定的安全策略。因此,我们可能希望扩展原来的安全策略,使其不仅考虑到当前的特权级别,也考虑到调用程序的级别。在80386/486中,可以使用选择器中的RLP域和调整被请求的特权级别(ARPL)指令支持这种策略。ARPL指令将所有选择器的RLP域改为调用程序的CPL,然后系统可以比较RPL(在选择器中)和客体的DPL(在描述符中),如果它们不同的话,拒绝完成被请求的操作(图5.8)。
图5.8
5.4 引用监视器
操作系统管理对数据和资源的访问,通常不涉及对用户数据的解释。多任务操作系统交替执行属于不同用户的进程,因此操作系统不仅必须保护它自己的完整性,还必须防止用户有意或无意地访问其他用户的数据。操作系统本身的完整性通过隔离用户空间和操作系统空间来保护,用户的逻辑隔离防止用户间有意和无意的干扰。隔离可以发生在两个层次上:
文件管理 ,处理逻辑存储客体,和
存储管理,处理物理存储客体。
对于安全来说,这种区分是非常重要的。为了说明这一点,考虑两种最主要的组织存储方式,分段和分页。分段是将数据划分成逻辑单元,每个段有一个唯一的名字,段内的数据项通过给出段名和适当的段内偏移量来寻址。操作系统维护一个段表,其中包括段名以及各个段在存储器中的真实地址。Multics操作系统用分段来进行逻辑访问控制。
分段是逻辑单元的一种划分,它是实施安全策略的良好基础。另一方面,段具有可变长度,这使得存储管理较为困难。
分页是将存储器划分成相同大小的页,同样地址由两部分组成,页号和页内偏移。
分页很流行,因为它允许高效的存储管理。Multics的段实际上是分页的。另一方面,
分页对于访问控制来说不是一个好基础,因为页不是逻辑单元。因此一个页可能包含要求不同保护的客体。
更糟的是,分页可能会打开一个隐蔽通道。逻辑客体可以跨越页边界存储,当这样的客体被访问时,操作系统在某个时候会要求一个新页,这时产生缺页。如果缺页可以被观察到,就象大多数操作系统中那样,那么用户就获得了比正确的访问请求结果更多的信息。
作为例子,考虑一个口令方案。用户输入一个口令,该口令被逐个字符地扫描,并同保存在存储器中的一个参考口令进行比较,当发现不匹配时访问被拒绝。如果一个口令跨越页边界存放,那么攻击者可从观察到缺页推断出第一页上的口令片段已被正确猜测出来。如果攻击者可以控制将口令存放在页的什么地方,口令猜测就变得相当容易了。
5.4.1 存储器保护
当你希望操作系统保护自己的完整性,并且将每个进程限制在分开的地址空间,那么你的任务之一就是控制对存储器中数据客体的访问。这样一个数据客体在物理上被表示成存放在某个存储位置的比特集合,访问一个逻辑客体最终被转换成机器语言级上的访问操作。在这一层上,控制对存储位置的访问可以有三种选择方法:
操作系统修改从用户进程收到的地址;
操作系统利用从用户进程收到的相对地址构造有效地址;
操作系统检查从用户进程收到的地址是否在给定的界限内。
地址沙箱法是第一种方法的一个例子。一个地址由一个段标识苻和一个偏移量组成,当操作系统收到一个地址时,它设置正确的段标识。图5.9显示如何用两个寄存器操作来完成地址修改。首先,用地址与mask_1的按位与(AND)操作清除段标识,然后用与mask_2的按位或(OR)操作将段标识设置成希望的值,SEG-ID。
图5.9
在第二种方法中,编址方式的巧妙使用可避免进程进入禁止的存储区域。如果你需要更多关于编址方式的背景知识,请查阅有关操作系统或计算机体系结构的书[38,66,100]。在各种各样的编址方式中,相对编址特别引起我们的注意:地址是用相对于某个给定的基地址的偏移量来指明的。比如,在Motorola 68000中相对编址是通过寄存器间接置换编址方式支持的。汇编语言指令
MOVE.L 8(A1),D3
将常数8加到寄存器A1的内容上获得一个存储器地址,将存放在该存储地址上的长字(16位)放入寄存器D3。
相对编址允许位置无关的编码,这样程序可以存放在存储器的任何地方,给了存储管理程序很大的灵活性,也方便栅栏寄存器的使用。栅栏寄存器包含了分配给操作系统的存储区域的边界地址,用户程序中的地址被解释为相对地址(偏移量,置换),操作系统使用关于栅栏寄存器的相对编址(基础寄存器编址(寄存器基址寻址))来计算有效地址(见图5.10)。用这种方式,只有操作系统空间以外的位置可被用户程序访问。类似的方法可被操作系统用来隔离分配给不同用户的存储区域。
图5.10
这种方法可以通过用基础寄存器和边界寄存器来定义分配给进程的存储空间而得到进一步的改进,我们甚至可以再进一步,分别为用户的程序空间和数据空间引入基础和边界(基址和界限)寄存器。为了正确使用这种工具,处理器必须能够检测一个给定的存储位置存放的是数据还是程序代码,然而大多数的指令集没有办法使指令检查其操作数的类型。如果没有这样的方法,类型信息可以通过在程序中指出不同存储访问操作必须使用的地址寄存器来提供,这种方法要求正确的编程规则。
另一种方法,在一个标记体系统结构中,每个数据项有一个说明其类型的标签(tag),执行前CPU可以从保存在存储器中的值直接检测出任何的类型违背。此标签也可用于实施安全策略。历史上,标记体系结构在理论描述中非常流行,但很少用于实际的实现。标记体系结构为数很少的几个例子包括Burroughs B6500-7500系统和IBM System/38[17]。(对计算历史感兴趣的读者,1945年冯?诺伊曼在他的First Draft of a Report on the EDVAC中描述了一个标记体系结构[154])。
图5.11给出了一个标记体系结构,它指示存储客体的类型,如整数(INT)、位串(STR)或操作数(OP)。标签也可被用来指示在一个存储位置上可以执行哪一种访问操作,如读、写或执行。
图5.11
5.4.2 Multics操作系统
在历史上有重要影响的Multics操作系统的例子能说明安全核心(内核,kernel)如何实施访问控制。Multics是一个雄心勃勃的研究计划的产物,该计划旨在开发安全的、可靠的等等多用户操作系统[13,119]。安全方面的许多研究,象BLP,都是由Multics计划引发的。[119]的第四章给出了Multics保护机制的一个概述。由于它范围广泛的目标和安全需求(?),该计划的一些成员觉得它太笨重了,于是建立了更简单的操作系统,就是Unix。就商业成功而言,这两个系统的历史就是可用性与安全性之间相平衡的一种表现。
5.4.3 BLP的Multics解释
研究Multics给了我们一个机会,看看安全模型是如何用于一个安全的操作系统的设计的,本例中是Bell-LaPadula模型。作为访问控制的一个抽象模型,BLP非常适合于捕捉操作系统的安全需求,事实上它正是为此目的而开发的。BLP中关于安全的归纳定义使它比较容易建立一个安全的系统,我们只需正确地定义状态迁移来保证安全性。为了证明Multics是安全的,我们必须找到一种与BLP相一致的Multics描述,我们将基本上按照[13]中的介绍来说明BLP的安全概念是如何映射到Multics的。
Multics中的主体是进程,每个主体有一个包含进程信息的描述符段,其中包括进程当前访问的客体的信息。对于每一个这样的客体,在主体的描述符段中有一个段描述符字(SDW)。SDW的格式在图5.12中给出,包括客体名、指向客体的指针以及读、执行和写访问的指示器标志,这些指示器涉及3.3.2所规定的访问属性。主体的安全级别保存在一个进程级别表和一个当前级别表中,活跃段表记录所有运行态(活跃的,active)的进程,只有运行态的进程能够访问客体。
图5.12
Multics中的客体是存储段、I/O设备等,客体按层次组织在一棵目录树中。目录也是段,有关一个客体的信息,像它的安全级别或访问控制列表(ACL),保存在客体的父目录中。因此,改变一个客体的访问控制参数以及建立或删除一个客体,需要对父目录写或者添加访问权限。
为访问一个客体,进程必须遍历从根目录到目标客体的目录树,如果路径中任何一个目录对于进程是不可访问的,那么目标客体也不可访问。换句话说,一个保密目录中的非保密客体不能被一般性用户阅读。因此,将客体放入具有较高安全级别的目录是没有意义的,我们总是要求客体的安全级别控制其父目录的安全级别,这个特性称为兼容性。你在现代操作系统(如Unix)中必须处理同样的问题,如果你想使你的文件对于其他用户是可访问的,你也必须完全获得对目录路径的访问控制设置。
现在我们有了全部所需的信息,可以用Multics系统表和描述符段中的数据来确定BLP状态集的组成(component)。
当前访问b:保存在运行态进程的描述符段的SDW中;运行态进程可以在活跃段表中找到。
访问控制矩阵M:用ACL表示;对于每个客体,ACL保存在它的父目录中;每个ACL表项列出一个进程以及进程对该客体的访问权限。
级别函数f:主体的安全级别保存在专门的进程安全级别表中,即进程级别表和当前级别表;客体的安全级别保存在其父目录中。
在3.3.2中,我们已经介绍了Multics对数据段和目录段的访问属性,也解释了这些访问属性如何对应Bell-LaPadula模型的访问权限。作为提示,我们在图5.13中重新叙述了对数据段的访问属性。
图5.13
现在我们用进程和数据段的安全级别以及SDW中的指示器重新描述BLP的安全特性。比如星特性写成如下形式,对于一个运行态进程的描述符段中的任何SDW,进程的当前级别:
控制段级别,如果读或执行指示器打开而写指示器关闭;
被段级别控制,如果读指示器关闭而写指示器打开;
等于段级别,如果读指示器打开而写指示器也打开。
图5.14说明如何验证与星特性的一致性。当前进程的安全级别Lc保存在当前级别表中,描述符段基础寄存器(DSBR)的内容指向当前进程的描述符段的头部,这个描述符段恰好包含了一个访问属性为只写的客体的SDW,因此,写指示器打开而读指示器关闭。客体的安全级别Lo从其父目录中得到,并与Ls比较来证明Ls(Lo成立。
图5.14
5.4.4 核心原语
最后必须规定一组核心原语。这些核心原语是Multics核心抽象模型中的状态迁移,我们必须证明它们保持BLP的安全策略。这样,基本安全定理的前提条件成立,我们就证明了Multics的“安全性”。当然,这不是安全性的一个完整证明,你还必须证明核心原语的实现以及最后它们在一个给定硬件平台上的执行符合它们的规范。
我们选择get-read来详细地看一个核心原语。get-read原语用process-id和segment-id作为参数,操作系统必须检查:
segment-id的ACL(保存在段的父目录中)是否列出了带有读允许的process-id;
process-id的安全级别是否控制segment-id的安全级别;
process-id是否是一个信任的主体,或者process-id的当前安全级别是否控制segment-id的安全级别。
如果所有三个条件都满足,访问被允许。如果没有segment-id的SDW存在,一个对应的SDW被添加到process-id的描述符段中,且读指示器打开。如果segment-id的一个SDW已经存在于process-id的描述符段中,则打开SDW中的读指示器。如果以上三个条件中任何一个不满足,访问被拒绝。
以下是另外一些已经提出来要在Multics核心中实现的原语:
release-read 进程释放一个客体;对应SDW中的读标志被清除;如果此后没有指示器打开,SDW被从描述符段中删除。
give-read 进程向另一个进程授予读访问权限(自主性访问控制)。
rescind-read 进程将赋予另一个进程的读权限收回。
create-object 进程创建一个客体;操作系统必须保证对客体目录段的写访问是允许的,并且段的安全级别控制进程的安全级别。
delete-object 当删除一个客体时,必须执行与create-object中一样的检查。
Change-subject-current-security-level 操作系统必须保证变化没有造成安全违背;这个核心原语以及原语
change-object-security-level不打算用于实现(稳定性)。
理想的情况是,开发处理器时使它的指令集与操作系统的核心原语相吻合。相反地,核心原语可以设计成与现有处理器提供的支持相匹配。
进一步的阅读
主要的访问控制范例应归功于Lampson[82]。[39]全面论述了针对第一个多用户操作系统而进行的计算机安全研究的成果。[84]汇集了对保护技术的进一步研究。[56]对于在设计安全的多用户操作系统中使用的技术作了极好的说明,这本书包含了许多指向该领域技术报告的有用链接。在[131]中可以找到对Multics安全性的评论,特别是对安全管理的复杂性以及对设计的正确性进行评估的复杂性评论。
Motorola 68000微处理器在[33]中作为例子有详细的解释。对Intel 80386/486上的保护机制的详细描述见[111],较简短的介绍见[49]。用Intel 80x86处理器构造安全核心在[141]中有讨论。
地址沙箱法和相关技术在[155]中有描述。需要存储管理方面的实用资料,请查看QNX网页:http://www.qnx.com/literature/nto_sysarch/nto_sysarch.html。有关Multics的信息可以在http://www.lilli.com/multics.html上找到。
安全计算机系统的早期开发历史在[93]中有比较。最近有人针对TCB(安全核心)在安全系统的构造中是否仍然是一个适当的范例提出了疑问,这场争论中相反的两种意见可以在[21](反对)和[11](赞成)中找到。
练习题练习5.1 在Motorola 68000中,如果状态寄存器中的跟踪位置位,每条指令执行后都会产生一个异常(中断),允许程序员运行一个异常处理例程(中断句柄),比如用于调试程序。设置跟踪位隐含的安全问题是什么?为什么在处理异常时跟踪位必须清除?
练习5.2 寄生病毒感染可执行程序(见8.8)。区分程序和数据的能力怎样才能有助于构造一道抵御这类病毒的防线?
练习5.3 智能卡上的微处理器通常将全部的卡操作系统置于ROM中,现在有一种趋势,就是部分的操作系统可以下载到EPROM中。将操作系统放在ROM中的优点和缺点是什么?将部分操作系统移入EPROM隐含的安全问题是什么?
练习5.4 证明5.4.3中星特性的重新描述是正确的。为什么我们只要考虑提到的三种情形?
练习5.5 应当给多级安全操作系统的根目录分配什么样的标签?
练习5.6 考虑多级安全操作系统中的一个目录,保存文件的安全级别有三种可供选择的方法:
将文件的安全级别和文件名一起保存在目录中。
将文件的安全级别和文件本身存放在一起,目录仅包含文件名。
将目录划分成若干区,每个安全级别对应一个区,文件名放入与它们的安全级别相对应的区中。
分析每一种方法隐含的安全问题和可用性问题。
练习5.7 没有安全核心你能获得安全性吗?讨论拥有一个象TCB那样的安全核心的优点与缺点。
练习5.8 寻找一些例子说明以下三条原则如何应用到构造安全的系统上:责任分开,抽象数据类型和原子操作。(为保持安全性,原子操作必须被全部执行。如果操作被中断,系统将终止在一种不安全的状态。)
练习5.9 当你注册到一个系统上后,你启动一个进程以你的身份运行。以你的身份运行的进程在你退出系统后能够继续运行吗?在你正在使用的操作系统上研究这个问题。
Authenticity 可靠性
In data security,controls that either prevent or detect the tampering and/or accidental destruction of data,If the data to be protected is already encrypted,then authenticity requires that a cryptanalyst would not be able to substitute a false ciphertext without detection.
数据安全技术中的一种控制功能,用以防止或能检测出故意和/或意外的数据破环。若待保护的数据已被译成密码,则可靠性要求密码分析员不能代之以伪造的密码电文而不被发现。参阅accidental destruction,digital signature,masquerading。
Accountability 责任
In computer security,the quality or state that enables violations or attempted violations of ADP system security to be traced to individuals who may then be held responsible.
计算机安全学中,指可以追查对自动数据处理系统的侵害或试图侵害的责任者的性质或状态。
Dependency 相关性
The condition in which the accuracy of results from one program depend upon the accuracy of results from another; for example,if the first program updates a file and the second uses it.
一种程序所得结果的精度取决于另一个程序所得结果精度的条件。例如,若第一个程序修改了一个文件,而第二个程序要用此文件。
Reliability 可靠性;[可靠度]
The ability of a functional unit to perform a required function under stated conditions for a stated period of time.
操作[功能]部件在规定条件下和规定时间内完成规定操作[功能]的能力。