软件工程专业缓冲区溢出的保护实践_第1页
软件工程专业缓冲区溢出的保护实践_第2页
软件工程专业缓冲区溢出的保护实践_第3页
软件工程专业缓冲区溢出的保护实践_第4页
软件工程专业缓冲区溢出的保护实践_第5页
已阅读5页,还剩10页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

1、15/15*大学*学院信息安全产品开发实践课程设计报告题 目 缓冲区溢出的爱护 学生姓名 学 号_ _ 年 级 指导老师 指导老师评阅意见: 指导老师评分: 提交时刻: 2007年12月 缓冲区溢出的爱护(软件工程专业)学生 学号 指导教师 摘要:1999 年 Bugtraq(一个讨论安全缺陷的邮件列表)进行的一次非正式调查发觉,三分之二的参与者认为第一号的缺陷确实是缓冲区溢出。从 1997 年到 2007 年 3 月,CERT/CC 发出的半数安全警报都基于缓冲区缺陷。 面对如此大的威胁,我们需要明白什么是缓冲区溢出,如何防止它们,能够采纳哪些最新的自动化工具来防止它们以及什么缘故这些工具还

2、不足够,还有如何在编写程序的程序中防止它们。关键字:缓冲区溢出;溢出爱护;溢出防备 Detection Of Buffer Overflow Abstract: From an informal investigation on Bugtraq (a mail list which discuss a limitation on security) in 1999, we can find that two-parts participants thought that the No.1 limitation is buffer overflow. From 1997 to May, 2007

3、, almost half the secure warnings sent by CERT/CC were based on the limitation of buffer. Facing such a huge menace, we need to learn what is the buffer overflow, how to defend them, which kinds of the latest automatization tools we can used for avoid them , why these tools still not enough, and how

4、 to prevent them in programming.Keywords: Buffer Overflow,Overflow Detection, Overflow Defense 正文1 绪论1.1 立题背景缓冲区溢出是当前一些软件存在的最常见的安全隐患之一,通过提供一个恶意的输入黑客能够改变进程的执行流程,缓冲区溢出能够威胁到整个进程,机器,甚至相关的系统领域。假如运行的进程是在权限比较高的用户下面,比如administrator或者本地的系统帐户(Local System Account),那么黑客破坏所导致的损失将会专门严峻而且将会面临更广泛的潜在危胁。最近时期爆发的一些众所周

5、知的病毒像,红色代码病毒和震荡波蠕虫病毒,差不多上C/C+代码里存在着缓冲区溢出的结果。1.2 研究内容在几乎所有计算机语言中,不管是新的语言依旧旧的语言,使缓冲区溢出的任何尝试通常都会被该语言本身自动检测并阻止(比如通过引发一个异常或依照需要给缓冲区添加更多空间)。然而有两种语言不是如此:C 和 C+ 语言。C 和 C+ 语言通常只是让额外的数据乱写到其余内存的任何位置,而这种情况可能被利用从而导致恐惧的结果。更糟糕的是,用 C 和 C+ 编写正确的代码来始终如一地处理缓冲区溢出则更为困难;专门容易就会意外地导致缓冲区溢出。除了 C 和 C+ 使用得 特不广泛外,上述这些可能差不多上不相关的

6、事实;例如,Red Hat Linux 7.1 中 86% 的代码行差不多上用 C 或 C + 编写的。因此,大量的代码对那个问题差不多上脆弱的,因为实现语言无法爱护代码幸免那个问题。 在 C 和 C+ 语言本身中,那个问题是不容易解决的。该问题基于 C 语言的全然设计决定(特不是 C 语言中指针和数组的处理方式)。由于 C+ 是最兼容的 C 语言超集,它也具有相同的问题。存在一些能防止那个问题的 C/C+ 兼容版本,然而它们存在极其严峻的性能问题。而且一旦改变 C 语言来防止那个问题,它就不再是 C 语言了。许多语言(比如 Java 和 C#)在语法上类似 C,但它们实际上是不同的语言,将现

7、有 C 或 C+ 程序改为使用那些语言是一项艰巨的任务。有些语言存在同意缓冲区溢动身生的“转义”子句。Ada 一般会检测和防止缓冲区溢出(即针对如此的尝试引发一个异常),然而不同的程序可能会禁用那个特性。C# 一般会检测和防止缓冲区溢出,然而它同意程序员将某些例程定义为“不安全的”,而如此的代码 可能 会导致缓冲区溢出。因此假如您使用那些转义机制,就需要使用 C/C+ 程序所必须使用的相同种类的爱护机制。许多语言差不多上用 C 语言来实现的(至少部分是用 C 语言来实现的 ),同时用任何语言编写的所有程序本质上都依靠用 C 或 C+ 编写的库。因此,所有程序都会继承那些问题,因此了解这些问题是

8、专门重要的。 2缓冲区溢出的概述 2.1 缓冲区溢出的起源内存溢出差不多是软件开发历史上存在了近40年的“老大难”问题2.2缓冲区溢出如何工作计算机还有由程序共享, 随机访问内存 (RAM)。 为了简化, 内存治理 Windows XP SP 2 有功能操纵当前正在使用哪段的 RAM。 假如启动程序, 释放内存分配给程序。 该内存被分为三段: 代码段此处存储程序特定执行命令。 数据段此处程序特定数据存储。 堆栈是数据段 (一部分)此处存储所有与程序函数。 这包括参数、 缓冲区存储本地变量以及, 最重要、 返回地址。 返回地址指定执行函数后, 程序将接着从。作为是由用户输入该信息也注册作为变量,

9、 一切, 发送到堆栈用户类型。 不通常, 此行为不提出问题。 然而, 假如因编程错误, 超过缓冲区限制堆栈成为容易操纵。 整个段被指定为本地变量例如, 假如攻击者选择适当项关于攻击, 可能会覆盖用指令。 此外, 后续返回地址可更改为指向恶意代码。 因此, 程序不再正常, 但盲目执行攻击者的命令。内存的底部 内存的顶部 buffer1 sfp ret a b c 增长 . 堆栈的顶部 堆栈的底部 许多计算机处理器,包括所有 x86 处理器,都支持从高位地址向低位地址“倒”增长堆栈。因此,每当一个函数调用另一个函数,更多的数据将被添加到左边(低位地址),直至系统的堆栈空间耗尽。在那个例子中,当 m

10、ain() 调用 function1() 时,它将 c 的值压入堆栈,然后压入 b 的值,最后压入 a 的值。之后它压入 return (ret) 值,那个值在 function1() 完成时告诉 function1() 返回到 main() 中的何处。它还把所谓的“已保存的帧指针(saved frame pointer,sfp)”记录到堆栈上;这并不是必须保存的内容,此处我们不需要理解它。在任何情况下, function1() 在启动以后,它会为 buffer1() 预留空间,这在图 1 中显示为具有一个低地址位置。 现在假设攻击者发送了超过 buffer1() 所能处理的数据。接下来会发生

11、什么情况呢?因此,C 和 C+ 程序员可不能自动检查那个问题,因此除非程序员明确地阻止它,否则下一个值将进入内存中的“下一个”位置。那意味着攻击者能够改写 sfp (即已保存的帧指针),然后改写 ret (返回地址)。之后,当 function1() 完成时,它将“返回” 只是不是返回到 main() ,而是返回到攻击者想要运行的任何代码。 通常攻击者会使用它想要运行的恶意代码来使缓冲区溢出,然后攻击者会更改返回值以指向它们已发送的恶意代码。这意味着攻击者本质上能够在一个操作中完成整个攻击!Aleph On 的文章(请参阅 参考资料)详细介绍了如此的攻击代码是如何创建的。例如,将一个 ASCI

12、I 0 字符压入缓冲区通常是专门困难的,而该文介绍了攻击者一般如何能够解决那个问题。 除了 smashing-stack 和更改返回地址外,还存在利用缓冲区溢出缺陷的其他途径。与改写返回地址不同,攻击者能够 smashing-stack(使堆栈上的缓冲区溢出),然后改写局部变量以利用缓冲区溢出缺陷。缓冲区全然就不必在堆栈上 它能够是堆中动态分配的内存(也称为“malloc”或“new”区域),或者在某些静态分配的内存中(比如“global”或“static”内存)。差不多上,假如攻击者能够溢出缓冲区的边界,苦恼或许就会找上你了。 然而,最危险的缓冲区溢出攻击确实是 stack-smashing

13、 攻击,因为假如程序对攻击者专门脆弱,攻击者获得整个机器的操纵权就特不容易 2.3缓冲区溢出分类 2.3.1在程序的地址空间里安排适当的代码 2.3.1.1殖入法 攻击者用被攻击程序的缓冲区来存放攻击代码。 攻击者向被攻击的程序输入一个字符串,程序会把那个字符串放到缓冲区里。那个字符串包含的数据是能够在那个被攻击的硬件平台上运行的指令序列。 2.3.1.2利用差不多存在的代码 有时候,攻击者想要的代码差不多在被攻击的程序中了,攻击者所要做的只是对代码传递一些参数,然后使程序跳转到指定目标。比如,在C语言中,攻击代码要求执行“exec(/bin/sh)”,而在libc库中的代码执行“exec(a

14、rg)”,其中arg是指向一个字符串的指针参数,那么攻击者只要把传入的参数指针指向/bin/sh,就能够调转到libc库中的相应的指令序列。 2.3.2操纵程序转移到攻击代码这种方法旨在改变程序的执行流程,使之跳转到攻击代码。最差不多方法的确实是溢出一个没有边界检查或者其他弱点的缓冲区,如此就扰乱了程序的正常的执行顺序。通过溢出一个缓冲区,攻击者能够用近乎暴力的方法改写相邻的程序空间而直接跃过了系统的检查。 2.3.2.1激活纪录(Activation Records) 每当一个函数调用发生时,调用者会在堆栈中留下一个激活纪录,它包含了函数结束时返回的地址。攻击者通过溢出这些自动变量,使那个返

15、回地址指向攻击代码。通过改变程序的返回地址,当函数调用结束时,程序就跳转到攻击者设定的地址,而不是原先的地址。这类的缓冲区溢出被称为“stack smashing attack”,是目前常用的缓冲区溢出攻击方式。 2.3.2C语言中,“void (* foo)()”声明了一个返回值为void函数指针的变量foo。函数指针能够用来定位任何地址空间,因此攻击者只需在任何空间内的函数指针附近找到一个能够溢出的缓冲区,然后溢出那个缓冲区来改变函数指针。在某一时刻,当程序通过函数指针调用函数时,程序的流程就按攻击者的意图实现了!它的一个攻击范例确实是在Linux系统下的super probe程序。 2.

16、3.2在C语言中包含了一个简单的检验/恢复系统,称为setjmp/longjmp。意思是在检验点设定“setjmp(buffer)”,用“longjmp(buffer)”来恢复检验点。然而,假如攻击者能够进入缓冲区的空间,那么“longjmp(buffer)”实际上是跳转到攻击者的代码。象函数指针一样,longjmp缓冲区能够指向任何地点,因此攻击者所要做的确实是找到一个可供溢出的缓冲区。一个典型的例子确实是Perl 5.003,攻击者首先进入用来恢复缓冲区溢出的的longjmp缓冲区,然后诱导进入恢复模式,如此就使Perl的解释器跳转到攻击代码上了! 3. 缓冲区溢出的爱护因此,要让程序员

17、不犯常见错误是专门难的,而让程序(以及程序员)改为使用另一种语言通常更为困难。那么为何不让底层系统自动爱护程序幸免这些问题呢?最起码,幸免 stack-smashing 攻击是一件好事,因为 stack-smashing 攻击是特不容易做到的。 一般来讲,更改底层系统以幸免常见的安全问题是一个极好的方法,我们在本文后面也会遇到那个主题。事实证明存在许多可用的防备措施,而一些最受欢迎的措施可分组为以下类不: 3.1基于探测方法(canary)的防备。这包括 StackGuard(由 Immunix 所使用)、ProPolice(由 OpenBSD 所使用)和 Microsoft 的 /GS 选项

18、。 非执行的堆栈防备。这包括 Solar Designer 的 non-exec 补丁(由 OpenWall 所使用)和 exec shield(由 Red Hat/Fedora 所使用)。 其他方法。这包括 libsafe(由 Mandrake 所使用)和堆栈分割方法。 遗憾的是,迄今所见的所有方法都具有弱点,因此它们不是万能药,然而它们会提供一些关心。 3.2基于探测方法的防备 :研究人员 Crispen Cowan 创建了一个称为 StackGuard 的有味方法。Stackguard 修改 C 编译器(gcc),以便将一个“探测”值插入到返回地址的前面。“探测仪”就像煤矿中的探测仪:它

19、在某个地点出故障时发出警告。在任何函数返回之前,它执行检查以确保探测值没有改变。假如攻击者改写返回地址(作为 stack-smashing 攻击的一部分),探测仪的值或许就会改变,系统内就会相应地中止。这是一种有用的方法,只是要注意这种方法无法防止缓冲区溢出改写其他值(攻击者仍然能够利用这些值来攻击系统)。人们也曾扩展这种方法来爱护其他值(比如堆上的值)。Stackguard(以及其他防备措施)由 Immunix 所使用。 IBM 的 stack-smashing 爱护程序(ssp,起初名为 ProPolice)是 StackGuard 的方法的一种变化形式。像 StackGuard 一样,s

20、sp 使用一个修改过的编译器在函数调用中插入一个探测仪以检测堆栈溢出。然而,它给这种差不多的思路添加了一些有味的变化。 它对存储局部变量的位置进行重新排序,并复制函数参数中的指针,以便它们也在任何数组之前。如此增强了ssp 的爱护能力;它意味着缓冲区溢出可不能修改指针值(否则能够操纵指针的攻击者就能使用指针来操纵程序保存数据的位置)。默认情况下,它可不能检测所有函数,而只是检测确实需要爱护的函数(要紧是使用字符数组的函数)。从理论上讲,如此会略微削弱爱护能力,然而这种默认行为改进了性能,同时仍然能够防止大多数问题。考虑到有用的因素,它们以独立于体系结构的方式使用 gcc 来实现它们的方法,从而

21、使其更易于运用。从 2003 年 5 月的公布版本开始,广受赞誉的 OpenBSD(它重点关注安全性)在他们的整个发行套件中使用了 ssp(也称为 ProPolice)。3.3非执行的堆栈防备:另一种方法首先使得在堆栈上执行代码变得不可能。 遗憾的是,x86 处理器(最常见的处理器)的内存爱护机制无法容易地支持这点;通常,假如一个内存页是可读的,它确实是可执行的。一个名叫 Solar Designer 的开发人员想出了一种内核和处理器机制的聪慧组合,为 Linux 内核创建了一个“非执行的堆栈补丁”;有了那个补丁,堆栈上的程序就不再能够像通常的那样在 x86 上运行。 事实证明在有些情况下,可

22、执行程序 需要在堆栈上;这包括信号处理和跳板代码(trampoline)处理。trampoline 是有时由编译器(比如 GNAT Ada 编译器)生成的奇异结构,用以支持像嵌套子例程之类的结构。Solar Designer 还解决了如何在防止攻击的同时使这些专门情况不受阻碍的问题。 Linux 中实现那个目的的最初补丁在 1998 年被 Linus Torvalds 拒绝,这是因为一个有味的缘故。即使不能将代码放到堆栈上,攻击者也能够利用缓冲区溢出来使程序“返回”某个现有的子例程(比如 C 库中的某个子例程),从而进行攻击。简而言之,仅只是拥有非可执行的堆栈是不足够的。一段时刻之后,人们又想

23、出了一种防止该问题的新思路:将所有可执行代码转移到一个称为“ASCII 爱护(ASCII armor)”区域的内存区。要理解这是如何工作的,就必须明白攻击者通常不能使用一般的缓冲区溢出攻击来插入 ASCII NUL 字符(0)那个事实。 这意味着攻击者会发觉,要使一个程序返回包含 0 的地址是专门困难的。由于那个事实,将所有可执行代码转移到包含 0 的地址就会使得攻击该程序困难多了。具有那个属性的最大连续内存范围是从 0 到 0 x01010100 的一组内存地址,因此它们就被命名为 ASCII 爱护区域(还有具有此属性的其他地址,但它们是分散的)。与非可执行的堆栈相结合,这种方法就相当有价值

24、了:非可执行的堆栈阻止攻击者发送可执行代码,而 ASCII 爱护内存使得攻击者难于通过利用现有代码来绕过非可执行堆栈。如此将爱护程序代码幸免堆栈、缓冲区和函数指针溢出,而且全都不需重新编译。然而,ASCII 爱护内存并不适用于所有程序;大程序也许无法装入 ASCII 爱护内存区域(因此这种爱护是不完美的),而且有时攻击者 能够将 0 插入目的地址。 此外,有些实现不支持跳板代码,因此可能必须对需要这种爱护的程序禁用该特性。Red Hat 的 Ingo Molnar 在他的“exec-shield”补丁中实现了这种思想,该补丁由 Fedora 核心(可从 Red Hat 获得它的免费版本)所使用。最新版本的 OpenWall GNU/Linux (OWL)使用了 Solar Designer 提供的这种方法的实现(请参阅 参考资料 以获得指向这些版本的链接)。 3.4其他方法还有其他许多方法。一种方法确实是使标准库对攻击更具抵抗力。Lucent Technologies 开发了 Libsafe,这是多个标准 C 库函数的包装,也确实是像 strcpy() 如此已知

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论