《软件工程专业缓冲区溢出的保护实践41920.docx》由会员分享,可在线阅读,更多相关《软件工程专业缓冲区溢出的保护实践41920.docx(14页珍藏版)》请在taowenge.com淘文阁网|工程机械CAD图纸|机械工程制图|CAD装配图下载|SolidWorks_CaTia_CAD_UG_PROE_设计图分享下载上搜索。
1、Evaluation Warning: The document was created with Spire.Doc for .NET.*大学*学院信息安全产品开开发实践课程程设计报告题 目 缓冲区溢溢出的保护 学生姓名 学 号_ _ 年 级 指导老师 指导老师评阅意意见: 指导老师评分: 提交时间: 2007年12月 缓冲区溢出的保保护(软件工工程专业)学生 学号 指导教师师 摘要:19999 年 Buugtraqq(一个讨论论安全缺陷的的邮件列表)进进行的一次非非正式调查发发现,三分之之二的参与者者认为第一号号的缺陷就是是缓冲区溢出出。从 19997 年到到 20077 年 3 月,CE
2、RRT/CC 发出的半数数安全警报都都基于缓冲区区缺陷。 面面对如此大的的威胁,我们们需要知道什什么是缓冲区区溢出,如何何防止它们,可可以采用哪些些最新的自动动化工具来防防止它们以及及为什么这些些工具还不足足够,还有如如何在编写程程序的程序中中防止它们。关键字:缓冲区区溢出;溢出保护;溢出防御 Detectiion Off Bufferr Overfllow Abstraact: From an innformaal invvestiggationn on BBugtraaq (a mail list whichh disccuss aa limiitatioon on securrity)
3、in 19999, wwe cann findd thatt two-parts parrticippants thougght thhat thhe No.1 limmitatiion iss bufffer ovverfloow. Frrom 19997 too May, 20077, almmost hhalf tthe seecure warniings ssent bby CERRT/CC were basedd on tthe liimitattion oof bufffer. Facinng succh a hhuge mmenacee, we need to leearn ww
4、hat iis thee bufffer ovverfloow, hoow to defennd theem, whhich kkinds of thhe lattest aautomaatizattion ttools we caan useed forr avoiid theem , wwhy thhese ttools stilll not enouggh, annd howw to pprevennt theem in progrramminng.Keywordds: Buuffer Overfflow,Overfflow Detecction, Overfflow Defeense
5、正文1 绪论1.1 立题背背景缓冲区溢出是当当前一些软件件存在的最常常见的安全隐隐患之一,通通过提供一个个恶意的输入入黑客可以改改变进程的执执行流程,缓缓冲区溢出能能够威胁到整整个进程,机机器,甚至相相关的系统领领域。如果运运行的进程是是在权限比较较高的用户下下面,比如aadminiistrattor或者本本地的系统帐帐户(Loccal Syystem Accouunt),那那么黑客破坏坏所导致的损损失将会很严严重而且将会会面临更广泛泛的潜在危胁胁。最近时期期爆发的一些些众所周知的的病毒像,红红色代码病毒毒和震荡波蠕蠕虫病毒,都都是C/C+代码里存存在着缓冲区区溢出的结果果。1.2 研究内内容
6、在几乎所有计算算机语言中,不不管是新的语语言还是旧的的语言,使缓缓冲区溢出的的任何尝试通通常都会被该该语言本身自自动检测并阻阻止(比如通通过引发一个个异常或根据据需要给缓冲冲区添加更多多空间)。但但是有两种语语言不是这样样:C 和 C+ 语语言。C 和和 C+ 语言通常只只是让额外的的数据乱写到到其余内存的的任何位置,而而这种情况可可能被利用从从而导致恐怖怖的结果。更更糟糕的是,用用 C 和 C+ 编编写正确的代代码来始终如如一地处理缓缓冲区溢出则则更为困难;很容易就会会意外地导致致缓冲区溢出出。除了 CC 和 C+ 使用得得 非常广泛泛外,上述这这些可能都是是不相关的事事实;例如,RRed
7、Haat Linnux 7.1 中 886% 的代代码行都是用用 C 或 C + 编写的。因因此,大量的的代码对这个个问题都是脆脆弱的,因为为实现语言无无法保护代码码避免这个问问题。 在 C 和 CC+ 语言言本身中,这这个问题是不不容易解决的的。该问题基基于 C 语语言的根本设设计决定(特特别是 C 语言中指针针和数组的处处理方式)。由由于 C+ 是最兼容容的 C 语语言超集,它它也具有相同同的问题。存存在一些能防防止这个问题题的 C/CC+ 兼容容版本,但是是它们存在极极其严重的性性能问题。而而且一旦改变变 C 语言言来防止这个个问题,它就就不再是 CC 语言了。许许多语言(比比如 Jav
8、va 和 CC#)在语法法上类似 CC,但它们实实际上是不同同的语言,将将现有 C 或 C+ 程序改为为使用那些语语言是一项艰艰巨的任务。有些语言存在允允许缓冲区溢溢出发生的&ldquoo;转义&rrdquo;子句。Adda 一般会会检测和防止止缓冲区溢出出(即针对这这样的尝试引引发一个异常常),但是不不同的程序可可能会禁用这这个特性。CC# 一般会会检测和防止止缓冲区溢出出,但是它允允许程序员将将某些例程定定义为“不安全的”,而这样的的代码 可能能 会导致缓缓冲区溢出。因因此如果您使使用那些转义义机制,就需需要使用 CC/C+ 程序所必须须使用的相同同种类的保护护机制。许多多语言都是用用 C
9、 语言言来实现的(至至少部分是用用 C 语言言来实现的 ),并且用用任何语言编编写的所有程程序本质上都都依赖用 CC 或 C+ 编写的的库。因此,所所有程序都会会继承那些问问题,所以了了解这些问题题是很重要的的。 2缓冲区溢出出的概述 2.1 缓冲区区溢出的起源源内存溢出已经是是软件开发历历史上存在了了近40年的的“老大难”问题2.2缓冲区溢溢出如何工作作计算机还有由程程序共享, 随机访问内内存 (RAAM)。 为为了简化, 内存管理 Windoows XPP SP 22 有功能控控制当前正在在使用哪段的的 RAM。 如果启动程程序, 释放放内存分配给给程序。 该内存被分为三三段: 代码段此处
10、存储程序特特定执行命令令。 数据段此处程序特定数数据存储。 堆栈是数据据段 (一部部分)此处存储所有与与程序函数。 这包括参数数、 缓冲区区存储本地变变量以及, 最重要、 返回地址。 返回地址指指定执行函数数后, 程序序将继续从。作为是由用户输输入该信息也也注册作为变变量, 一切切, 发送到到堆栈用户类类型。 不通通常, 此行行为不提出问问题。 但是是, 如果因因编程错误, 超过缓冲冲区限制堆栈栈成为容易控控制。 整个个段被指定为为本地变量例例如, 如果果攻击者选择择适当项对于于攻击, 可可能会覆盖用用指令。 此此外, 后续续返回地址可可更改为指向向恶意代码。 因此, 程程序不再正常常, 但盲
11、目目执行攻击者者的命令。内存的底部 内存的顶顶部 bufferr1 sffp reet a b cc - 增长长 - . 堆栈的顶部 堆栈的底底部 许多计算机处理理器,包括所所有 x866 处理器,都都支持从高位位地址向低位位地址“倒”增长堆栈。因因此,每当一一个函数调用用另一个函数数,更多的数数据将被添加加到左边(低低位地址),直直至系统的堆堆栈空间耗尽尽。在这个例例子中,当 main() 调用 functtion1() 时,它它将 c 的的值压入堆栈栈,然后压入入 b 的值值,最后压入入 a 的值值。之后它压压入 retturn (ret) 值,这个值值在 funnctionn1() 完完
12、成时告诉 functtion1() 返回到到 mainn() 中的的何处。它还还把所谓的“已保存的帧帧指针(saaved fframe pointter,sffp)”记录到堆栈栈上;这并不不是必须保存存的内容,此此处我们不需需要理解它。在在任何情况下下, funnctionn1() 在在启动以后,它它会为 buuffer11() 预留留空间,这在在图 1 中中显示为具有有一个低地址址位置。 现在假设攻击者者发送了超过过 bufffer1() 所能处理理的数据。接接下来会发生生什么情况呢呢?当然,CC 和 C+ 程序员员不会自动检检查这个问题题,因此除非非程序员明确确地阻止它,否否则下一个值值将
13、进入内存存中的“下一个”位置。那意意味着攻击者者能够改写 sfp (即即已保存的帧帧指针),然然后改写 rret (返返回地址)。之之后,当 ffunctiion1() 完成时,它它将“返回” 不过过不是返回到到 mainn() ,而而是返回到攻攻击者想要运运行的任何代代码。 通常攻击者会使使用它想要运运行的恶意代代码来使缓冲冲区溢出,然然后攻击者会会更改返回值值以指向它们们已发送的恶恶意代码。这这意味着攻击击者本质上能能够在一个操操作中完成整整个攻击!AAleph On 的文文章(请参阅阅 参考资料料)详细介绍绍了这样的攻攻击代码是如如何创建的。例例如,将一个个 ASCIII 0 字字符压入
14、缓冲冲区通常是很很困难的,而而该文介绍了了攻击者一般般如何能够解解决这个问题题。 除了 smasshing-stackk 和更改返返回地址外,还还存在利用缓缓冲区溢出缺缺陷的其他途途径。与改写写返回地址不不同,攻击者者可以 smmashinng-staack(使堆堆栈上的缓冲冲区溢出),然然后改写局部部变量以利用用缓冲区溢出出缺陷。缓冲冲区根本就不不必在堆栈上上 它可以以是堆中动态态分配的内存存(也称为“mallooc”或“new”区域),或或者在某些静静态分配的内内存中(比如如“globaal”或“statiic”内存)。基基本上,如果果攻击者能够够溢出缓冲区区的边界,麻麻烦或许就会会找上你
15、了。 然而,最危危险的缓冲区区溢出攻击就就是 staack-smmashinng 攻击,因因为如果程序序对攻击者很很脆弱,攻击击者获得整个个机器的控制制权就特别容容易 2.3缓冲区区溢出分类 2.33.1在程序的地地址空间里安安排适当的代代码 22.3.1.1殖入法 攻击者用被攻击击程序的缓冲冲区来存放攻攻击代码。 攻击者向被被攻击的程序序输入一个字字符串,程序序会把这个字字符串放到缓缓冲区里。这这个字符串包包含的数据是是可以在这个个被攻击的硬硬件平台上运运行的指令序序列。 2.3.1.22利用已经存存在的代码 有时候,攻击者者想要的代码码已经在被攻攻击的程序中中了,攻击者者所要做的只只是对代
16、码传传递一些参数数,然后使程程序跳转到指指定目标。比比如,在C语语言中,攻击击代码要求执执行“exec(/binn/sh)”,而在liibc库中的的代码执行“exec(arg)”,其中arrg是指向一一个字符串的的指针参数,那那么攻击者只只要把传入的的参数指针指指向/biin/sh,就可以调调转到libbc库中的相相应的指令序序列。 2.3.2控控制程序转移移到攻击代码码这种方法旨在改改变程序的执执行流程,使使之跳转到攻攻击代码。最最基本方法的的就是溢出一一个没有边界界检查或者其其他弱点的缓缓冲区,这样样就扰乱了程程序的正常的的执行顺序。通通过溢出一个个缓冲区,攻攻击者可以用用近乎暴力的的方法
17、改写相相邻的程序空空间而直接跳跳过了系统的的检查。 2.3.2.11激活纪录(AActivaation Recorrds) 每当一个函数调调用发生时,调调用者会在堆堆栈中留下一一个激活纪录录,它包含了了函数结束时时返回的地址址。攻击者通通过溢出这些些自动变量,使使这个返回地地址指向攻击击代码。通过过改变程序的的返回地址,当当函数调用结结束时,程序序就跳转到攻攻击者设定的的地址,而不不是原先的地地址。这类的的缓冲区溢出出被称为“stackk smasshing attacck”,是目前常常用的缓冲区区溢出攻击方方式。 2.3.2.22函数指针(FFunctiion Poointerrs) C语言
18、中,“vvoid (* fooo)()”声明了一个个返回值为vvoid函数数指针的变量量foo。函函数指针可以以用来定位任任何地址空间间,所以攻击击者只需在任任何空间内的的函数指针附附近找到一个个能够溢出的的缓冲区,然然后溢出这个个缓冲区来改改变函数指针针。在某一时时刻,当程序序通过函数指指针调用函数数时,程序的的流程就按攻攻击者的意图图实现了!它它的一个攻击击范例就是在在Linuxx系统下的ssuper probee程序。 2.3.2.33长跳转缓冲冲区(Lonngjmp buffeers) 在C语言中包含含了一个简单单的检验/恢恢复系统,称称为setjjmp/loongjmpp。意思是在在
19、检验点设定定“setjmmp(bufffer)”,用“longjjmp(buuffer)”来恢复检验验点。然而,如如果攻击者能能够进入缓冲冲区的空间,那那么“longjjmp(buuffer)”实际上是跳跳转到攻击者者的代码。象象函数指针一一样,lonngjmp缓缓冲区能够指指向任何地方方,所以攻击击者所要做的的就是找到一一个可供溢出出的缓冲区。一一个典型的例例子就是Peerl 5.003,攻攻击者首先进进入用来恢复复缓冲区溢出出的的lonngjmp缓缓冲区,然后后诱导进入恢恢复模式,这这样就使Peerl的解释释器跳转到攻攻击代码上了了! 3. 缓冲区溢溢出的保护当然,要让程序序员 不犯常常见
20、错误是很很难的,而让让程序(以及及程序员)改改为使用另一一种语言通常常更为困难。那那么为何不让让底层系统自自动保护程序序避免这些问问题呢?最起起码,避免 stackk-smasshing 攻击是一件件好事,因为为 stacck-smaashingg 攻击是特特别容易做到到的。 一般来说,更改改底层系统以以避免常见的的安全问题是是一个极好的的想法,我们们在本文后面面也会遇到这这个主题。事事实证明存在在许多可用的的防御措施,而而一些最受欢欢迎的措施可可分组为以下下类别: 3.1基于探测测方法(caanary)的的防御。这包包括 StaackGuaard(由 Immunnix 所使使用)、PrroP
21、oliice(由 OpenBBSD 所使使用)和 MMicrossoft 的的 /GS 选项。 非执行的堆栈防防御。这包括括 Solaar Dessignerr 的 noon-exeec 补丁(由由 OpennWall 所使用)和和 execc shieeld(由 Red HHat/Feedora 所使用)。 其他方法。这包包括 libbsafe(由由 Manddrake 所使用)和和堆栈分割方方法。 遗憾的是,迄今今所见的所有有方法都具有有弱点,因此此它们不是万万能药,但是是它们会提供供一些帮助。 3.2基于探测测方法的防御御 :研究人员 Crisppen Coowan 创创建了一个称称为
22、StaackGuaard 的有有趣方法。SStackgguard 修改 C 编译器(ggcc),以以便将一个“探测”值插入到返返回地址的前前面。“探测仪”就像煤矿中中的探测仪:它在某个地地方出故障时时发出警告。在在任何函数返返回之前,它它执行检查以以确保探测值值没有改变。如如果攻击者改改写返回地址址(作为 sstack-smashhing 攻攻击的一部分分),探测仪仪的值或许就就会改变,系系统内就会相相应地中止。这这是一种有用用的方法,不不过要注意这这种方法无法法防止缓冲区区溢出改写其其他值(攻击击者仍然能够够利用这些值值来攻击系统统)。人们也也曾扩展这种种方法来保护护其他值(比比如堆上的值值
23、)。Staackguaard(以及及其他防御措措施)由 IImmuniix 所使用用。 IBM 的 sstack-smashhing 保保护程序(sssp,起初初名为 PrroPoliice)是 StackkGuardd 的方法的的一种变化形形式。像 SStackGGuard 一样,sssp 使用一一个修改过的的编译器在函函数调用中插插入一个探测测仪以检测堆堆栈溢出。然然而,它给这这种基本的思思路添加了一一些有趣的变变化。 它对对存储局部变变量的位置进进行重新排序序,并复制函函数参数中的的指针,以便便它们也在任任何数组之前前。这样增强强了ssp 的保护能力力;它意味着着缓冲区溢出出不会修改指指
24、针值(否则则能够控制指指针的攻击者者就能使用指指针来控制程程序保存数据据的位置)。默默认情况下,它它不会检测所所有函数,而而只是检测确确实需要保护护的函数(主主要是使用字字符数组的函函数)。从理理论上讲,这这样会稍微削削弱保护能力力,但是这种种默认行为改改进了性能,同同时仍然能够够防止大多数数问题。考虑虑到实用的因因素,它们以以独立于体系系结构的方式式使用 gccc 来实现现它们的方法法,从而使其其更易于运用用。从 20003 年 5 月的发发布版本开始始,广受赞誉誉的 OpeenBSD(它它重点关注安安全性)在他他们的整个发发行套件中使使用了 sssp(也称为为 ProPPolicee)。3
25、.3非执行的的堆栈防御:另一种方法首先先使得在堆栈栈上执行代码码变得不可能能。 遗憾的的是,x866 处理器(最最常见的处理理器)的内存存保护机制无无法容易地支支持这点;通通常,如果一一个内存页是是可读的,它它就是可执行行的。一个名名叫 Sollar Deesigneer 的开发发人员想出了了一种内核和和处理器机制制的聪明组合合,为 Liinux 内内核创建了一一个“非执行的堆堆栈补丁”;有了这个个补丁,堆栈栈上的程序就就不再能够像像通常的那样样在 x866 上运行。 事实证明在在有些情况下下,可执行程程序 需要在在堆栈上;这这包括信号处处理和跳板代代码(traampoliine)处理理。tr
26、ammpolinne 是有时时由编译器(比比如 GNAAT Adaa 编译器)生生成的奇妙结结构,用以支支持像嵌套子子例程之类的的结构。Soolar DDesignner 还解解决了如何在在防止攻击的的同时使这些些特殊情况不不受影响的问问题。 Linux 中中实现这个目目的的最初补补丁在 19998 年被被 Linuus Torrvaldss 拒绝,这这是因为一个个有趣的原因因。即使不能能将代码放到到堆栈上,攻攻击者也可以以利用缓冲区区溢出来使程程序“返回”某个现有的的子例程(比比如 C 库库中的某个子子例程),从从而进行攻击击。简而言之之,仅只是拥拥有非可执行行的堆栈是不不足够的。一段时间之
27、后,人人们又想出了了一种防止该该问题的新思思路:将所有有可执行代码码转移到一个个称为“ASCIII 保护(AASCII armorr)”区域的内存存区。要理解解这是如何工工作的,就必必须知道攻击击者通常不能能使用一般的的缓冲区溢出出攻击来插入入 ASCIII NULL 字符(00)这个事实实。 这意味味着攻击者会会发现,要使使一个程序返返回包含 00 的地址是是很困难的。由由于这个事实实,将所有可可执行代码转转移到包含 0 的地址址就会使得攻攻击该程序困困难多了。具有这个属性的的最大连续内内存范围是从从 0 到 0x0100101000 的一组内内存地址,因因此它们就被被命名为 AASCII
28、保护区域(还还有具有此属属性的其他地地址,但它们们是分散的)。与与非可执行的的堆栈相结合合,这种方法法就相当有价价值了:非可可执行的堆栈栈阻止攻击者者发送可执行行代码,而 ASCIII 保护内存存使得攻击者者难于通过利利用现有代码码来绕过非可可执行堆栈。这这样将保护程程序代码避免免堆栈、缓冲冲区和函数指指针溢出,而而且全都不需需重新编译。然而,ASCIII 保护内内存并不适用用于所有程序序;大程序也也许无法装入入 ASCIII 保护内内存区域(因因此这种保护护是不完美的的),而且有有时攻击者 能够将 00 插入目的的地址。 此此外,有些实实现不支持跳跳板代码,因因此可能必须须对需要这种种保护的
29、程序序禁用该特性性。Red Hat 的的 Ingoo Molnnar 在他他的“exec-shielld”补丁中实现现了这种思想想,该补丁由由 Fedoora 核心心(可从 RRed Haat 获得它它的免费版本本)所使用。最最新版本的 OpenWWall GGNU/Liinux (OWL)使使用了 Soolar DDesignner 提供供的这种方法法的实现(请请参阅 参考考资料 以获获得指向这些些版本的链接接)。 3.4其他方法法还有其他许多方方法。一种方方法就是使标标准库对攻击击更具抵抗力力。Luceent Teechnollogiess 开发了 Libsaafe,这是是多个标准 C 库
30、函数数的包装,也也就是像 sstrcpyy() 这样样已知的对 stackk-smasshing 攻击很脆弱弱的函数。LLibsaffe 是在 LGPL 下授予许可可证的开放源源代码软件。那那些函数的 libsaafe 版本本执行相关的的检查,确保保数组改写不不会超出堆栈栈桢。然而,这这种方法仅保保护那些特定定的函数,而而不是从总体体上防止堆栈栈溢出缺陷,并并且它仅保护护堆栈,而不不保护堆栈中中的局部变量量。它们的最最初实现使用用了 LD_PRELOOAD ,而而这可能与其其他程序产生生冲突。Liinux 的的 Manddrake 发行套件包包括了 liibsafee。 4.总结借助知识、谨慎
31、慎和工具,CC 和 C+ 中的缓缓冲区溢出缺缺陷是可以防防止的。不过过做起来并没没有那么容易易,特别是在在 C 中。如如果使用 CC 和 C+ 来编写写安全的程序序,您需要真真正理解缓冲冲区溢出和如如何防止它们们。一种替代方法是是使用另一种种编程语言,因因为如今的几几乎其他所有有语言都能防防止缓冲区溢溢出。但是使使用另一种语语言并不会消消除所有问题题。许多语言言依赖 C 库,并且许许多语言还具具有关闭该保保护特性的机机制(为速度度而牺牲安全全性)。但是是即便如此,不不管您使用哪哪种语言,开开发人员都可可能会犯其他他许多错误,从从而带来引入入缺陷。 5参考文献【1】蒋佳,刘刘新喜,信息息安全工程
32、,机机械工业出版版社,20003.48页【2】FlasshSky ,Windoows 20003堆溢出出及其利用技技术深入研究究,20033.8页【3】FlasshSky,缓冲区溢出漏洞发掘模型,2003.5【4】李涛,网网络安全概论论,北京:电电子工业出版版者,20004.4455页【5】启明星辰辰认证安全技技术工程师培培训【6】网络信息息安全概论【7】Willlian SStalliings,网网络安全基础础教程(第二二版),清华华大学出版社社,20044.337页页【8】阙喜戎 ,赵耀 ,王纯 ,龚向阳,Windoows系统中中基于缓冲区区溢出的攻击击的分析,22002.44页【9】姚奇富,网网络安全技术术,浙江大学学出版社,22006,1145页【10】姚建东东,秦军,古古志民,两种种新的缓冲区区溢出攻击原原理及防范,22006,55页