联系我们 更多+

电话:028-86911314

手机:17098380137

投稿:[email protected]

地址:成都市一环路北一段113号

QQ在线客服 QQ在线客服 QQ在线客服 QQ在线客服
缓冲区溢出的原理及防范
当前位置:首页 » 论文欣赏 » 计算机论文 »
缓冲区溢出的原理及防范

The Principle and Precaution of Buffer Overflow
【摘要】随着 Internet 及相关信息技术的迅速发展,网上的电子商务呈现出极大的增长势头,但投入的增多意味着风险
也随之而来, 网络安全问题成为各种网上活动需要考虑的头等大事。 本文重点探讨一下缓冲区溢出对计算机系统造成的
危害。因为几十年来,缓冲区溢出一直引起许多严重的安全性问题。近年由 CERT/CC(Computer Emergency Response
Term/Coodination Center)发布的忠告中关于缓冲区溢出漏洞占 56.76%以上。本文首先解释了缓冲区溢出的概念,从程
序语言本身存在缺陷,不够健壮的角度出发,对缓冲区溢出的原理进行了详细的阐述;之后,结合缓冲区溢出攻击的类
型,从系统管理和软件开发两个角度提出了缓冲区溢出攻击的防范策略。
【关键词】缓冲区溢出  攻击
【ABSTRACT】With the development of Internet and information technology, the great growth has appeared out in
E-Commerce. But this trend lead to more venture, network security issue has become the cardinal task that various kinds of online
activity need to consider.At present, the biggest problem on network is that computer software is usually not stalwart enough,
sometimes such barrier will cause catastrophic result, especially when being utilized maliciously by the lawless person, the harm will
hard to estimate.Buffer overflow attacking is a seriously problem in network security and cause serious security problems in recently
years. Some program language have pestilent bug, for example, C program language doesn’t check the border of the array of
number is apt to cause the buffer overflow, and therefore possibly cause the failure of program processing and paralysis of computer.
This paper analysis deeply the principle and possibility of buffer overflow attacking, and point out buffer overflow’s potential
dangers. At last, according to the kinds of buffer overflow attacking, I put forward my own opinion of precautionary measures on
buffer overflow attacking.
【Key Words】buffer overflow    attacking

第一章 缓冲区溢出简介
1.1  什么是缓冲区溢出
缓冲区溢出开始于每个程序都需要的一些情况:放置位元
的空间。多数计算机程序都在内存中创建多个地址用于信息存
储。 C 编程语言允许程序员在运行时在内存的两个不同部分 (堆
栈和堆)中创建存储器。通常,分配到堆的数据是那些 malloc()
或新建时获得的数据。而分配到堆栈的数据一般包括非静态的
局部变量和所有按值传递的参数。大部分其它信息存储在全局
静态存储器中。在分配同一数据类型的相邻块时,这块内存区
域称为缓冲区。
在写入缓冲区时,C 程序员必须注意存储在缓冲区中的数
据不能超过它所能容纳的量。缓冲区只能容纳一定数量的位,
如果试图放入缓冲区的数据比它能装入的要多,额外的数据就
会溢出到别处,并且您不希望它到其它地方!
当程序写入超过缓冲区的边界时,这就是所谓的“缓冲区
溢出” 。发生缓冲区溢出时,会覆盖下一个相邻的内存块。由于
C 语言本质上的不安全性,所以它允许程序随意(或者更准确
地说是完全出于偶然)溢出缓冲区。没有运行时检查来防止写
入超过缓冲区末尾,所以程序员必须在其自己的代码中执行这
一检查,否则继续下去会遇到问题。
读取或写入超过缓冲区的末尾时,会导致许多不同(并且
通常是不可预料的)行为:1) 程序的执行很奇怪,2) 程序完全
失败, 或者 3) 程序可以继续, 而且在执行中没有任何明显不同。
缓冲区溢出的副作用取决于:

写入的数据中有多少超过缓冲区边界

当缓冲区已满并且溢出时,覆盖了哪些数据(如果有
的话)

程序是否试图读取溢出期间被覆盖的数据

哪些数据最终替换被覆盖的内存
存在缓冲区溢出的程序的不确定行为使得对它们的调试异
常棘手。最坏的情况是:程序可能正发生缓冲区溢出,但根本
没有任何副作用的迹象。因此,缓冲区溢出问题常常在标准测
试期间是发现不了的。认识缓冲区溢出的重要一点是:在发生
溢出时,会潜在地修改碰巧分配在缓冲区附近的任何数据。
1.2  为什么缓冲区溢出是安全问题
当缓冲区溢出时,额外的数据会摧残程序将来可能要访问
的其它有用的数据。有时,这些其它数据的更改会导致安全性
问题。
最简单的情况就是考虑直接在缓冲区后面的内存中分配一
个布尔标志。这个标志决定运行程序的用户是否可以访问专用
文件。如果有不怀好意的用户覆盖缓冲区,则会更改标志的值,
从而指出攻击者是非法访问专用文件。
缓冲区溢出导致安全性问题的另一个方法是通过摧毁堆
栈。摧毁堆栈的目的是导致一个特定的编程故障:不仔细使用
分配在程序运行时堆栈上的数据缓冲区,即局部变量和函数自
变量。有创造力的攻击者会通过摧毁堆栈利用缓冲区溢出的弱
点,然后运行任何代码。这种想法是相当直接的:在某处插入
一些攻击代码并以将控制传递给攻击代码的方式来覆盖堆栈。
一般地,攻击者利用缓冲区溢出得到机器上的交互式会话。
如果被利用的程序以较高的优先权在运行,则攻击者就会在交
互式会话中得到该优先权。最惊人的缓冲区溢出是堆栈的摧毁,
它会在超级用户或 root、shell 中造成后果。
1.3  缓冲区溢出问题的现状
据了解,大约 80%的安全事件与缓冲区溢出有关。这个特
别的安全问题引发的病毒感染可能比其它原因引发的病毒感染
数量的总和还要多。市场上几乎每个应用程序和操作系统都存
在黑客可能利用的缓冲区溢出漏洞。这可能让我们觉得很糟糕,
但是最糟糕的是:这一问题不但没有(至少到现在为止似乎没
有)得到很好的解决,反而有越变越糟的倾向。
第二章 缓冲区溢出的防范策略
缓冲区溢出攻击的防范是和整个系统的安全性分不开的。
如果整个网络系统的安全设计很差,则遭受缓冲区溢出攻击的
机会也大大增加。针对缓冲区溢出,我们可以采取多种防范策
略。

2.1  系统管理上的防范策略
(1)关闭不需要的特权程序
由于缓冲区溢出只有在获得更高的特权时才有意义,所以
带有特权的 Unix 下的 suid 程序和 Windows 下由系统管理员启动
的服务进程都经常是缓冲区溢出攻击的目标。这时候,关闭一
些不必要的特权程序就可以降低被攻击的风险。当有缓冲区溢
出漏洞的程序还没有补丁时,就可以用这种方法。
(2)及时给程序漏洞打补丁
这是漏洞出现后最迅速有效的补救措施。大部分的入侵是
利用一些已被公布的漏洞达成的,如能及时补上这些漏洞,无
疑极大的增强了系统抵抗攻击的能力。
这两种措施对管理员来说,代价都不是很高,但能很有效
地防止住大部分的攻击企图。
2.2  软件开发过程中的防范策略
发生缓冲区溢出的主要及各要素是:数组没有边界检查而
导致的缓冲区溢出;函数返回地址或函数指针被改变,使程序
流程的改变成为可能;植入代码被成功的执行等等。所以针对
这些要素,从技术上我们就可以采取一定的措施。
(1)编写正确的代码
只要我们在所有拷贝数据的地方进行数据长度和有效性的
检查,确保目标缓冲区中数据不越界并有效,则就可以避免缓
冲区溢出,更不可能使程序跳转到恶意代码上。但是诸如 C/C++
自身是一种不进行强类型和长度检查的一种程序设计语言,而
程序员在编写代码时由于开发速度和代码的简洁性,往往忽视
了程序的健壮性,从而导致缓冲区溢出,因此我们必须从程序
语言和系统结构方面加强防范。
很多不安全程序的出现是由于调用了一些不安全的库函
数,这些库函数往往没有对数组边界进行检查。所以一种简单
的方法是利用 grep 搜索源程序,找出对这些函数的调用,然后
代以更安全的函数。进一步的查找可以是检查更广范围的不安
全操作,如在一个不定循环中对数组的赋值等。
可用的另一种措施是漏洞探测。利用一些工具,人为随机
地产生一些缓冲区溢出来寻找代码的安全漏洞。已有这方面的
一些高级的查错工具,如 fault injection 等。
(2)缓冲区不可执行
通过使被攻击程序的数据段地址空间不可执行,从而使得
攻击者不可能执行已植入被攻击程序输入缓冲区的代码,这种
技术被称为缓冲区不可执行技术。事实上,很多老的 Unix 系统
都是这样设计的, 但是近来的 Unix 和 MS Windows 系统为实现更
好的性能和功能,往往在数据段中动态地放入可执行的代码。
所以为了保持程序的兼容性不可能使得所有程序的数据段不可
执行。但是我们可以设定堆栈数据段不可执行,这样就可以最
大限度地保证了程序的兼容性。Linux 和 Solaris 都发布了有关这
方面的内核补丁。因为几乎没有任何合法的程序会在堆栈中存
放代码,这种做法几乎不产生任何兼容性问题。
(3)改进 C 语言函数库
C 语言中存在缓冲区溢出攻击隐患的系统函数有很多。 例如
gets(),sprintf(),strcpy(),strcat()等。可以开发出更安全的封装了
若干已知易受堆栈溢出攻击的库函数。修改后的库函数实现了
原有功能,但在某种程度上可以确保任一缓冲区溢出都被控制
在现有堆栈帧之内。
(4)数组边界检查
可以说缓冲区溢出的根本原因是没有数组边界检查,当数
组被溢出的时候,一些关键的数据就有可能被修改。同时,攻
击代码也可以被植入。
因此,对数组进行边界检查,使超长代码不可能植入,这
样就完全没有了缓冲区溢出攻击产生的条件。只要数组不能被
溢出,溢出攻击就无从谈起。
为了实现数组边界检查,则所有的对数组的读写操作都应
当被检查,以确保对数组的操作在正确的范围内。最直接的方
法是检查所有的数组操作,但是会使性能下降很多,通常可以
采用一些优化的技术来减少检查的次数。
(5)使堆栈向高地址方向增长
缓冲区溢出的一个重要要素是植入的代码成功地被执行。
最常见的是被植入的代码放在堆栈区中。通过修改操作系统核
心,在核心层引入保护机制,限制代码在堆栈区的执行,这样,
缓冲区溢出攻击就不可能成功。
到目前为止,我们讨论利用函数返回地址控制程序转移到
攻击代码的攻击方法时,有一个基本的前提,那就是当堆栈被
压入数据时,栈顶向低地址方向增长,只有这样,缓冲区溢出
时才可能覆盖低地址处的函数返回地址指针,从而控制程序转
移到攻击代码。如果我们使用的机器堆栈压入数据时向高地址
方向前进,那么无论缓冲区如何溢出,都不可能覆盖低地址处
的函数返回地址指针,也就避免了缓冲区溢出攻击。但是这种
方法仍然无法防范利用堆和静态数据段的缓冲区进行溢出的攻
击。
(6)程序指针完整性检查
程序指针完整性检查是针对上述缓冲区溢出的另一个要素
——阻止由于函数返回地址或函数指针的改变而导致的程序执
行流程的改变。它的原理是在每次在程序指针被引用之前先检
测该指针是否已被恶意改动过,如果发现被改动,程序就拒绝
执行。
因此,即使一个攻击者成功地改变程序的指针,由于系统
事先检测到了指针的改变,因此这个指针不会被使用。与数组
边界检查相比,这种方法不能解决所有的缓冲区溢出问题。但
这种方法在性能上有很大的优势,而且兼容性也很好。
程序指针完整性检查大体上有三个研究方向:第一,手写
的堆栈检测;第二,堆栈保护;第三,保护指针。
1)手写的堆栈监测
Snarskii 为 FreeBSD 开发了一套定制的能通过监测 cpu 堆栈
来确定缓冲区溢出的 libc。这个应用完全用手工汇编写的,而且
只保护 libc 中的当前有效纪录函数。这个应用达到了设计要求,
对于基于 libc 库函数的攻击具有很好的防卫,但是不能防卫其
它方式的攻击。
2)堆栈保护:编译器生成的有效纪录完整性检测
堆栈保护是一种提供程序指针完整性检查的编译器技术,
通过检查函数活动纪录中的返回地址来实现。堆栈保护作为 gcc
的一个小的补丁,在每个函数中,加入了函数建立和销毁的代
码。加入的函数建立代码实际上在堆栈中函数返回地址后面加
了一些附加的字节。而在函数返回时,首先检查这个附加的字
节是否被改动过。如果发生过缓冲区溢出的攻击,那么这种攻
击很容易在函数返回前被检测到。
3)指针保护:编译器生成程序指针完整性检查
在堆栈保护设计的时候,冲击堆栈构成了缓冲区溢出攻击
的常见的一种形式。指针保护是堆栈保护针对这种情况的一个
。通过在所有的代码指针之后放置附加字节来检验指针在
被调用之前的合法性。如果检验失败,会发出报警信号和退出
程序的执行,就如同在堆栈保护中的行为一样。
(7)利用编译器将静态数据段中的函数地址指针存放地址
和其他数据的存放地址分离
我们知道缓冲区溢出的一个基本条件是在缓冲区的高地址
附近存放着可供溢出覆盖的函数地址指针,如果我们破坏了这
一条件,就会使缓冲区溢出不能覆盖函数地址指针。比如,我
们可以假定编译器在编译程序时会将静态数据段中的函数地址

指针存放地址和其他数据的存放地址隔开相当大的一段距离,
例如数十兆,数百兆,这样才会迫使攻击者只有送入长的出乎
想象数据才能抵达函数地址指针存放地址并覆盖它,以这样的
不可操作性来制止攻击者实现攻击意图。另外,我们还可以使
这两种数据段间的线形地址空间不分配物理地址并设置为不可
读写,这些都可以通过硬件实现,这样每当缓冲区溢出进入这
段区域,就会出现地址保护错误,从而阻止了缓冲区溢出攻击。
另外一种较为简洁的方法是始终保持使静态数据段中的函
数地址指针存放地址低于其他数据的存放地址。但是这个方法
仅仅是防止了静态数据段中的缓冲区溢出攻击,而不能避免堆
的缓冲区溢出攻击,因为编译器和操作系统并不知道用户申请
的内存是用来存放函数地址指针还是其他数据,从而无法为其
隔离分配内存。表 1 是针对静态数据段、堆栈和堆的缓冲区溢
出的防范策略,其中没有把边界检查包括在内,因为它能有效
地防止所有的缓冲区溢出。
表 1    缓冲区溢出的防范策略
第三章 总结
缓冲区溢出是当今很流行的一种网络攻击方法,它易于攻
击而且危害严重,给系统的安全带来了极大的隐患。因此,如
何及时有效地检测出计算机网络系统入侵行为,已越来越成为
网络安全管理的一项重要内容。缓冲区溢出的漏洞一般有以下
几种情况:
(1)系统漏洞
如操作系统、服务器程序、数据库程序等,这种漏洞可以
通过升级软件、打安全“补丁”等方法来解决。
(2)应用软件
在软件开发过程中,如果程序员没有很强的安全意识和良
好的编程习惯,也会产生很多安全漏洞。
本文从上面的系统环境及程序设计语言角度,对目前主要
的网络攻击方式:缓冲区溢出攻击的出现和原理进行了详细的
分析,并根据缓冲区溢出攻击的类型提出了相应的防范策略。
然而,飞速发展的网络技术还需要我们继续对各种黑客攻
击系统的方法做更多的关注和应付措施的探索,为网络安全做
出更大的实践意义的研究。
【参考文献】
[1]Gary McGraw、John Viega: 《使您的软件运行起来:了解
有关缓冲区溢出方面的基础知识》
[2]刘欣、余兆力(公安部第三研究所) : 《fp30reg.dll 动态库
存在缓存溢出》
[3]www.nsfocus.com(绿盟)

上一篇:
下一篇:

dota竞猜dota2比赛竞猜dota2赛事竞猜