157
第 3 第 第第第第

第 3 章 程序安全

Embed Size (px)

DESCRIPTION

第 3 章 程序安全. 本章要点. 具有安全隐患的编程错误 恶意代码 防止恶意代码和脆弱性的程序开发控制 控制程序运行时的缺陷. 程序构成了一个计算机系统的很多部分,因此多种形式保护程序是计算机安全的核心。我们将所有代码片称之为 “程序” (program) 。 这里需要提出两个重要问题:怎样消除程序中的缺陷?在程序有缺陷的情况下,如何保护计算机资源? 本章讨论的是一般的程序话题,包括程序编写。程序安全中一个重要问题是 信任 。信任问题是指:假设提供一个已完成的程序,如何来确定它的安全性或者说如何以最安全的方式使用它?答案是采用独立的第三方的评估。. - PowerPoint PPT Presentation

Citation preview

Page 1: 第 3 章 程序安全

第 3 章 程序安全

Page 2: 第 3 章 程序安全

本章要点 具有安全隐患的编程错误 恶意代码 防止恶意代码和脆弱性的程序开发控

制 控制程序运行时的缺陷

Page 3: 第 3 章 程序安全

程序构成了一个计算机系统的很多部分,因此多种形式保护程序是计算机安全的核心。我们将所有代码片称之为“程序” (program) 。这里需要提出两个重要问题:怎样消除程序中的缺陷?在程序有缺陷的情况下,如何保护计算机资源?

本章讨论的是一般的程序话题,包括程序编写。程序安全中一个重要问题是信任。信任问题是指:假设提供一个已完成的程序,如何来确定它的安全性或者说如何以最安全的方式使用它?答案是采用独立的第三方的评估。

Page 4: 第 3 章 程序安全

3.1 安全程序 评估程序安全与软件质量的评估相似,一

种评估软件安全性或质量的方法是让人们列出能反映该软件整体安全的那些特性。然而,不同的人有不同的答案。人们对软件质量的总体设想也会影响对安全性的评估。一般而言,开发者把错误的数量和种类作为衡量产品质量的依据。

Page 5: 第 3 章 程序安全

当一个人在从事软件活动的过程中有所疏失时,我们称之为过失 (error) 。过失可能会在计算机程序中导致一个错误 (fault) ,或者一个不确定的步骤、命令、过程或数据定义。一个单独的过失可以产生很多错误,一个错误可以隐藏在任何产品的开发和维护中。

一次失效 (failure) 就是对系统要求行为的一次违反。一次失效意味着系统没有按照需求执行。

错误是对系统的内部观点而言的,是开发者所见到的;而失效则是对系统的外部观点而言的,是用户看到的问题。

Page 6: 第 3 章 程序安全

3.1.1 修改错误 修改错误是评估安全质量的一种方法。计算

机安全工作建立在“查找错误并打补丁” (penetrate and patch) 的模式上。分析专家在该模式下寻找错误,并给错误打上补丁。

Page 7: 第 3 章 程序安全

3.1.1 修改错误 ( 续 )

缺陷: 1) 修补指定问题的压力使得人们仅仅关注

错误本身,而不是与之相关的上下文环境。 2) 在离错误较远的区域,其副作用不明显。

3) 修补一个问题时常导致其他地方的失败,

或者说补丁仅仅解决一个地方的问题,而没有解决相关地方的问题。

4) 打补丁可能会影响系统的功能和性能,所以补丁经常不能恰当地修补系统错误。

Page 8: 第 3 章 程序安全

3.1.2 意外行为 “ 程序安全缺陷” (program security flaw)

是由于程序的脆弱点而引起的不恰当的程序行为。 “脆弱点”和“缺陷”这组词与“错误”和“失败”这组词之间并没有直接的对应关系。一个缺陷可以是一个错误或是失败,而脆弱点经常用来描述某一类缺陷,诸如缓冲区溢出。尽管不一致,但应该记住:我们必须从两个方面来看待脆弱点和缺陷,即起因和影响。

程序安全性缺陷可以来源于任何种类的软件错误。有必要将程序缺陷划分为两种逻辑类别:由开发者的疏忽所引起的错误和恶 ( 有 ) 意设计的缺陷。

Page 9: 第 3 章 程序安全

3.1.2 意外行为 ( 续 )

分类帮助我们理解一些方法,用以防止将缺陷有意或无意地引入到以后的代码编写中。一个因疏忽而引起的错误给用户及其组织带来的损失可能与恶意漏洞带来的损失相当。计算机攻击 (cyber attack) 即有意的安全事件,是如今最大的安全威胁。

从根本上说安全是困难的,安全时常与有效性和性能相冲突,而且错误的安全解决方案会阻碍安全编程的真实进展。我们还没有技术来消除或解决所有的程序安全缺陷。原因有两个:

Page 10: 第 3 章 程序安全

3.1.2 意外行为 ( 续 )

1) 程序控制是在单独的程序和程序员的级别上实施的。功能测试是解决程序“应该做什么”的问题,而安全测试还要确定 “不应该做什么” 的问题。要保证程序精确地按照设计者和用户的意图来执行而没有其他的行为,这几乎是不可能的。在一个复杂的大型系统中,不管设计者或程序员的意图何在,许多相关模块都以各种各样难以控制的方式交织着。巨大的规模和复杂性使得我们不可能去预防和检查所有缺陷。想要植入恶意代码的程序员可以利用系统的不完整性成功地将漏洞隐藏其中。

Page 11: 第 3 章 程序安全

3.1.2 意外行为 ( 续 )

2) 程序设计和软件工程技术的发展迅速远远超过了计算机安全技术的发展速度。所以我们经常发现自己还在努力保护去年的技术,而软件开发者却正迅速地采用当前最新的技术了。

# 尽管如此,我们可以通过理解什么导致错误以及怎样阻止它,来开发技术和工具,保护大多数计算机的应用程序。

Page 12: 第 3 章 程序安全

3.1.3 缺陷类型 Landwehr等提出了一种关于程序缺陷的分类

法,首先分为有意和无意的缺陷。进一步将有意缺陷细分为恶意和非恶意的类型。无意的缺陷分为 6 类:

失效过失 ( 不完善或不一致 ) :许可权核查。

域过失:对于数据的受控访问。 序列化和混淆:程序流顺序。 不充分的识别和鉴别:授权的基础。 边界条件违规:首次或末次案例失效。 其他可以利用的逻辑过失。

Page 13: 第 3 章 程序安全

3.2 非恶意的程序漏洞 3.2.1缓冲区溢出 问题说明 定义 1 缓冲区(或数组、字符串)是一个

用来存储数据的空间。缓冲区位于内存中。由于内存是有限的,所以缓冲区的容量也是有限的。因此,在许多程序设计语言中,程序员必须声明缓冲区的最大容量,以使编译器能留出所需的空间。

Page 14: 第 3 章 程序安全

3.2.1缓冲区溢出 ( 续 )

C 程序中:char sample[10];

sample[10]=‘B’;

sample[i]=‘B’; // 执行过程确定 i的值

Page 15: 第 3 章 程序安全

3.2.1缓冲区溢出 ( 续 )

若有:for(i=0;i<10;i++)

sample[i]=‘A’;

sample[10]=‘B’;

图 3.1 缓冲区会溢出的位置

Page 16: 第 3 章 程序安全

3.2.1缓冲区溢出 ( 续 )

安全含义 一个非恶意的过失造成的缺陷仍然会带来危害,因为一个恶意攻击者会利用这些缺陷。攻击者可以把数据插入到紧跟缓冲区的空间中以造成损害,可以诱使系统执行那些已经计划好的指令代码。这里,给出两类经常使用的缓冲区溢出攻击。

一类是,攻击者可能替换系统空间中的代码,并有可能提高自身的权限。

另一类是,攻击者可能会利用堆栈指针或返回值的寄存器。

Page 17: 第 3 章 程序安全

3.2.1缓冲区溢出 ( 续 )

另一种缓冲区溢出在参数值被传递到程序中时发生,特别是当参数值被传递到 Web服务器上时。例如,当参数转递到 URL 中,语法是: http://www.somesite.com/subpage/userinput.asp?parm1=(808)555-1212&parm2=2009Jan17

(808)555-1212 可能是电话, 2009Jan17 可能是日期。攻击者可能想了解一个非常长的电话号码,服务器做何反应,如, 500位或 1000位。这时程序会崩溃吗?会按照可以接受的方式崩溃吗?

Page 18: 第 3 章 程序安全

3.2.1缓冲区溢出 ( 续 )

带数组的高级语言出现时,缓冲区溢出就随之出现了。起初给程序员和用户带来的困扰很小,最多不过出现系统崩溃。而攻击者利用它首先使系统崩溃,然后制造出可控制的故障,这就导致了严重的安全问题。

Page 19: 第 3 章 程序安全

3.2.2 不完全验证 问题说明 还是, http://www.somesite.com/subpage/useri

nput.asp?parm1=(808)555-1212 &parm2=2009Jan17 ,参数 parm2表示日期,若输入 1800Jan01 、 1800Feb30 、 2048Min32 、 1Aardvark2Many 会发生怎样的情况?

一种可能是,系统将由于尝试处理不正确的数据类型,而发生灾难性故障。另一种可能是接收到这些错误参数的程序将继续运行而得出错误的结果。

Page 20: 第 3 章 程序安全

3.2.2 不完全验证 ( 续 )

一种解决方法是预测出所有潜在可能发生的问题。通过提交验证技术,程序员可能避免用户无意制造的错误。然而,由于用户可以操作和修改 URL ,所以这种改进仍然脆弱。在这种情况下,提交的数据并没有经过完善验证,那些敏感的数据处于公开和不受控制的状态。

Page 21: 第 3 章 程序安全

3.2.2 不完全验证 ( 续 )

安全含义 不完全的参数验证很容易被利用。例如, Things公司专门经营客户产品。如果客户想要购买 20 个编号 555A 的物品。每个物品的售价 10元,则网站可以计算总价格是 200元,客户端的浏览器会自动按格式填充数据: http://www.things.com/order.asp?custID=101&part=555A&qy=20&price=10&ship=boat&shipcost=5&total=205

攻击者可以做如下修改 http://www.things.com/order.asp?custID=101&part=555A&qy=20&price=1&ship=boat&shipcost=5&total=25

Page 22: 第 3 章 程序安全

3.2.3 “检测时刻到使用时刻”错误 问题说明 现代处理器和操作系统经常改变指令和程

序的执行顺序。访问控制是确定具有访问权限的人或进程才能进行相应的访问,主要由访问策略实现。访问策略的执行代理对访问请求进行仲裁。检查时刻到使用时刻 (time-of-check to time-of-use, TOCTTOU)的漏洞与仲裁在执行中受到诱骗有关。该漏洞也称为序列化 (serialization)漏洞或同步 (synchronization)漏洞。

Page 23: 第 3 章 程序安全

3.2.3 “检测时刻到使用时刻”错误 ( 续 )计算系统的攻击例子

图 3.2 文件访问的数据结构

图 3.3 被修改的数据

# 在访问被检查和检查结果被使用之间的时段,发生一些变化,并导致了检查结果的错误。

Page 24: 第 3 章 程序安全

3.2.3 “检测时刻到使用时刻”错误 ( 续 )

安全含义 检查一个动作而执行另一个动作 ,是一个无效访问控制的原因。

解决的办法有: 1) 确保关键参数在失控时不暴露。访问控制软件一直掌握请求数据直到请求动作完成。 2) 确保序列的完整性。也就是在验证期间禁止中断,或验证程序复制数据到程序空间,并基于该数据完成验证。

Page 25: 第 3 章 程序安全

3.2.4 非恶意程序漏洞的结合使用 以上三种漏洞还可以结合起来使用,以三叉式攻击出现。攻击者先借助缓冲区溢出来破坏机器上运行的任意代码,同时利用检查时刻至使用时刻的漏洞来添加一个新的系统用户。接下来,攻击者以新的用户身份登录系统并应用不完整的参数检查漏洞获得一定权限或做其他事情。因此,对任何一个小漏洞我们都必须了解并保护它不受攻击。

Page 26: 第 3 章 程序安全

3.3 病毒和其他恶意代码 就程序本身而言很少对安全性构成威胁。

程序对数据进行操作,只有当数据和状态发生改变并满足其触发条件时,才采取行动。程序所做的大部分工作对用户来说是不可见的,所以一般用户不太可能发现它们在进行危险的活动。由于用户不能对计算机的程序和数据进行观察,攻击者可以编写自己的程序作为工具来访问和修改其他程序的数据。

Page 27: 第 3 章 程序安全

3.3.1 关注恶意代码的原因 恶意代码可以以意料之外的方式运行,我

们把恶意代码看作是系统中的潜伏者,它可能是正在运行的程序的全部或一部分。

恶意代码是如何进入系统的?当安装一个大型软件包,会运行诸如 INSTALL 或 SETUP 之类的命令;当浏览站点并盲目地从中下载应用程序,如 Java applet 或 Active X等。在这些情况下,大量的程序与数据被传送,大量新的文件被创立,已经存在的文件被修改,而作为用户其实对这些实际的过程并不知情。

Page 28: 第 3 章 程序安全

3.3.1 关注恶意代码的原因 ( 续 ) 恶意代码极具破坏性 其他程序能做到的事情,恶意代码也能做

到。恶意代码可能什么也不做,直到产生一些触发事件来驱动它运行。恶意代码每一次都可以做不同的事情。通常说,恶意代码行为的可预测性和两岁小孩行为的可预测性相似:大体我们知道他想做什么,甚至知道某些特定环境下的行为,但是他也经常能做出超乎想象的事情。

恶意代码在非法获取的用户授权下运行,与用户有相同的权限,但无需用户授权,甚至无需用户知道。

Page 29: 第 3 章 程序安全

3.3.1 关注恶意代码的原因 ( 续 )

恶意代码的长期存在 恶意代码不是现在才出现的一种新现象,早在 1970年Ware 和 Anderson 就准确地描述了病毒的威胁、程序的脆弱点和程序安全缺陷,特别是那些恶意部分。恶意代码将仍然继续存在下去。研究它们的外在表现和工作原理对我们阻止它们进行破坏活动,或者至少减弱它们的影响十分重要。

Page 30: 第 3 章 程序安全

3.3.1 关注恶意代码的原因 ( 续 ) 产品漏洞和漏洞利用代码出现的时间间隔正在缩短。

一般利用过程符合如下序列: 1) 攻击者发现一个先前的未知漏洞 2) 生产商知道这个漏洞 3) 有人开发出代码 ( 称概念证明 )证明在特定设置下

的漏洞 4) 生产商开发并发布一个针对该漏洞的补丁或者对策 5) 用户采取相应保护措施 6) 有人扩展概念证明或者原始漏洞定义得到一个实际攻击

一旦用户在实际攻击前接受并采取了相应保护措施,就可以避免灾难发生。一种攻击在保护措施可获得之前发生就是 0天利用 (Zero day exploit) 。

Page 31: 第 3 章 程序安全

3.3.2 恶意代码的种类 恶意代码 (malicious code) 和欺诈程序 (rogu

e program) 是以破坏为目的的一类程序或部分,由一个代理 (agent) 编制,在软件中造成不期望的结果。代理是指该类程序的作者或是促成程序发布的人。

Page 32: 第 3 章 程序安全

3.3.2 恶意代码的种类 ( 续 )

病毒是一种复制自身并将恶意代码传递给正常程序的程序,它通过修改正常程序做到这一点。术语“病毒” (virus) 的得名是因为它与生物学中的病毒具有相似特征,被它感染的系统将继续感染其他系统以破坏其或使病毒与其共存。

瞬时病毒 (transient virus) 的生命周期依赖于它的宿主的生命周期,病毒所依附的程序开始运行时,病毒也开始运行;病毒所依附的程序终止时,病毒也终止运行。

长期性的寄居病毒 (resident virus) 常驻在内存里,保持激活状态或作为独立的程序被激活而不管它寄宿的程序是否终止运行。

Page 33: 第 3 章 程序安全

3.3.2 恶意代码的种类 ( 续 )

特洛伊木马 (Trojan horse) 是这样一种恶意代码:它除了程序所具有的基本功能之外,还有一些不易被人发觉的破坏作用。

逻辑炸弹 (logic bomb) 也是恶意代码中的一种,它将在特定条件产生时被“引爆”。

定时炸弹 (time bomb) 是逻辑炸弹的一种,它的触发条件是时间或日期。

Page 34: 第 3 章 程序安全

3.3.2 恶意代码的种类 ( 续 ) 陷门 (trapdoor) 或后门 (backdoor) 是某些程序所具有

的特征,人们可以利用这个特征进入该程序,而不是通过明显、直接的调用,或其他需要特殊权限的进入方式。

蠕虫 (worm) 是一种通过网络大量传播自身副本的程序。蠕虫与病毒的基本区别在于蠕虫的操作都是通过网络来进行的,而病毒可以通过任何介质进行传播 (但通常利用的是已复制的程序或数据文件 ) 。另外,蠕虫的自身复制都是以独立程序的形式传播的,而病毒的自身复制则必须嵌入到其他程序中来传播。

“ 兔子” (rabbit) 定义为一种病毒或一种蠕虫,“兔子”会无限制地复制自己以消耗计算机的系统资源。

Page 35: 第 3 章 程序安全

3.3.2 恶意代码的种类 ( 续 )表 3.1 恶意代码的类型 代码类型 特征病毒 将自身注入到程序中并传播自己的副本到其他程序中

特洛伊木马 包含意料之外的附加功能逻辑炸弹 当满足一定条件时激发一些行为定时炸弹 当满足一指定时间条件时激发一些行为

陷门 允许未授权的访问蠕虫 通过网络传播自身副本“兔子” 无止境复制自己以耗尽系统资源#由于“病毒”常常是对所有恶意代码的统称,且各类恶意代码之间的界限很模糊,因此讨论中通常不严格区分这些概念。另外,两种或两种以上的恶意代码结合可以产生新的后果。

Page 36: 第 3 章 程序安全

3.3.3 病毒是怎样植入到正常程序中的 病毒要复制必须处于激活状态,完成自己

的破坏活动,并进行传播。要使病毒运行有很多方法。例如,在 CD-ROM 上的含有病毒的程序,可以在 CD-ROM 运行时将自己安装到目标系统的硬盘,并感染所有正在内存中的运行的程序。这个过程开始需要人为干预,之后就可以自动传播。另一种更普遍的病毒植入方式是将其作为附件附加在电子邮件中,只要受害者打开电子邮件,病毒就可以开始工作。病毒可以伪装成各种文件,而邮件处理软件为了用户方便,常常为用户自动打开附件。

Page 37: 第 3 章 程序安全

3.3.3 病毒是怎样植入到正常程序中的 ( 续 )

挂接性病毒 一旦病毒程序注入到其他程序中,只要那

些程序一运行,病毒就将被激活。最简单的情形是,病毒将自己的一份副本添加到可执行文件的第一条指令之前。这种植入方式非常简单有效,病毒编写者无需知道被注入程序的情况,被注入程序不过是病毒的一个载体。而用户也不会知道病毒的存在,因为原始程序会像往常一样工作。

Page 38: 第 3 章 程序安全

3.3.3 病毒是怎样植入到正常程序中的 ( 续 )

图 3.4 病毒被添加到程序

挂接性病毒 ( 继 )

Page 39: 第 3 章 程序安全

3.3.3 病毒是怎样植入到正常程序中的 ( 续 ) 包裹性病毒 另一种植入方式是在原始程序运行之前和

之后都由病毒来控制运行。常见的如,对组成文件清单的程序感染。

图 3.5 病毒包裹程序

Page 40: 第 3 章 程序安全

3.3.3 病毒是怎样植入到正常程序中的 ( 续 ) 整合并替换性病毒 第三种植入方式是病毒用自身替换目标代码,并

将自己整合进原始程序中。编写病毒的人必须了解原始程序的结构。病毒可以模仿目标程序的功能,同时进行自己的工作,也可以忽略目标程序的功能,完成自己的工作。

图 3.6 病毒整合程序

Page 41: 第 3 章 程序安全

3.3.4 文档类病毒 文档类病毒 (document virus) 是目前流传很广的病毒。这种病毒出现在标准格式的文档中,如文字文档、数据库文件、幻灯片、图片或电子表等。这些文件高度结构化,包含高级程序语言的一部分,病毒编写者正是利用这部分进行恶意操作。普通用户只能看见文件内容,于是病毒编写者将病毒注入文档命令部分,如同上面的整合性病毒一样。

Page 42: 第 3 章 程序安全

3.3.5 病毒如何获得控制权 病毒必须替代目标程序而被用户或系统调用。病毒可以通过在文件结构中替换目标程序 T 的代码( 或加入到 T 的代码中去 ) 来使用 T 的名字,这种技术对普通程序适用。

图 3.7 病毒完全替换程序

Page 43: 第 3 章 程序安全

3.3.6 病毒的藏身之地 病毒希望具有下列特性: 1) 不易被检测 2) 不易被清除,也不易失效 3) 传播感染的范围广 4) 可以重复感染宿主程序和其他程序 5) 容易创建 6) 与平台和操作系统无关 几乎没有病毒可以完全符合上述标准,病毒编写者需要考虑主要功能和将植入何处,而根据需要挑选出其中一部分。

Page 44: 第 3 章 程序安全

3.3.6 病毒的藏身之地 ( 续 )

以前,病毒制造者面临的挑战是如何使病毒代码重复执行以大量繁殖。然而现在,一次执行已经可以确保病毒大量繁殖。许多病毒都是通过电子邮件传播的,主要有两种方式:在第一种方式中,病毒编写者生成新的电子邮件并发送给受害者地址簿里所记录的用户。在第二种方式中,病毒编写者让用户在不知到的情况下将被感染的文件转发给其他用户。只要病毒的效果没有显现,被感染的文件就有可能被用户发出。

Page 45: 第 3 章 程序安全

3.3.6 病毒的藏身之地 ( 续 )

一次运行方式 目前大多数病毒只要运行一次就能感染系

统。例如,邮件附件中的病毒只要将其打开,内藏的病毒就能运行。

引导扇区病毒 在计算机启动时,首先由固件取得控制权

以决定哪些硬件组件将被使用,并预先测试它们,之后再把控制权交给操作系统。操作系统是存放在硬盘上的软件,一些代码会把操作系统从硬盘复制到内存中,并使操作系统取得控制权,这些代码就是引导程序 (bootstrap) ,通常也被称为引导 (boot) 。

Page 46: 第 3 章 程序安全

3.3.6 病毒的藏身之地 ( 续 )

固件的控制权转交过程是这样完成的:固件从磁盘上一处叫引导区 (boot sector) 的特定位置读取一定数目的字节,并把它写入内存中的特定位置,然后跳转至该地址 ( 该地址包含引导程序装载器的第一条指令 ) 。 然后装载器将磁盘中操作系统的剩余部分读入内存。硬件设计者在磁盘上为引导程序装载器保留了空间, PC 上引导区略小于512字节,但装载器大小超过这个大小,因而设计采用了“链式” (chaining)技术。链式 技术在保证大规模数据存储的同时,也使得病毒安装变得简单。

Page 47: 第 3 章 程序安全

3.3.6 病毒的藏身之地 ( 续 )

图 3.8 引导扇区病毒重载代码

# 病毒在计算机启动初期就获得控制权,这样可以避开检测,且由于在启动区域对用户“不可见”,不易为用户察觉。

Page 48: 第 3 章 程序安全

3.3.6 病毒的藏身之地 ( 续 )

驻留在内存中的病毒 对于经常使用的操作系统程序和一些特殊的用户程

序,需要时再装载入内存将会非常浪费时间。所以对于这些代码,就让它们留在内存里,称之为“常驻内存的代码”。常驻内存的程序通常称为“终止后依然留守” (Terminate and stay resident ,TSR) 程序。将病毒植入到常驻内存的代码中,每次运行这些代码,病毒就随之运行,寻找并感染新载体。

病毒也可以修改操作系统要运行的程序表,如, windows 的系统注册表,在其中添加自己的表项。这样即使在内存中清除了病毒副本,在每次机器启动时,病毒仍将再次出现。

Page 49: 第 3 章 程序安全

3.3.6 病毒的藏身之地 ( 续 ) 病毒的其他藏身之地 病毒的另外一个寄居的地方是应用程序。许

多应用程序,如文字处理软件、电子数据表格等都有“宏”功能,它允许用户自定义一系列的命令并通过一个调用来重复使用它们。病毒编写者可以创建一个宏病毒,该宏可以把自己添加到应用程序的启动指令中,而且它还可以把自身副本嵌入到数据文件以感染所有接收文件的用户。

库也是恶意代码的藏身的一个绝佳的地方。此外,编译器、加载器、链接器、在线监视器、在线调试器甚至病毒控制程序都是病毒喜欢寄居的地方。

Page 50: 第 3 章 程序安全

3.3.7 病毒特征

病毒不可能完全隐身,病毒代码必须存储在某个地方,而代码必须在内存中被执行。此外,病毒是以很特别的方式来运行、传播的。病毒的所有这些性质提供了一个暴露它们行踪的特性,称为“病毒特征” (signature) 。病毒特征对编写所谓的病毒扫描 (virus scanner) 程序是非常重要的,病毒扫描程序可以自动侦测到病毒,有时候还可以自动清除病毒。扫描程序搜索内存、永久性存储器,监控程序运行并留意是否有病毒特征。

Page 51: 第 3 章 程序安全

3.3.7 病毒特征 ( 续 ) 例如,病毒扫描程序如果扫描到如下字符串 /default.ida?NNNNNNNNNNNNNNNNNNNNNNNNNNNNNNN NNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNN NNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNN NNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNN NNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNN %u9090%u6858%ucbd3 %u7801%u9090%u6858%ucdb3%u7801%u9090%u6858 %ucbd3%u7801%u9090 %u9090%u8190%u00c3%u0003%ub00%u531b%u53ff %u0078%u0000%u00=a HTTP/1.0

就可以确定有红色代码蠕虫病毒存在。当扫描器识别到一个已知的病毒格式,它就会隔离该病毒,通知用户,并使病毒失效或删除病毒。然而,病毒扫描器只有在得到最新的病毒信息的情况下,才是有效的。

Page 52: 第 3 章 程序安全

3.3.7 病毒特征 ( 续 )

存储模式 大部分病毒都附着于存储介质上 ( 如磁盘 )

的程序中,由于病毒的挂接部分是不变的,这样病毒代码的开始部分就具有可探测的特征。

病毒可以附着于文件,在这种情况下文件长度会增加,也可以删除部分或全部正常程序使文件的大小保持不变。

Page 53: 第 3 章 程序安全

3.3.7 病毒特征 ( 续 )

图 3.9 可辨认的病毒格式

存储模式( 续 )

Page 54: 第 3 章 程序安全

3.3.7 病毒特征 ( 续 )执行模式表 3.2 病毒的预期效果和造成原因

病毒的预期效果 使用手段附着于可执行程序中 修改文件目录 / 写入到可执行程序文件中附着于数据和控制文件 改变目录 / 重写数据 /添加到数据中 /添加数据

到自身驻留在存储器中 修改中断处理地址表获取中断 / 将自身装载入非

短期存储区域感染磁盘 截获中断 /截获系统调用 / 修改系统文件 / 修改

普通执行程序隐藏自身 截获可能暴露自身的系统调用并伪造结果 / 将自

身设置为“隐藏”文件传播感染 感染引导扇区 /感染系统程序 /感染普通程序 /

感染用于控制普通程序运行所要获取的数据防止失效 在失效程序运行前阻止并阻塞其功能 / 在失效前

存储自身副本以供失效以后重新激活

Page 55: 第 3 章 程序安全

3.3.7 病毒特征 ( 续 )

传输模式 病毒可以在启动过程中通过附着在可执行

文件或数据文件中传播。传播本身发生在被感染程序执行期间。且病毒传播不受单一介质和运行模式限制。

Page 56: 第 3 章 程序安全

3.3.7 病毒特征 ( 续 )

多形态病毒 能够变换自己外观的病毒称为多形态病毒

(polymorphic virus) 。简单改变病毒外观相对来说比较容易,很多指令是无效的,如对一个数加 0( 相对于数本身而言 ) 或跳到下一条指令。这些指令有时被称为空指令(no-ops) ,可以散缀在代码中来变形格式。 一个多形态病毒必须不断随机重新放置它自身的所有部分并随机改变所有固定数据。

Page 57: 第 3 章 程序安全

3.3.7 病毒特征 ( 续 )

多形态病毒 ( 续 )

多形态病毒一种简单变种方式是用不同的密钥进行加密,这样病毒的存储形态会各不相同。这种病毒有时称为加密病毒 (encrypting viruses) 。这种类型的病毒必须包含三个不同的部分:一个解密密钥;一段已被加密的病毒代码;一段未被加密的用以说明解密规则的代码。对于这类病毒来说,由于解密规则本身或者对解密规则库的调用必须是公开的,这样它们就成了该类病毒的特征。

Page 58: 第 3 章 程序安全

3.3.8 病毒源 由于病毒可以变得非常小,这样就能深入隐藏在其

他更大更复杂的程序中。一个 200 行代码病毒可以被分成两个各有 100 行代码的包,并互相跳转。这种 100 行代码的病毒包可以很方便地隐藏在编译器、文件管理器或其他大型程序中。

判定两个程序是否等价对查找病毒十分有用。两个模块的结果也可能会有极细微的差别,两者的结果是否与安全性相关也很难确定。这些差别可能是良性的,也可能是病毒感染的一个标记。所以,我们不太可能开发一种程序以区分被感染的模块和未被感染的模块。此外,在系统执行时清理病毒必须使检测和消灭病毒的速度超过病毒的传播速度。

Page 59: 第 3 章 程序安全

3.3.9 防止病毒感染 防止病毒感染的唯一方法是不要与感染源共享可执行代码。遵循这条原则曾经是很容易的,但现在却变得越来越困难了,原因主要是可执行文件的概念越来越模糊。

微软开发的专有格式文件有些不为人知的特性,可以为病毒代码编写者利用。编写可以将病毒取一个不合理的后缀名,如 doc 或者 ppt ,不知情的接受者在打开文件的同时也就执行了其中的恶意代码。

Page 60: 第 3 章 程序安全

3.3.9 防止病毒感染 ( 续 )

人们还发现,可执行代码可以隐藏在包含大量数据集合的文件中,如图片和只读文件中,这对发现隐藏病毒代码带来了很大困难。

因为我们不可能总是知道哪些外界资源被感染,我们应该假定外界的资源都被感染了。对我们有利的一点是我们知道何时从外界接收了代码,对我们不利的一点是我们不可能总与外界隔绝。

群体计算机与外界隔离对防止病毒有益,但做到这一点越来越难。

Page 61: 第 3 章 程序安全

3.3.9 防止病毒感染 ( 续 )

防止病毒的措施:1) 只使用从可信赖的商家获取的商业软件2) 在一台孤立的计算机上测试所有的新软件3) 只有在确认了附件是安全的以后才能打开

它4) 制作一个可供恢复的系统镜像文件,并保存在安全之处

5) 为可执行的系统文件制作备份并保存6) 有规律地使用病毒扫描器并时常更新

Page 62: 第 3 章 程序安全

3.3.10 关于病毒的误解和真相 由于病毒对计算机通信经常造成剧烈的冲击,

成为新闻的重点报道对象,然而,对病毒仍然存在一些误解。以下是有关病毒的一些流行说法:

1) 病毒只会感染微软的 Windows 系统 (只要包含计算机代码的设备都可能感染病毒 )

2) 病毒可以篡改“隐藏”和“只读”属性的文件 ( 这两种机制都是通过软件实现,病毒完全可以覆盖原来的软件保护 )

3) 病毒仅孤立存在于数据文件、 Word 文档文件或程序中 ( 它们的界限在实际应用中不明显 )

Page 63: 第 3 章 程序安全

3.3.10 关于病毒的误解和真相 ( 续 )

4) 病毒只能通过磁盘或只能通过电子邮件传播( 任何共享方式都有可能传播病毒 )

5) 在彻底断绝电源并重新启动以后,原先的病毒不可能驻留在内存中 (但这不意味着病毒被清除和启动完成后病毒又重新驻留在内存中 )

6) 病毒不会感染硬件 ( 如果硬件包含被程序控制的可写存储器,那么存储器也会成为病毒攻击的目标 )

7) 病毒既可能是恶意的也可能是良性的或善意的

Page 64: 第 3 章 程序安全

3.3.11 第一个恶意代码的例子: Brain病毒 Brain病毒是最早出现的病毒之一,也是被研究得最彻底的病毒之一。任何类型的磁盘在遭受了该病毒的攻击后,磁盘的卷标名称都会被改为“ BRAIN” , Brain病毒也因此而得名。人们认为这种特殊的病毒起源于巴基斯坦,只对运行在 PC 机上的微软操作系统平台进行攻击。该病毒拥有大量的变种,因此,人们相信该病毒的源代码是一个地下的病毒编写团队发布的。

Page 65: 第 3 章 程序安全

3.3.11 第一个恶意代码的例子: Brain病毒 ( 续 ) Brain 病毒的行为

病毒首先将自己定位在上端内存,然后通过执行一个系统调用来重置上端内存的边界,使之在病毒体的下方。这样,病毒就可以不受干扰地独立运行了。病毒重置中断地址表指向自己以捕获 19号中断 (磁盘读取 ) ,然后将 6号中断 (未使用 ) 地址设置成为之前 19号中断的地址。这样,病毒就将磁盘读取的系统调用隐藏起来了。病毒处理对引导扇区的信息读取 ( 将被移动到“坏”扇区中的初始引导信息恢复返回给系统 ) 。其他磁盘调用在执行 6号中断时交给正常的磁盘读取程序来处理。

病毒只在传播感染过程中才会有所表现。病毒产生的大量变种会抹掉磁盘中的数据或损坏文件分配表。

Page 66: 第 3 章 程序安全

3.3.11 第一个恶意代码的例子: Brain病毒 ( 续 )

Brain 病毒的传播方式 Brain病毒一般隐匿于引导扇区和磁盘上 6 个其他扇

区中。其中 1 个扇区包含从引导扇区中移过来的初始化启动代码。剩下的扇区中有 2 个包含病毒代码的剩余部分,其余 3 个扇区包含了上面 3 个扇区内容的副本。病毒将这 6 个扇区标注为“有故障的”(faulty) ,操作系统就不会使用它们了 ( 当然,低级调用可以强制性地使硬盘读取数据,而不管该扇区是否被操作系统标注为“有故障的”坏扇区 ) 。病毒不会终止系统的启动过程。

一旦被读入到内存后,病毒将截获对磁盘的读取请求。对每一次读取过程,病毒都会先读取磁盘的引导扇区并检查第 5 个和第 6 个字节是否是十六进制数的 1234( 这就是该病毒的特征 ) 。如果是,就表明该磁盘已经被感染,否则就感染该磁盘。

Page 67: 第 3 章 程序安全

3.3.11 第一个恶意代码的例子: Brain病毒 ( 续 )

关于 Brain 病毒的小结 Brain病毒使用了一些普通病毒都爱玩弄的

把戏,如隐藏在引导扇区中,截获并隐藏中断等,其为之后的病毒提供了一个原型。

Brain病毒总的表现比较温和。

Page 68: 第 3 章 程序安全

3.3.12 另外一个例子:因特网蠕虫病毒 1988年 11月 2日的傍晚,因特网上诞生了

第一个蠕虫病毒,并给网络造成了严重破坏。

编写和发布该蠕虫病毒的是 Cornell大学的一名研究生 Robert T. Morris, Jr. 。

Page 69: 第 3 章 程序安全

3.3.12 另外一个例子:因特网蠕虫病毒 ( 续 )

蠕虫病毒的行为 Morris希望该病毒完成以下三个主要任务: 1) 自己决定传播路径 2) 传染 3) 隐藏自己,使自己不被发现

Page 70: 第 3 章 程序安全

3.3.12 另外一个例子:因特网蠕虫病毒 ( 续 )

蠕虫病毒的危害 1) 蠕虫病毒最大危害就是侵吞系统资源。蠕虫病毒最显而易见的后果就是被感染机器的性能显著下降。

2) 蠕虫的第二个危害是可以断绝因特网上大量系统间的连接。

3) 许多工作不能在与外界隔离的情况下展开。系统管理员无法在切断因特网的系统上与其它安装点的副本进行信息交流,所以不能获知网络的状态、容量和防御等信息。

Page 71: 第 3 章 程序安全

3.3.12 另外一个例子:因特网蠕虫病毒 ( 续 )

蠕虫病毒的工作机制 蠕虫利用了 UNIX操作系统的几种已知漏洞

和配置上的失误,完成了三个主要任务: 决定向何处传播 蠕虫采用了三种技术来确定潜在的受害机器。 1) 漏洞是用户与系统关联的错误,蠕虫利用

该漏洞来猜解用户口令 2) 漏洞是关于 finger 的,该程序的作用是向

其他提出请求的计算机提供关于系统所有用户的信息

3) 漏洞是与 sendmail 程序中的陷门有关的

Page 72: 第 3 章 程序安全

3.3.12 另外一个例子:因特网蠕虫病毒 ( 续 )

传染 当蠕虫确定了目标机器后,就发送引导程

序装载器到目标机器。该装载器是一段 99行的 C 代码程序,它将在目标机器上编译和运行。引导程序装载器将在随后从原来的宿主机器上获得蠕虫程序的剩余部分。在消息传递过程中,实施了一次性口令保护措施,保证活动的秘密。 这种方法可以防止系统管理员获取蠕虫的剩余部分以进行后续分析。

Page 73: 第 3 章 程序安全

3.3.12 另外一个例子:因特网蠕虫病毒 ( 续 ) 隐藏自己,不被人们发现 蠕虫的长度都设计得很合理以防在宿主机

上被发现。例如,在获取剩余蠕虫部分的过程中,一旦出现传输错误,装载器就将清零复位并清除所有已经传输的代码,然后退出。

蠕虫获得全部代码,就将其加密载入内存,并在硬盘上删除原始副本。蠕虫还会周期性地改变自己的名字和进程标识符。

Page 74: 第 3 章 程序安全

3.3.12 另外一个例子:因特网蠕虫病毒 ( 续 ) 关于蠕虫病毒的小结 蠕虫病毒给因特网带来了强烈的冲击,并且

在当时引起了学术界和研究者的广泛关注。感染过的站点纷纷关闭了可以被蠕虫利用的安全漏洞加强了安全措施。然而,对因特网站点漏洞的安全分析检查发现,许多同样的安全漏洞仍然存在,如果类似的蠕虫病毒再次发动攻击,也许不会像之前那么成功,但仍会造成不便。

蠕虫的温和性体现在它仅仅传播给其他系统,但并不毁坏它们。新的蠕虫变种可能就不会那么温和了。

Page 75: 第 3 章 程序安全

3.3.12 另外一个例子:因特网蠕虫病毒 ( 续 )

关于蠕虫病毒的后果 蠕虫危害的一个积极结果是美国建立了一个基础体系,并以此来报告和修正恶意及非恶意的漏洞。这也就是计算机应急响应小组 (Computer Emergency Response Team, CERT) 在 Carnegie Mellon大学成立。它们致力于收集和发布关于恶意代码攻击的信息以及对付它们的方法。实践表明,安全来自于积极细致的保护和行动,而不是来自于对问题熟视无睹和无所作为。

Page 76: 第 3 章 程序安全

3.3.13 更加危险的恶意代码:红色代码 红色代码出现在 2001年中期,引起了破坏

性后果。当年在 6000000台易感染服务器中,感染率达 1/8 ,造成的损失超过 20亿美元。

红色代码的行为 红色代码的行为有两个步骤:感染和传播。

该蠕虫利用了微软 IIS(Internet Information Server) Web服务器软件的脆弱点来感染服务器。它利用动态连接库 idq.dll 中的缓冲区溢出漏洞而驻留在服务器内存中。为了寻找传播目标,红色代码在 PC 机的 80端口检查其他 PC 的 IP 地址,以确定该服务器是否易受攻击。

Page 77: 第 3 章 程序安全

3.3.13 更加危险的恶意代码:红色代码 ( 续 )

红色代码的危害 第一个版本是用 HELLO! Welcome to http://www.worm.com! Hacked by Chinese!

篡改站点网站页面,之后完全由日期决定行为。每月 1-19日,蠕虫将产生 99 个线程从相同 IP地址为起点扫描其他脆弱计算机。每月 20-27日,蠕虫向美国站点 www.whitehouse.gov 发动分布式拒绝服务攻击。每月 28日到月底,蠕虫将什么也不干。

之后的版本对传染速度进行优化并加入了特洛伊木马 。

Page 78: 第 3 章 程序安全

3.3.13 更加危险的恶意代码:红色代码 ( 续 )

红色代码的工作机理 红色代码的目标是运行了 IIS 的、易受攻击的

个人计算机。但在 Windows NT 和 Windows 2000 的表现不同。后期的版本在被感染服务器上建立陷门。红色代码将 %windir%\cmd.exe 复制在以下 4 个地方:

c:\inetpub\scripts\root.exe c:\progra~1\common~1\system\MSADC\root.exe

d:\inetpub\scripts\root.exe d:\progra~1\common~1\system\MSADC\root.exe

Page 79: 第 3 章 程序安全

3.3.13 更加危险的恶意代码:红色代码 ( 续 ) 红色代码的工作机理 ( 续 ) 红色代码可以将自带的 explorer.exe复制于 C盘

或 D盘,这样 Windows 运行的是恶意副本,而不是正常 explorer.exe 程序。这一木马程序首先运行正常的 explorer.exe 程序,但其将篡改系统注册表,使一些文件保护失效,这样就保证它对一些目录具有读、写和执行的权限。即使explorer.exe停止运行其中的木马程序依然可以有一个虚拟路径进入系统运行于后台。

在传播方面,蠕虫创建 400 个或 600 个线程,在24 或 48小时后向其他机器传播,这里线程都为并行非阻塞式嵌套字方式。然后,强制重启系统,删除蠕虫只在系统中保留木马和后门。早期红色代码攻击 www.whitehouse.gov ,之后的版本则随机选择与宿主机较近的 IP 地址攻击。

Page 80: 第 3 章 程序安全

3.3.13 更加危险的恶意代码:红色代码 ( 续 )

关于红色代码的小结 红色代码是“信息化战争的一个小测试”。红色代码安全威胁的根源在于,人们时常购买和安装连最低安全标准都未达到的产品,而且不愿意把资源投入到大规模、持久的补丁开发和错误修正中去。

Page 81: 第 3 章 程序安全

3.3.14 网页上的恶意代码:网页 bug

网页 bug 的行为 网页 bug ,有时也称为像素标记 (pixel tag) 、清晰图片 (clear gif) 、连续图片 (one-by-one gif) 、不可见图片 (invisible gif) 或信标图片 (beacon gif) 。它们都是一些隐藏在文档中的图片,这些文档都是可以使用 HTML标记,如网页、 HTML格式的电子邮件消息或电子数据表格等。这些 bug 对用户而言都是不可见的,但由此可以追踪Web 用户行为。

Page 82: 第 3 章 程序安全

3.3.14 网页上的恶意代码:网页 bug ( 续 )

网页 bug 的效果 假如网上冲浪加载 Commercial.com网页,

其中包含一个为市场和广告公司的站点 Market.com服务的网页 bug ,这个 bug 可以将一个名为 cookie 的文件放到系统的硬盘上。该 cookie 包含了一个标识符,它会记录冲浪习惯并对此做粗略统计。

Page 83: 第 3 章 程序安全

3.3.14 网页上的恶意代码:网页 bug ( 续 )

网页 bug 的工作机制 当在 Commercial.com 上购买某种产品时,

可能会要求各种信息,如: IP 地址、使用的浏览器种类和设置、显示器分辨率、建立连接时间、此前的 cookie记录数据。这样在 Web服务器获得这些信息后, bug 就可以探测用户的个人隐私,甚至从 Web服务器上的日志文件找到 IP 地址并通过其入侵系统。

Page 84: 第 3 章 程序安全

3.3.14 网页上的恶意代码:网页 bug ( 续 )

关于网页 bug 的小结 网页 bug引发了关于隐私的问题。隐私权基金会 (Privacy Foundation) 开发了一个叫 Bugnosis 的实用工具查找网页 bug 。

用户可以从浏览器中禁止 cookie 的使用,或装入 cookie 时通知用户,但这也会给用户带来不便。另外,还可以允许使用 cookie ,但定时清除它们。

Page 85: 第 3 章 程序安全

3.4 有针对性的恶意代码 有一类恶意代码是专门为某一特定系统、

特定应用和特定目的设计的。 3.4.1 陷门 陷门 (trapdoor) 是通往一个模块内部入口,但在设计的文档中没有该入口的记录。陷门在代码开发期间加入,其目的可能是为了测试软件模块,或为将来模块的修改和功能增强提供“钩子” (hook) ,也或者在以后系统失效时提供一个特别通道。除了这些合法的应用外,当程序成为产品后,陷门可使程序员进入程序。

Page 86: 第 3 章 程序安全

3.4.1 陷门 ( 续 )陷门的例子

图 3.10 桩和驱动

# 在模块中插入命令行是已经公认的测试手段。然而,如果测试结束仍将命令行留在模块,就会引起一些问题。它们是未在文档中记录的控制序列,有可能被用作陷门

Page 87: 第 3 章 程序安全

3.4.1 陷门 ( 续 )

陷门的例子 ( 续 )

拙劣的错误检查 (error checking) 是产生陷门的另一个原因。一个好的开发者在设计系统时,会在每个数据使用前检查该数据。这种检查包括确保数据类型是正确的,数据值在允许的范围内。但在一些设计拙劣的系统中,一些不允许接受的数据也能轻易通过检查,并以难以预料的方式使用。

Page 88: 第 3 章 程序安全

3.4.1 陷门 ( 续 )

陷门的例子 ( 续 )

硬件处理器设计的这类安全漏洞是,未定义操作码 (undefined opcode) 有时会执行特定的指令,可能是因为测试处理器的需要,也可能是设计者的疏漏。

陷门并非总是充满恶意,在寻找安全漏洞时,它们也非常有用。但是,必须在文档中很好记录这些陷门,严格控制对它们的访问,并清楚其内在逻辑关系。

Page 89: 第 3 章 程序安全

3.4.1 陷门 ( 续 )

陷门的成因 1) 开发者经常忘记去掉陷门 2) 出于测试目的,刻意将其保留在程序中 3) 出于维护目的,刻意将其保留在程序中 4) 将它作为一个隐蔽的访问方式而刻意将

其保留在程序中 陷门本身没有错,错误发生在当开发者不

需要陷门时,没有及时将其关闭,而成为一个系统脆弱点。

Page 90: 第 3 章 程序安全

3.4.2 salami攻击 这个名字起源于一种制作腊肠的方法:将肉和脂肪间隔着混在一起。 salami攻击用同样的方法将一些不合乎逻辑的数据位结合在一起而产生出惊人的效果。

salami 攻击的例子 假定银行年利息为 6.5% ,帐户余额为 102.87美元,银行每月结算一次利息,则有 31天的某月利息为:

31/365*0.065*102.87 = 0.549 5726 。 通常不会有人为利息由 0.5495美元减为 0.54美元而

不是 0.55美元而抱怨。由于引入舍入机制,个体计算额度与计算总和存在误差。

Page 91: 第 3 章 程序安全

3.4.2 salami攻击 ( 续 ) salami 攻击的例子 ( 续 )

salami攻击还有更大牟利和有趣的方式。程序不再抽取帐户零头,而是直接从每个帐户抽取几美分,这假定用户没兴趣重新计算利息,即使意识到利息有所偏差,也认为是算法上的错误或对利息计算理解有误。同样,程序也可以将一项服务定为 20美元,而实际公司这项服务是 15美元,从而将帐户中的 5美元抽走。只要用户不特别关注帐户的上金额的变化。

Page 92: 第 3 章 程序安全

3.4.2 salami攻击 ( 续 )

salami 攻击持续不断的原因 计算机中的计算经常受到舍入错误的困扰,

特别是很大的数字和很小的数字相结合的时候。为了缓和这种错误危害,程序员通常加入一个错误修正程序。对这些程序的不完善审计使得 salami攻击容易被忽视。又由于系统的源代码多很庞大而复杂,系统的规模和检查漏洞需花费的时间明显有利于恶意代码程序员。

Page 93: 第 3 章 程序安全

3.4.3 Rootkit 和索尼 XCP

Rootkit 是一段恶意代码,它可以很长时间不被发现,并且即使被删除后还可以重建自身。这个名字起源于代码执行在 root权限 (UNIX 系统的超级用户 ) 的意图。典型的 Rootkit 可以干预用户和操作系统的正常交互,隐藏显示自己。假定怀疑代码是干预文件显示的程序,可以写一个显示文件的程序,检查磁盘和文件系统,直接列举文件,并比较这两个结果。 Rootkit检查器(Rootkit revealer) 就是这样的程序。

Page 94: 第 3 章 程序安全

3.4.3 Rootkit 和索尼 XCP ( 续 )

XCP 的行为 索尼公司利用 XCP Rootkit阻止用户复制音乐 CD ,而允许用户播放它们。 XCP通过混淆其他进程读 CD 的结果来妨碍其他程序的任何访问。

CD 第一次插入 PC 机驱动器时, Rootkit 在没有用户的干预下利用 Windows 的“自动运行”特征,安装到 PC 机上。 XCP必须隐藏自己,防止被用户删除,因此, Rootkit屏蔽了所有 $sys$ 开头的文件。

Page 95: 第 3 章 程序安全

3.4.3 Rootkit 和索尼 XCP ( 续 )

XCP 的行为 ( 续 )

索尼公司犯了两个错误:一,它发布的代码为信任的用户系统带来了恶意代码感染的可能;二,在未经用户知晓和允许的条件下安装了这些代码,并通过策略阻止删除这些代码。

Page 96: 第 3 章 程序安全

3.4.3 Rootkit 和索尼 XCP ( 续 )

补丁渗透 Russinovich报告了 XCP 的故事。索尼公司面对严

重的负面舆论。发布了 XCP Rootkit卸载程序。但仍然存在安全漏洞:卸载程序发布在一个网页上用于下载和执行,程序员无法验证这些代码,确实就是卸载程序;卸载程序在 XCP Rootkit卸装后,又留在了用户系统中,成为新的安全漏洞。

Felten 和 Halderman 的调查报告指出:数字版权管理的需求非常类似于恶意代码开发者的需求。索尼公司就曾经与主要反病毒软件厂商合作,让它的 XCP Rootkit 不被查出。

Page 97: 第 3 章 程序安全

3.4.4 权限提升 恶意代码希望访问更多系统对象,因此,必须有更高的权限运行。权限提升 (privilege escalation)攻击就是恶意代码以一个低权限用户启动,而运行在更高级权限的手段。

权限提升的实例 2006年 4月, Symantec 发布了一个软件漏洞补丁

(bulletin Sym06-007) ,修补 Live Update 的漏洞。更新过程包含几个程序的执行,如 LU1 , LU2 ,Sys3 ,和 Sys4 。 LU1 和 LU2 是 Live Update组件, Sys3 和 Sys4 是标准操作系统组件。操作系统使用查找路径来执行程序。 Symantec 软件产品在 Macintosh版本中允许 Live Update通过查找路径而不是明确指定路径来寻找程序。 Live Update 是提升权限运行的,并可以将权限传递给 Sys3 和 Sys4 。如果用户设定查找路径从用户空间开始并放置一个 Sys3 程序, Sys3 程序将以提升权限运行。

Page 98: 第 3 章 程序安全

3.4.4 权限提升 ( 续 )

权限提升的影响 恶意代码编写者可以通过创建一个小的 She

ll 程序 Sys3 ,将它存于任何地方,重置查找路径,调用 Live Update 。结果是 Sys3 在特权模式下接管控制权,并借此攻击系统。恶意代码在运行一次后,可以设置一个标志以便将来获得提高了的特权。

Page 99: 第 3 章 程序安全

3.4.5 界面幻觉 界面幻觉 (interface illusion) 是一个哄骗攻击,攻击中全部或部分网页是假的。攻击者的目的是让用户确信而去做一些不该做的事情。 由于屏幕的每个点可以寻址,一个恶意界面可以显示假的地址条和假的滚动条,来欺骗用户。

Page 100: 第 3 章 程序安全

3.4.6 键盘记录器

键盘和程序之间没有直接的途径来处理击键操作。一个按键可以产生一个被设备驱动程序接收的信号,转换,分析并传输,最终由程序接受。键盘记录器 (keystroke logger) 的恶意程序暗中保存一个所有按键的副本。键盘记录器可以独立保存每个按键的记录或与特定程序相关联的按键日志。

Page 101: 第 3 章 程序安全

3.4.7 中间人攻击 中间人攻击 (man-in-the-middle attack) 是恶

意程序在另外两个程序 (典型的是在用户输入和应用程序结果 ) 之间插入自己。一个例子是恶意程序运行在文字处理器与文件系统之间,每次都阻止保存文件或加密保存文件,以敲诈文件创立者。

Page 102: 第 3 章 程序安全

3.4.8 定时攻击 通过程序执行时间来推断执行操作以及数量。

这种攻击特别适合攻击密码算法,如, RSA算法的密钥。通过对执行时间的比较与分析,推断出密码算法密钥的具体数值。

Page 103: 第 3 章 程序安全

3.4.9 隐蔽通道:泄露信息的程序 传送信息的通信方式是隐蔽的、与其他方式

同时进行,并且是非常合理的。我们一般把这些特殊的通信途径称为隐蔽通道 (covert channel) 。

图 3.11 泄露信息的隐蔽通道

Page 104: 第 3 章 程序安全

3.4.9 隐蔽通道:泄露信息的程序 ( 续 )

隐蔽通道概述 当程序已经投入使用后,就不应该让程序员访问其中的敏感数据了。因为可能从这些敏感数据获利,程序员可能希望可以开发这样的程序,以便能在运行期间秘密与程序员通信并传输数据。

Page 105: 第 3 章 程序安全

3.4.9 隐蔽通道:泄露信息的程序 ( 续 ) 创建隐蔽通道的方式 传输数据可以通过改变输出格式、改变每行数

据的长度、打印或不打印某个特定数据等实现。

图 3.12 隐蔽信道

Page 106: 第 3 章 程序安全

3.4.9 隐蔽通道:泄露信息的程序 ( 续 ) 存储通道 利用存储器中是否有某个特定目标来传递信息,这样的隐蔽通道被称为存储通道 (storage channel) 。文件上锁通道 (file lock channel) 是一个简单的隐蔽通道的例子。在多用户系统中,文件可以被上锁以防止两个用户同时向同一个文件写入(当一个用户写入的内容覆盖了另外一个用户写入的内容时,文件将被损坏)。操作系统或数据管理系统在同一时间只允许一个程序写文件,而阻塞、推迟或拒绝其他程序对该文件的写入请求。隐蔽通道可以通过一个文件是否上锁而传递一个比特位的信息。

Page 107: 第 3 章 程序安全

3.4.9 隐蔽通道:泄露信息的程序 ( 续 )存储通道 ( 续 )

图 3.13 文件上锁隐蔽通道

# 服务程序和间谍程序需要使用时钟,占用一些时间间隔

Page 108: 第 3 章 程序安全

3.4.9 隐蔽通道:泄露信息的程序 ( 续 )

存储通道 ( 续 )

图 3.14 利用文件在通道传递信号 100

#共享系统资源为建立通道提供了便利。每次传输效率可能很低,但计算机为快速系统,传输效果完全可以接受

Page 109: 第 3 章 程序安全

3.4.9 隐蔽通道:泄露信息的程序 ( 续 ) 时间通道 还有一种称为时间通道 (timing channel) 的隐蔽通道,通过事件的发生速度来传递信息。事实上,时间通道仍然是共享资源的通道,而这次共享的资源是时间。

图 3.15 隐蔽的时间通道

Page 110: 第 3 章 程序安全

3.4.9 隐蔽通道:泄露信息的程序 ( 续 ) 识别潜在的隐蔽通道 由于系统资源庞大且使用频繁,找出隐蔽信道并

不容易。有两种旧方法目前仍然实用。第一种方法是以系统资源分析为基础,第二种则是工作在源代码级上。

共享资源矩阵表 3.3 共享资源矩阵

服务进程 间谍进程上锁文件 R, M R, M

机密数据 R

# R 代表可以读取, M 代表可以设置

Page 111: 第 3 章 程序安全

3.4.9 隐蔽通道:泄露信息的程序 ( 续 )识别潜在的隐蔽通道 ( 续 )

通过观察有

表 3.4 共享资源矩阵

服务进程 间谍进程上锁文件 R, M R, M

机密数据 R R

Page 112: 第 3 章 程序安全

3.4.9 隐蔽通道:泄露信息的程序 ( 续 )

识别潜在的隐蔽通道 ( 续 )

信息流方式 这是基于程序语法的信息流分析技术,可以利用一个编译器自动实现。

Page 113: 第 3 章 程序安全

3.4.9 隐蔽通道:泄露信息的程序 ( 续 ) 识别潜在的隐蔽通道 ( 续 )表 3.5 语法上体现的信息流动语句 信息流动B:=A 从 A 到 BIF C=1 THEN B:=A 从 A 到 B ,从 C 到 BFOR K:=1 to N DO stmts END 从 K 到 stmts

WHILE K>0 DO stmts END 从 K 到 stmts

CASE (exp) val1: stmts 从 exp 到 stmts

B:=fcn(args) 从 fcn 到 B

OPEN FILE f 没有信息流动READ (f, X) 从文件 f 到 XWRITE (f, X) 从 X 到文件 f

Page 114: 第 3 章 程序安全

3.4.9 隐蔽通道:泄露信息的程序 ( 续 )

对隐蔽通道的小结 隐蔽通道对信息系统的安全来说是一个严

重的威胁。隐蔽通道攻击手段非常灵活,可以隐藏在任何服务程序,如打印机程序等。制造起来也不比病毒难。容量和速度也不是限制信息流传播的条件,特别是隐藏在硬件中的隐蔽通道。关闭隐蔽通道的技术进展并不乐观。

隐蔽通道存在的可能性要求人们对程序开发分析、系统结构分析和输出审查给予更大关注。

Page 115: 第 3 章 程序安全

3.5 对程序威胁的控制 应该更关注如何预防漏洞而不是修补漏洞。

这需要在软件开发 (software development)期间,即编写规范、设计、编码和测试等过程中,实施控制。我们将讨论:开发控制、操作系统控制和管理控制。这里先讨论开发控制。

Page 116: 第 3 章 程序安全

3.5.1 开发控制 软件开发过程的特点 开发过程中需要完成的任务: 系统需求分析,获取系统的需求并从用户的角度构建模型系统。 设计系统,从需求描述出发,提出解决问题的方案,并为该方

案建模。 实现系统,以设计方案为蓝本来实施问题的解决方案。 测试系统,确保系统符合需求分析和系统设计中所提出的需要。 在不同的阶段复查系统,确保最终的产品符合需求分析和系统

设计中所提出的要求。 为系统编写文档,以进行对用户的培训和支持。 管理系统,以清除一些不必要的资源。这些资源在软件开发过

程中使用,但系统完成后,它们可能会成为通往系统内部的暗道。

维护系统,追踪被发现的问题、必要的系统变化和已经产生的系统变化,并从整体上评估它们对系统的质量和功能的影响。

Page 117: 第 3 章 程序安全

3.5.1 开发控制 ( 续 )

软件开发过程的特点 ( 续 )

设计安全、可用的系统,需要注意如下要点:1) 不能随意发挥可用的安全性能2) 工具不是解决方案3) 关注上层4) 让用户满意5) 局部思考,局部动作

Page 118: 第 3 章 程序安全

3.5.1 开发控制 ( 续 ) 模块化、封装性和信息隐藏 通常,代码的生存期 (shelf-life) 是很长的。但是,随着时间的推移,代码需要完善,因为需求可能发生变更,并且发现的错误需要修改。因此,软件工程的一个重要原则就是将代码或其他设计实体做成小型、独立的单元,称为组件 (component) 或模块 (module) 。当系统按照这种方法开发时,我们 称其为模块化 (modular) 。

Page 119: 第 3 章 程序安全

3.5.1 开发控制 ( 续 ) 模块化、封装性和信息隐藏 ( 续 )

如果一个独立的组件不受其他组件的影响,就很容易找出其中故障的原因,并将故障的危害控制在最小范围内。独立组件也使系统的维护变得容易,因为对一个独立组件所做的调整将不会影响其他组件。在组件间完全独立的情况下,我们能更容易地发现漏洞所在。这种独立的模块化形式称为封装性 (encapsulation) 。

信息隐藏 (information hiding) 是模块化软件的又一个特性。信息隐藏指的是,每个组件都隐藏自己的实现细节或设计细节。 这样在系统需要调整时,只需要调整某个特定组件。

Page 120: 第 3 章 程序安全

3.5.1 开发控制 ( 续 )

模块化、封装性和信息隐藏 ( 续 ) 模块化是将一个任务划分为若干子任务的过程。

这种划分是以逻辑性或功能性为基础的。模块化使得每个组件都必须满足 4 个条件:

单任务:只完成一个特定的功能 小型化:一个组件包含的信息数量非常少,以至于人们可以很容易地理解它的构造和内容

简单化:复杂程度不高,可以很容易地理解模块的意图和构造

独立性:不依靠其他模块而独立完成任务

Page 121: 第 3 章 程序安全

3.5.1 开发控制 ( 续 )

图 3.16 模块化

模块化、封装性和信息隐藏 ( 续 )

Page 122: 第 3 章 程序安全

3.5.1 开发控制 ( 续 ) 模块化、封装性和信息隐藏 ( 续 ) 小型、独立的组件具有许多好处: 易维护:当需要用改进版本取代一个旧版本的组件时,如果

该组件只执行某个单独的功能,则只需将旧组件移除就可以了。

易理解:人们通常更容易理解一个由许多小型组件所构成的系统,而不容易理解一个由大量非结构化的代码所构成的系统。

可重用:为一项特定任务而开发的组件经常可以被其他系统重复利用。重用正确、已经存在的代码或设计,可以减少开发和测试的难度。

易修复:对完成一项特定任务的组件来说,很容易确定它的故障。

易测试:一个良好定义了输入、输出和功能性的组件仅从自身出发尽一切可能性来进行测试,这些测试不用考虑其他模块的影响。

Page 123: 第 3 章 程序安全

3.5.1 开发控制 ( 续 ) 模块化、封装性和信息隐藏 ( 续 )

内聚 (cohesion) 是指组件中所有元素的存在都有充足的逻辑理由或功能理由,每个组件元素都与组件要执行的单一任务是相关的。耦合 (coupling) 是指某个组件与系统中其他组件的相互依赖程度。

图 3.17 耦合

Page 124: 第 3 章 程序安全

3.5.1 开发控制 ( 续 )

模块化、封装性和信息隐藏 ( 续 )

封装性 一个被封装组件的边界可以根据需要设计

成半透明或透明。应该将组件内的信息打包,隐藏应该隐藏的部分,并将应该可见的部分呈现出来。

Page 125: 第 3 章 程序安全

3.5.1 开发控制 ( 续 ) 模块化、封装性和信息隐藏 ( 续 )

信息隐藏 一个设计良好的组件,对其他设计者而言没有必

要知道该模块的实现细节。隐藏实现细节,使得恶意开发者因为不知道该组件是如何工作的,而不能轻易用其他的组件替换。

图 3.18 信息隐藏

Page 126: 第 3 章 程序安全

3.5.1 开发控制 ( 续 )

相互猜疑 相互猜疑 (mutual suspicion) 是描述两个程

序的关系,相互猜疑的程序各自运行,仿佛系统中其他程序是恶意或者不正确的。每个程序都保护它的接口数据以限制其他程序访问。

限制 一个受限制的程序被严格地限制它可以访

问的系统资源。强限制有助于限制病毒扩散。

Page 127: 第 3 章 程序安全

3.5.1 开发控制 ( 续 )

遗传的多样性 来自一个来源的系统的多个组件是危险的。

软件产品的紧密集成也是一个类似问题。由于紧密集成,修补一个软件产品的漏洞会影响其他软件产品。

Page 128: 第 3 章 程序安全

3.5.1 开发控制 ( 续 )技术手段软件开发阶段,几种关键的技术包括:1) 对等复查2) 风险分析3) 测试4) 良好的设计5) 预测6) 静态分析7) 配置管理8) 错误分析

Page 129: 第 3 章 程序安全

3.5.1 开发控制 ( 续 )

对等复查 三种有很细微差别的对等复查: 复查:让复查小组非正式地对产品做出评审,目的

在于在开发继续进行之前,听取大多数人的意见。 走查:产品的制造者将产品提交评审小组,并主持

和控制小组的讨论。该类型复查的目的在于让小组成员针对产品进行学习,关注的焦点是研究某个单独的文档。

检查:这种复查更加正规,它将根据一张清单做详细的分析,该清单上列举了一些应该关注的问题。作者不再是讨论的主持人,而错误的发现和修正通常由统计测试来控制。

Page 130: 第 3 章 程序安全

3.5.1 开发控制 ( 续 )

对等复查 ( 续 )

发现了错误后可以采取至少三种方法进行处理:

1) 研究错误发生的方式、时间和原因。 2) 采取行动阻止错误的运行。 3) 仔细检查产品以找出被忽略的错误实例

和影响。

Page 131: 第 3 章 程序安全

3.5.1 开发控制 ( 续 ) 对等复查 ( 续 ) 进行对等复查非常必要。 Hewlett-Packard早期的研究表明:在开发过程中实施了对等复查的产品比其他实施传统测试技术的产品具有明显优势。

图 3.19 报告的错误发现率

Page 132: 第 3 章 程序安全

3.5.1 开发控制 ( 续 ) 对等复查 ( 续 ) 复查的过程包括了几个重要步骤:计划、

个体准备、会议讨论、再工作和再检查。复查中,应该密切关注复查者的发现和他们发现问题的速度。这可以了解每位复查者是否胜任。而且可以了解某类错误是否较其他错误更难发现。对错误的处理还要追根溯源。开发中记载错误的日志可以形成检查清单,以备复查使用。管理措施必须强制系统在开发的整个过程中使用苛刻的复查法才能保证最终程序的安全。

Page 133: 第 3 章 程序安全

3.5.1 开发控制 ( 续 )

风险分析 风险分析 (hazard analysis) 是在系统级上采

用一系列技术揭示系统潜在的不安全状态。风险分析是系统级而非代码级,其对发现安全漏洞无能为力。风险分析越早越好,并且应该贯穿整个软件生存期。大量不同的技术都支持查找和管理潜在的风险。

Page 134: 第 3 章 程序安全

3.5.1 开发控制 ( 续 ) 风险分析 ( 续 ) 最有效的技术是风险和运行性研究 (hazard an

d operability studies , HAZOP) 、失效模式和后果分析 (failure modes and effects analysis ,FMEA) ,以及故障树分析 (fault tree analysis ,FTA) 。

表 3.6 风险分析的观点已知原因 未知原因

已知结果 描述出系统的行为 推论分析,如 FTA

未知结果 诱导分析,如 FMEA 探测分析,如 HAZOP

Page 135: 第 3 章 程序安全

3.5.1 开发控制 ( 续 )

测试 测试是针对产品质量的活动,目的是消除产

品的故障或使故障在允许范围内。由于一个控制失败暴露出的脆弱点是再多的功能控制所无法改善的,因此,测试者应该保持足够的谨慎。

安全测试很艰难。副作用、依赖性、不可预知的用户、有缺陷的实现基础都给安全测试带来困难。安全测试复杂的本质在于,不仅需要考虑程序的正确运行,而还必须考虑程序可能出错的各种方式。

Page 136: 第 3 章 程序安全

3.5.1 开发控制 ( 续 )

测试 ( 续 ) 测试通常包括几个阶段: 单元测试 (unit testing) 是在可操控的环境下实现的,这样测试小组可以为组件输入一组预定的数据,并观察组件的输出行为和输出数据。此外,测试小组还检查输入和输出数据的内部结构、逻辑条件和边界条件。

集成测试 (integration testing) 是确保系统的组件间按照系统设计规范的描述协调工作的过程。

Page 137: 第 3 章 程序安全

3.5.1 开发控制 ( 续 ) 测试 ( 续 ) 功能测试 (function test) 评估系统以确定集成系统的功能是否同需求规范中所描述的一样。测试的结果是一个功能性系统。

性能测试 (performance test) 将把系统与软、硬件需求做比较。在功能测试和性能测试期间,检查了系统的安全需求,确信安全需求与安全性能相一致。

接受测试 (acceptance test) 将检查系统是否符合用户的需求规范。

安装测试 (installation test) 将系统安装在运行环境中进行最后的测试,确保系统在安装后仍然具有同样的功能性。同时,安全需求还经常指出系统不应该做的事情。

Page 138: 第 3 章 程序安全

3.5.1 开发控制 ( 续 )

测试 ( 续 )

此外还有对系统的安全性非常重要的回归测试 (regression testing) ,目的是确保在系统的功能加强或修复了某个漏洞后,其他功能仍可以正常运行而不受系统变化的影响。

以上每种测试方法可以采用黑盒测试 (black-box testing) 和白盒测试 (white-box testing) 。多种技术的混合使用取决于系统的大小、应用领域、风险总和等因素。

Page 139: 第 3 章 程序安全

3.5.1 开发控制 ( 续 )

测试 ( 续 ) 独立测试 (independent testing) 是相当必要

的,可以预防开发者在正常过程中隐藏一些东西,或保留一个子系统不受测试控制中以便将来使用。独立测试可以增大对隐藏事物的曝光率。

渗透测试 (penetration testing) 是计算机安全中一种独特的测试类型。在这种测试形式中,测试员尽量让软件失败。也就是说,尽量发现软件是否做了它没有被假定做的事情,测试可能的安全失效。

Page 140: 第 3 章 程序安全

3.5.1 开发控制 ( 续 )

良好的设计 许多与设计有关的活动对开发安全软件有帮助。

1) 使用容错技术 (fault tolerance) 的哲学。处理错误应该尽量减少对系统的破坏且尽量符合安全。错误处理通常不应该采用被动故障检测 (passive fault detection) ,而是主动故障检测 (active fault detection) ,还可以利用冗余性 (redundancy) 。如果修正错误的风险太大,则可以应用容错技术,即安全策略选择减轻安全问题的影响而不是阻止它的发生。

Page 141: 第 3 章 程序安全

3.5.1 开发控制 ( 续 ) 良好的设计 ( 续 )

2) 使用一致的策略 (policy) 来处理错误。典型的错误包括:不能提供某个服务、提供错误的服务或数据、损坏数据。解决出现的这些问题可以对应于每种错误采取如下一种方法:

重试:将系统恢复到之前的状态,使用其他策略重新运行服务。

修改:将系统恢复到之前的状态,修正一些系统特征,使用相同的策略重新运行服务。

报告:将系统恢复到之前的状态,将问题报告给错误处理组件,并不再执行服务。

# 这将有助于查找系统的安全脆弱点。

Page 142: 第 3 章 程序安全

3.5.1 开发控制 ( 续 )

良好的设计 ( 续 )

3) 抓住设计的基本原理 (desgin rationale)和历史记录。这些文献有助我们了解采用某种方法创建系统的依据。

4) 使用设计模式 (design pattern) 。设计模式可以对将来的设计方法提供指导,简化设计。

Page 143: 第 3 章 程序安全

3.5.1 开发控制 ( 续 )

前景预测 软件开发过程中的前景预测,其预测内容是创建和使用系统的风险性。前景预测可以帮助我们挑选控制方法,以及决定控制的数量。例如,如果认为某个安全分支的风险系数很小,我们就不会投入大量的资金、时间和精力来建立复杂的控制系统。或者,可以在可能的风险冲击下证明同时使用一系列控制即“深度防御” (defense in depth) 是正确的。

Page 144: 第 3 章 程序安全

3.5.1 开发控制 ( 续 )

静态分析 在系统完成运行之前,可以通过检查设计

和代码来寻找和修复安全漏洞。对等复查涉及这项技术。但静态分析更进一步检查设计和代码的细节,并在对等复查之前进行。可以从以下几个方面检查设计和代码: 控制流结构、数据流结构、数据结构。

Page 145: 第 3 章 程序安全

3.5.1 开发控制 ( 续 )

配置管理 在开发软件时,重要的一点是必须清楚谁

在什么时候对什么做了怎样的改变: 修改性改变:维护系统日常功能的控制 适应性改变:维护控制而对系统的调整 完善性改变:完善已经存在的系统功能 预防性改变:预防系统性能下降到不能接受的程度

Page 146: 第 3 章 程序安全

3.5.1 开发控制 ( 续 ) 配置管理 ( 续 ) 配置管理 (configuration management) 是在

开发和维护期间用来控制软件改变的过程,对安全性也十分有利。特别是,配置管理会审查新代码或改变后的代码,以确保安全漏洞没有被有意或无意地插入其中。

配置管理中包含 4 类活动: 1) 配置鉴定 2) 配置控制和变化管理 3) 配置审查 4) 状态说明

Page 147: 第 3 章 程序安全

3.5.1 开发控制 ( 续 ) 配置管理 ( 续 ) 配置鉴定 (configuration identification) 设置了一个基线,所有

改变后的代码将与之比较。这就是说,首先创建一个详细目录,其中记载了系统的所有组件。然后,“冻结”该基线并小心地对其加以控制。当系统发生改变时,将被描述为相对基线的改变。

配置控制 (configuration control) 和配置管理 (configuration management) 确保了可以协调不同的相关版本。这里有三种控制变化的方法:分隔文件、 delta 方法和条件编译。分隔文件的方法就是让不同的系统版本拥有不同的文件。 delta 方法是指定某个版本为系统的主要版本,再定义其他的不同版本,版本中不同的文件称为 delta ,包含一些编辑过的命令行,这些命令行描述了从主版本向其他变异版本的转换方法。条件编译是在所有版本中都使用同一个代码组件,而由编译器来决定哪个版本应该使用哪条语句。这种方法似乎对安全应用有吸引力,所有代码都集中管理,如果版本非常复杂,代码也就会非常难以阅读和理解。

Page 148: 第 3 章 程序安全

3.5.1 开发控制 ( 续 )

配置管理 ( 续 )

配置审查 (configuration audit) 可以确保基线是完整和精确的。审查通常使用下面两种独立方法中的一种进行的:复查基线中的每个实体,并将它们与投入使用的系统做比较;或者仅仅从大型系统中抽取小部分做抽样审查以确保系统的一致性。

状态说明 (status accounting) 将记录关于组件的信息,如所有组件的来源、最新版本、修改历史记录和未决定的修改申请等等。

Page 149: 第 3 章 程序安全

3.5.1 开发控制 ( 续 )

配置管理 ( 续 )

上述 4 类活动由配置和修改控制组 (CCB, configuration and change control board) 统一执行。 CCB 包含系统相关不同群体代表,负责复查和改进各种修改申请。配置管理通过保护程序和文档的完整性很好地实现了消除无意的系统威胁并预防恶意威胁的目标。在系统运行阶段,开发人员只能通过 CCB 来访问运行成品程序。

Page 150: 第 3 章 程序安全

3.5.1 开发控制 ( 续 )

从错误中吸取教训 在设计和创建系统时,可以把决定做成文档,不仅要记录决定和做出该决定的原因,还要记录不做出某个决定的原因。从这些信息中,可以创建检查清单和指导方针帮助系统开发,保证我们不会犯同样的错误,并使其他系统开发员不犯相同的错误。

Page 151: 第 3 章 程序安全

3.5.1 开发控制 ( 续 ) 程序正确性证明 计算机安全原理指出不可能确定两个程序是否做同样

的事情。这一结论是从“停机问题”推导来的,因此,确定程序是否安全从理论上来说非常困难。

程序核实 (program verification) 的技术可以论证某些特定程序正确,但仍然有很多因素阻碍着它的发展。

1) 正确性证明依赖于程序员或逻辑学家将程序语句翻译为逻辑表达。如果程序发现是有错误的,错误也可能出现在翻译中。

2) 从最初断言和语句涵义中得出正确性的证明是非常难的,进行证明的逻辑引擎也运行得很慢。正确性的证明不适合大型程序。

3) 现今程序核实的发展远不如代码产品。所以,正确性证明还没有在大型产品中普遍运用。

Page 152: 第 3 章 程序安全

3.5.1 开发控制 ( 续 )

编程实践的小结 在任何系统开发中,没有一项管理或技术

可以保证在生产率、可靠性和简易性上有哪怕一个数量的改进。任何技术都不能保证软件开发过程中没有错误发生,应该对新技术采取怀疑态度,确保每种新技术确实可信和有效。

Page 153: 第 3 章 程序安全

3.5.1 开发控制 ( 续 ) 程序开发的标准 可以通过以下几种指南来实施软件开发的管理控

制: 1) 设计标准,包括使用专门设计工具等。 2) 文档、语言及编码风格标准。 3) 编程标准,包括强制对等复查等。 4) 测试标准,如采用程序验证技术等。 5) 配置管理标准,控制对稳定、完整程序单元的访问和修改。

# 在共同的框架下,使得每个人都不是不可缺少的,且一个项目的经验可以为下一个项目利用。此外,安全审计 (security audits) 可以保证标准被贯彻。

Page 154: 第 3 章 程序安全

3.5.1 开发控制 ( 续 )

过程标准 美国软件工程研究所开发了 CMM(Capability

Maturity Model ) 来评价组织机构,而不是产品, ISO 的 ISO 9001 在某种程度上类似 CMM 。过程模型 (process model) ,是检查一个组织怎么做一件事情,而不是已经做了哪些事情。秩序、结构和一致性可以导致软件项目的成功,但不能确定是唯一的可行方式。

Page 155: 第 3 章 程序安全

3.5.2 程序控制 人类的创造性可以让人们在失败中吸取教训,逐渐形成原则。好的软件开发人员会充分理解安全的重要性并将安全因素很好地融入开发过程。

Page 156: 第 3 章 程序安全

3.6 本章总结 本章的内容涵盖了计算机安全中的开发部

分:安全漏洞的种类和影响,无意漏洞和恶意代码以及能控制威胁的技术。控制的意义并不仅限于限制某些行为,控制对系统的整体性能做出了非常积极的贡献。安全特性是控制目标的一个重要方面。

Page 157: 第 3 章 程序安全

谢谢!