1、第3章 程序安全 本章要点r 具有安全隐患的编程错误 r 恶意代码 r 防止恶意代码和脆弱性的程序开发控制 r 控制程序运行时的缺陷 程序构成了一个计算机系统的很多部分,因此多种形式保护程序是计算机安全的核心。我 们 将 所 有 代 码 片 称 之 为“程 序程 序”(program)。这里需要提出两个重要问题:怎样消除程序中的缺陷?在程序有缺陷的情况下,如何保护计算机资源?本章讨论的是一般的程序话题,包括程序编写。程序安全中一个重要问题是信任信任。信任问题是指:假设提供一个已完成的程序,如何来确定它的安全性或者说如何以最安全的方式使用它?答案是采用独立的第三方的评估第三方的评估。3.1 安全
2、程序 评估程序安全与软件质量的评估相似,一种评估软件安全性或质量的方法是让人们列出能反映该软件整体安全的那些特性。然而,不同的人有不同的答案。人们对软件质量的总体设想也会影响对安全性的评估。一般而言,开发者把错误的数量数量和种种类类作为衡量产品质量的依据。当一个人在从事软件活动的过程中有所疏失时,我们称之为过失过失(error)。过失可能会在计算机程序中导致一个错误错误(fault),或者一个不确定的步骤、命令、过程或数据定义。一个单独的过失可以产生很多错误,一个错误可以隐藏在任何产品的开发和维护中。一次失效失效(failure)就是对系统要求行为的一次违反。一次失效意味着系统没有按照需求执行
3、。错误是对系统的内部观点而言的,是开发开发者者所见到的;而失效则是对系统的外部观点而言的,是用户用户看到的问题。3.1.1 修改错误 修改错误是评估安全质量的一种方法。计算机安全工作建立在“查找错误并打补丁查找错误并打补丁”(penetrate and patch)的模式上。分析专家在该模式下寻找错误,并给错误打上补丁。3.1.1 修改错误(续)缺陷:1)修补指定问题的压力使得人们仅仅关注错误本身,而不是与之相关的上下文环境。2)在离错误较远的区域,其副作用不明显。3)修补一个问题时常导致其他地方的失败,或者说补丁仅仅解决一个地方的问题,而没有解决相关地方的问题。4)打补丁可能会影响系统的功能
4、和性能,所以补丁经常不能恰当地修补系统错误。3.1.2 意外行为 “程序安全缺陷程序安全缺陷”(program security flaw)是由于程序的脆弱点而引起的不恰当的程序行为。“脆弱点”和“缺陷”这组词与“错误”和“失效”这组词之间并没有直接的对应关系。一个缺陷可以是一个错误或是失效,而脆弱点经常用来描述某一类缺陷,诸如缓冲区溢出。尽管不一致,但应该记住:我们必须从两个方面来看待脆弱点和缺陷,即起因起因和影响影响。程序安全性缺陷可以来源于任何种类的软件错误。有必要将程序缺陷划分为两种逻辑类别:由开发者的疏忽所引起的错误和恶(有)意设计的缺陷。3.1.2 意外行为(续)分类帮助我们理解一
5、些方法,用以防止将缺陷有意或无意地引入到以后的代码编写中。一个因疏忽而引起的错误给用户及其组织带来的损失可能与恶意漏洞带来的损失相当。计算机攻击计算机攻击(cyber attack)即有意的安全事件,是如今最大的安全威胁。从根本上说安全是困难的,安全时常与有效性和性能相冲突,而且错误的安全解决方案会阻碍安全编程的真实进展。我们还没有技术来消除或解决所有的程序安全缺陷。原因有两个:3.1.2 意外行为(续)1)程序控制是在单独的程序和程序员的级别上实施的。功能测试是解决程序“应该应该做什么做什么”的问题,而安全测试还要确定“不应该做什么不应该做什么”的问题。要保证程序精确地按照设计者和用户的意图
6、来执行而没有其他的行为,这几乎是不可能的。在一个复杂的大型系统中,不管设计者或程序员的意图何在,许多相关模块都以各种各样难以控制的方式交织着。巨大的规模巨大的规模和复杂性复杂性使得我们不可能去预防和检查所有缺陷。想要植入恶意代码的程序员可以利用系统的不完整性成功地将漏洞隐藏其中。3.1.2 意外行为(续)2)程序设计和软件工程技术的发展迅速远远超过了计算机安全技术的发展速度。所以我们经常发现自己还在努力保护去年的技术,而软件开发者却正迅速地采用当前最新的技术了。#尽管如此,我们可以通过理解什么导致错误以及怎样阻止它,来开发技术和工具,保护大多数计算机的应用程序。3.1.3 缺陷类型 Landw
7、ehr等提出了一种关于程序缺陷的分类法,首先分为有意和无意的缺陷。进一步将有意缺陷细分为恶意和非恶意的类型。无意的缺陷分为6类:确认过失确认过失(不完善或不一致不完善或不一致):许可权核查。域过失域过失:对于数据的受控访问。序列化和混淆序列化和混淆:程序流顺序。不充分的识别和鉴别不充分的识别和鉴别:授权的基础。边界条件违规边界条件违规:首次或末次情形失效。其他可以利用的逻辑过失逻辑过失。3.2 非恶意的程序漏洞 3.2.1缓冲区溢出 问题说明问题说明 定义定义 1 缓冲区缓冲区(或数组、字符串)是一个用来存储数据的空间。缓冲区位于内存中。由于内存是有限的,所以缓冲区的容量也是有限的。因此,在许
8、多程序设计语言中,程序员必须声明缓冲区的最大容量,以使编译器能留出所需的空间。3.2.1缓冲区溢出(续)C程序中:char sample10;sample10=B;samplei=B;/执行过程确定i的值3.2.1缓冲区溢出(续)若有:for(i=0;i0 DO stmts END从K到stmtsCASE(exp)val1:stmts从exp到stmtsB:=fcn(args)从fcn到BOPEN FILE f没有信息流动READ(f,X)从文件f到XWRITE(f,X)从X 到文件f3.4.9 隐蔽通道:泄露信息的程序(续)对隐蔽通道的小结对隐蔽通道的小结 隐蔽通道对信息系统的安全来说是一个
9、严重的威胁。隐蔽通道攻击手段非常灵活,可以隐藏在任何服务程序,如打印机程序等。制造起来也不比病毒难。容量和速度也不是限制信息流传播的条件,特别是隐藏在硬件中的隐蔽通道。关闭隐蔽通道的技术进展并不乐观。隐蔽通道存在的可能性要求人们对程序开发分析、系统结构分析和输出审查给予更大关注。3.5 对程序威胁的控制 应该更关注如何预防漏洞而不是修补漏洞。这需要在软件开发软件开发(software development)期间,即编写规范、设计、编码和测试等过程中,实施控制。我们将讨论:开发控制、操作系统控制和管理控制。这里先讨论开发控制。3.5.1 开发控制 软件开发过程的特点软件开发过程的特点 开发过程
10、中需要完成的任务:系统需求分析系统需求分析,获取系统的需求并从用户的角度构建模型系统。设计系统设计系统,从需求描述出发,提出解决问题的方案,并为该方案建模。实现系统实现系统,以设计方案为蓝本来实施问题的解决方案。测试系统测试系统,确保系统符合需求分析和系统设计中所提出的需要。在不同的阶段复查系统在不同的阶段复查系统,确保最终的产品符合需求分析和系统设计中所提出的要求。为系统编写文档为系统编写文档,以进行对用户的培训和支持。管理系统管理系统,以清除一些不必要的资源。这些资源在软件开发过程中使用,但系统完成后,它们可能会成为通往系统内部的暗道。维护系统维护系统,追踪被发现的问题、必要的系统变化和已
11、经产生的系统变化,并从整体上评估它们对系统的质量和功能的影响。3.5.1 开发控制(续)软件开发过程的特点软件开发过程的特点(续续)设计安全、可用的系统,需要注意如下要点:1)不能随意发挥可用的安全性能2)工具不是解决方案3)关注上层4)让用户满意5)局部思考,局部动作 3.5.1 开发控制(续)模块化、封装性和信息隐藏模块化、封装性和信息隐藏 通常,代码的生存期生存期(shelf-life)是很长的。但是,随着时间的推移,代码需要完善,因为需求可能发生变更,并且发现的错误需要修改。因此,软件工程的一个重要原则就是将代码或其他设计实体做成小型、独立的单元,称为组件组件(component)或模
12、块模块(module)。当系统按照这种方法开发时,我们 称其为模块化模块化(modular)。3.5.1 开发控制(续)模块化、封装性和信息隐藏模块化、封装性和信息隐藏(续续)如果一个独立的组件不受其他组件的影响,就很容易找出其中故障的原因,并将故障的危害控制在最小范围内。独立组件也使系统的维护变得容易,因为对一个独立组件所做的调整将不会影响其他组件。在组件间完全独立的情况下,我们能更容易地发现漏洞所在。这种独立的模块化形式称为封装性封装性(encapsulation)。信息隐藏信息隐藏(information hiding)是模块化软件的又一个特性。信息隐藏指的是,每个组件都隐藏自己的实现细
13、节或设计细节。这样在系统需要调整时,只需要调整某个特定组件。3.5.1 开发控制(续)模块化、封装性和信息隐藏模块化、封装性和信息隐藏(续续)模块化是将一个任务划分为若干子任务的过程。这种划分是以逻辑性逻辑性或功能性功能性为基础的。模块化使得每个组件都必须满足4个条件:单任务单任务:只完成一个特定的功能 小型化小型化:一个组件包含的信息数量非常少,以至于人们可以很容易地理解它的构造和内容 简单化简单化:复杂程度不高,可以很容易地理解模块的意图和构造 独立性独立性:不依靠其他模块而独立完成任务 3.5.1 开发控制(续)图 3.16 模块化模块化、封装性和信息隐藏模块化、封装性和信息隐藏(续续)
14、3.5.1 开发控制(续)模块化、封装性和信息隐藏模块化、封装性和信息隐藏(续续)小型、独立的组件具有许多好处:易维护易维护:当需要用改进版本取代一个旧版本的组件时,如果该组件只执行某个单独的功能,则只需将旧组件移除就可以了。易理解易理解:人们通常更容易理解一个由许多小型组件所构成的系统,而不容易理解一个由大量非结构化的代码所构成的系统。可重用可重用:为一项特定任务而开发的组件经常可以被其他系统重复利用。重用正确、已经存在的代码或设计,可以减少开发和测试的难度。易修复易修复:对完成一项特定任务的组件来说,很容易确定它的故障。易测试易测试:一个良好定义了输入、输出和功能性的组件可以仅从自身出发尽
15、一切可能性来进行测试,这些测试不用考虑其他模块的影响。3.5.1 开发控制(续)模块化、封装性和信息隐藏模块化、封装性和信息隐藏(续续)内聚内聚(cohesion)是指组件中所有元素的存在都有充足的逻辑理由或功能理由,每个组件元素都与组件要执行的单一任务是相关的。耦合耦合(coupling)是指某个组件与系统中其他组件的相互依赖程度。图 3.17 耦合3.5.1 开发控制(续)模块化、封装性和信息隐藏模块化、封装性和信息隐藏(续续)封装性 一个被封装组件的边界可以根据需要设计成半透明或透明。应该将组件内的信息打包,隐藏应该隐藏的部分,并将应该可见的部分呈现出来。3.5.1 开发控制(续)模块化
16、、封装性和信息隐藏模块化、封装性和信息隐藏(续续)信息隐藏 一个设计良好的组件,对其他设计者而言没有必要知道该模块的实现细节。隐藏实现细节,使得恶意开发者因为不知道该组件是如何工作的,而不能轻易用其他的组件替换。图 3.18 信息隐藏3.5.1 开发控制(续)相互猜疑相互猜疑 相互猜疑相互猜疑(mutual suspicion)是描述两个程序的关系,相互猜疑的程序各自运行,仿佛系统中其他程序是恶意或者不正确的。每个程序都保护它的接口数据以限制其他程序访问。限制限制 一个受限制的程序被严格地限制它可以访问的系统资源。强限制有助于限制病毒扩散。3.5.1 开发控制(续)遗传的多样性遗传的多样性 来
17、自一个来源的系统的多个组件是危险的。软件产品的紧密集成也是一个类似问题。由于紧密集成,修补一个软件产品的漏洞会影响其他软件产品。3.5.1 开发控制(续)技术手段技术手段软件开发阶段,几种关键的技术包括:1)对等复查2)风险分析3)测试4)良好的设计5)预测6)静态分析7)配置管理8)错误分析 3.5.1 开发控制(续)对等复查对等复查 三种有很细微差别的对等复查:复查复查:让复查小组非正式地对产品做出评审,目的在于在开发继续进行之前,听取大多数人的意见。走查走查:产品的制造者将产品提交评审小组,并主持和控制小组的讨论。该类型复查的目的在于让小组成员针对产品进行学习,关注的焦点是研究某个单独的
18、文档。检查检查:这种复查更加正规,它将根据一张清单做详细的分析,该清单上列举了一些应该关注的问题。作者不再是讨论的主持人,而错误的发现和修正通常由统计测试来控制。3.5.1 开发控制(续)对等复查对等复查(续续)发现了错误后可以采取至少三种方法进行处理:1)研究错误发生的方式、时间和原因。2)采取行动阻止错误的运行。3)仔细检查产品以找出被忽略的错误实例和影响。3.5.1 开发控制(续)对等复查对等复查(续续)进行对等复查非常必要。Hewlett-Packard早期的研究表明:在开发过程中实施了对等复查的产品比其他实施传统测试技术的产品具有明显优势。图 3.19 报告的错误发现率3.5.1 开
19、发控制(续)对等复查对等复查(续续)复查的过程包括了几个重要步骤:计划计划、个体准备个体准备、会议讨论会议讨论、再工作再工作和再检查再检查。复查中,应该密切关注复查者的发现和他们发现问题的速度。这可以了解每位复查者是否胜任。而且可以了解某类错误是否较其他错误更难发现。对错误的处理还要追根溯源。开发中记载错误的日志错误的日志可以形成检查清单,以备复查使用。管理措施必须强制系统在开发的整个过程中使用苛刻的复查法才能保证最终程序的安全。3.5.1 开发控制(续)风险分析风险分析 风险分析风险分析(hazard analysis)是在系统级上采用一系列技术揭示系统潜在的不安全状态。风险分析是系统级而非
20、代码级,其对发现安全漏洞无能为力。风险分析越早越好,并且应该贯穿整个软件生存期。大量不同的技术都支持查找和管理潜在的风险。3.5.1 开发控制(续)风险分析风险分析(续)最有效的技术是风险和运行性研究风险和运行性研究(hazard and operability studies,HAZOP)、失效模式和后失效模式和后果分析果分析(failure modes and effects analysis,FMEA),以及故障树分析故障树分析(fault tree analysis,FTA)。表 3.6 风险分析的观点已知原因未知原因已知结果描述出系统的行为推论分析,如FTA未知结果诱导分析,如FME
21、A探测分析,如HAZOP3.5.1 开发控制(续)测试测试 测试是针对产品质量的活动,目的是消除产品的故障或使故障在允许范围内。由于一个控制失败暴露出的脆弱点是再多的功能控制所无法改善的,因此,测试者应该保持足够的谨慎。安全测试很艰难。副作用、依赖性、不可预知的用户、有缺陷的实现基础都给安全测试带来困难。安全测试复杂的本质在于,不仅安全测试复杂的本质在于,不仅需要考虑程序的正确运行,而还必须考虑程需要考虑程序的正确运行,而还必须考虑程序可能出错的各种方式序可能出错的各种方式。3.5.1 开发控制(续)测试测试(续续)测试通常包括几个阶段:单元测试单元测试(unit testing)是在可操控的
22、环境下实现的,这样测试小组可以为组件输入一组预定的数据,并观察组件的输出行为和输出数据。此外,测试小组还依据输入和输出数据检查内部结构、逻辑条件和边界条件。集成测试集成测试(integration testing)是确保系统的组件间按照系统设计规范的描述协调工作的检测过程。3.5.1 开发控制(续)测试测试(续续)功能测试功能测试(function test)评估系统以确定集成系统的功能是否同需求规范中所描述的一样。测试的结果是一个功能性系统。性能测试性能测试(performance test)将把系统与软、硬件需求做比较。在功能测试和性能测试期间,检查了系统的安全需求,确信安全需求与安全性能
23、相一致。接受测试接受测试(acceptance test)将检查系统是否符合用户的需求规范。安装测试安装测试(installation test)将系统安装在运行环境中进行最后的测试,确保系统在安装后仍然具有同样的功能性。同时,安全需求还经常指出系统不应该做的事情。3.5.1 开发控制(续)测试测试(续续)此外还有对系统的安全性非常重要的回归测试回归测试(regression testing),目的是确保在系统的功能加强或修复了某个漏洞后,其他功能仍可以正常运行而不受系统变化的影响。以上每种测试方法可以采用黑盒测试黑盒测试(black-box testing)和白盒测试白盒测试(white-b
24、ox testing)。多种技术的混合使用取决于系统的大小、应用领域、风险总和等因素。3.5.1 开发控制(续)测试测试(续续)独立测试独立测试(independent testing)是相当必要的,可以预防开发者在正常过程中隐藏一些东西,或保留一个子系统不受测试控制中以便将来使用。独立测试可以增大对隐藏事物的曝光率。渗透测试渗透测试(penetration testing)是计算机安全中一种独特的测试类型。在这种测试形式中,测试员尽量让软件失败。也就是说,尽量发现软件是否做了它没有被假定做的事情,测试可能的安全失效。3.5.1 开发控制(续)良好的设计良好的设计 许多与设计有关的活动对开发安
25、全软件有帮助。1)使用容错技术容错技术(fault tolerance)的哲学。处理错误应该尽量减少对系统的破坏且尽量符合安全。错误处理通常不应该采用被被动故障检测动故障检测(passive fault detection),而是主动故障检测主动故障检测(active fault detection),还可以利用冗余性冗余性(redundancy)。如果修正错误的风险太大,则可以应用容错技术,即安全策略选择减轻安全问题的影响而不是阻止它的发生。3.5.1 开发控制(续)良好的设计良好的设计(续续)2)使用一致的策略策略(policy)来处理错误。典型的错误包括:不能提供某个服务、提供错误的服务
26、或数据、损坏数据。解决出现的这些问题可以对应于每种错误采取如下一种方法:重试重试:将系统恢复到之前的状态,使用其他策略重新运行服务。修改修改:将系统恢复到之前的状态,修正一些系统特征,使用相同的策略重新运行服务。报告报告:将系统恢复到之前的状态,将问题报告给错误处理组件,并不再执行服务。#这些一致性的策略将有助于查找系统的安全脆弱点。3.5.1 开发控制(续)良好的设计良好的设计(续续)3)抓住设计的基本原理设计的基本原理(desgin rationale)和历史记录。这些文献有助我们了解采用某种方法创建系统的依据。4)使用设计模式设计模式(design pattern)。设计模式可以对将来的
27、设计方法提供指导,简化设计。3.5.1 开发控制(续)前景预测前景预测 软件开发过程中的前景预测,其预测内容是创建和使用系统的风险性。前景预测可以帮助我们挑选控制方法,以及决定控制的数量。例如,如果认为某个安全分支的风险系数很小,我们就不会投入大量的资金、时间和精力来建立复杂的控制系统。或者,可以在可能的风险冲击下证明同时使用一系列控制即“深度防御深度防御”(defense in depth)是正确的。3.5.1 开发控制(续)静态分析静态分析 在系统完成运行之前,可以通过检查设计和代码来寻找和修复安全漏洞。对等复查涉及这项技术。但静态分析更进一步检查设计和代码的细节,并在对等复查之前进行。可
28、以从以下几个方面检查设计和代码:控制流结构、数据流结构、数据结构。3.5.1 开发控制(续)配置管理配置管理 在开发软件时,重要的一点是必须清楚谁谁在什么时候什么时候对什么做了怎样的改变什么做了怎样的改变:修改性改变修改性改变:维护系统日常功能的控制 适应性改变适应性改变:维护控制而对系统的调整 完善性改变完善性改变:完善已经存在的系统功能 预防性改变预防性改变:预防系统性能下降到不能接受的程度3.5.1 开发控制(续)配置管理配置管理(续续)配置管理配置管理(configuration management)是在开发和维护期间用来控制软件改变的过程,对安全性也十分有利。特别是,配置管理会审查
29、新代码或改变后的代码,以确保安全漏洞没有被有意或无意地插入其中。配置管理中包含4类活动:1)配置鉴定 2)配置控制和变化管理 3)配置审查 4)状态说明3.5.1 开发控制(续)配置管理配置管理(续续)配置鉴定配置鉴定(configuration identification)设置了一个基线,所有改变后的代码将与之比较。这就是说,首先创建一个详细目录,其中记载了系统的所有组件。然后,“冻结”该基线并小心地对其加以控制。当系统发生改变时,将被描述为相对基线的改变。配置控制配置控制(configuration control)和配置管理配置管理(configuration management)确
30、保了可以协调不同的相关版本。这里有三种控制变化的方法:分隔文件分隔文件、delta方法方法和条件编译条件编译。分隔文件的方法就是让不同的系统版本拥有不同的文件。delta方法是指定某个版本为系统的主要版本,再定义其他的不同版本,版本中不同的文件称为delta,包含一些编辑过的命令行,这些命令行描述了从主版本向其他变异版本的转换方法。条件编译是在所有版本中都使用同一个代码组件,而由编译器来决定哪个版本应该使用哪条语句。这种方法似乎对安全应用有吸引力,所有代码都集中管理,如果版本非常复杂,代码也就会非常难以阅读和理解。3.5.1 开发控制(续)配置管理配置管理(续续)配置审查配置审查(config
31、uration audit)可以确保基线是完整和精确的。审查通常使用下面两种独立方法中的一种进行的:复查基线中的每个实体,并将它们与投入使用的系统做比较;或者仅仅从大型系统中抽取小部分做抽样审查以确保系统的一致性。状态说明状态说明(status accounting)将记录关于组件的信息,如所有组件的来源、最新版本、修改历史记录和未决定的修改申请等等。3.5.1 开发控制(续)配置管理配置管理(续续)上述4类活动由配置和修改控制组配置和修改控制组(CCB,configuration and change control board)统一执行。CCB包含系统相关不同群体代表,负责复查和改进各种修
32、改申请。配置管理通过保护程序和文档的完整性很好地实现了消除无意的系统威胁并预防恶意威胁的目标。在系统运行阶段,开发人员只能通过CCB来访问运行成品程序。3.5.1 开发控制(续)从错误中吸取教训从错误中吸取教训 在设计和创建系统时,可以把决定做成文档,不仅要记录决定和做出该决定的原因,还要记录不做出某个决定的原因还要记录不做出某个决定的原因。从这些信息中,可以创建检查清单和指导方针帮助系统开发,保证我们不会犯同样的错误,并使其他系统开发人员不犯相同的错误。3.5.1 开发控制(续)程序正确性证明程序正确性证明 计算机安全原理指出不可能确定两个程序是否做同样的事情。这一结论是从“停机问题”推导来
33、的,因此,确定程序是否安全从理论上来说非常困难。程序核实程序核实(program verification)的技术可以论证某些特定程序正确,但仍然有很多因素阻碍着它的发展。1)正确性证明依赖于程序员或逻辑学家将程序语句翻译为逻辑表达。如果程序发现是有错误的,错误也可能出现在翻译中。2)从最初断言和语句涵义中得出正确性的证明是非常难的,进行证明的逻辑引擎也运行得很慢。正确性的证明不适合大型程序。3)现今程序核实的发展远不如代码产品。所以,正确性证明还没有在大型产品中普遍运用。3.5.1 开发控制(续)编程实践的小结编程实践的小结 在任何系统开发中,没有一项管理或技术可以保证在生产率、可靠性和简易
34、性上有哪怕一个数量的改进。任何技术都不能保证软件开发过程中没有错误发生,应该对新技术采取怀疑态度,确保每种新技术确实可信和有效。3.5.1 开发控制(续)程序开发的标准程序开发的标准 可以通过以下几种指南来实施软件开发的管理控制:1)设计标准,包括使用专门设计工具等。2)文档、语言及编码风格标准。3)编程标准,包括强制对等复查等。4)测试标准,如采用程序验证技术等。5)配置管理标准,控制对稳定、完整程序单元的访问和修改。#在共同的框架下,使得每个人都不是不可缺少的,且一个项目的经验可以为下一个项目利用。此外,安全审计安全审计(security audits)可以保证标准被贯彻。3.5.1 开发
35、控制(续)过程标准过程标准 美国软件工程研究所开发了CMM(Capability Maturity Model)来评价组织机构,而不是产品,ISO的ISO 9001在某种程度上类似CMM。过程模型过程模型(process model),是检查一个组织怎么做一件事情,而不是已经做了哪些事情。秩序、结构和一致性可以导致软件项目的成功,但不能确定是唯一的可行方式。3.5.2 程序控制 人类的创造性可以让人们在失败中吸取教训,逐渐形成原则。好的软件开发人员会充分理解安全的重要性并将安全因素很好地融入开发过程。3.6 本章总结 本章的内容涵盖了计算机安全中的开发部分:安全漏洞的种类和影响,无意漏洞和恶意代码以及能控制威胁的技术。控制的意义并不仅限于限制某些行为,控制对系统的整体性能做出了非常积极的贡献。安全特性是控制目标的一个重要方面。谢谢!谢谢!