网络安全课程设计基于缓冲区溢出的漏洞研究.docx
- 文档编号:3621654
- 上传时间:2022-11-24
- 格式:DOCX
- 页数:14
- 大小:189.55KB
网络安全课程设计基于缓冲区溢出的漏洞研究.docx
《网络安全课程设计基于缓冲区溢出的漏洞研究.docx》由会员分享,可在线阅读,更多相关《网络安全课程设计基于缓冲区溢出的漏洞研究.docx(14页珍藏版)》请在冰豆网上搜索。
网络安全课程设计基于缓冲区溢出的漏洞研究
《网络安全》期末考试
(课程设计总结)
设计名称基于缓冲区溢出的漏洞研究
姓名
指导教师
班级2014级计本班
成绩
2016年12月
摘要:
缓冲区溢出攻击是网络攻击事件中最常用的一种攻击方式,成为系统和网络安全中函待解决的重要问题在分析缓冲区溢出攻击原理的基础上,说明了攻击的成因,然后描述了目前常见的攻击类型,最后给出了应如何做出防范措施,以及处理该漏洞的解决方案。
关键词:
缓冲区溢出攻击;系统安全;边界检查
目录
第一章引言....................................................................................................................1
第二章攻击原理及危害...............................................................................................2
第三章造成攻击的技术原因......................................................................................3
3.1缺少必要的边界检查....................................................................................................3
3.2操作系统设计策略上的隐患........................................................................................3
第四章攻击类型.........................................................................................................3
4.1基于堆栈的缓冲区溢出攻击..........................................................................................3
4.2基于堆的缓冲区溢出攻击.............................................................................................4
4.3基于LB库的缓冲区溢出攻击.....................................................................................9
第五章防范措施..........................................................................................................10
5.1安全编码........................................................................................................................10
5.2非可执行的缓冲区..........................................................................................................10
5.3数组边界检查.................................................................................................................10
5.4加强对返回地址的保护..................................................................................................11
5.5了解系统常见进程..........................................................................................................11
5.6及时打补丁或升级..........................................................................................................11
5.7从系统级和编译器两个方而来加强对内存空间的管理................................................11
第六章结论.................................................................................................................12
参考文献..........................................................................................................................12
第一章引言
自从缓冲区溢出漏洞被发现以来,缓冲区溢出攻击一直是网络攻击事件中用得最多的一种攻击方式,成为系统和网络安全中履待解决的重要问题。
早在1988年,美国康奈尔大学计算机科学系研究生莫里斯就利用UNIXFingered不限输入长度等漏洞感染了互联网中的数万台机器;2003年8月席卷全球的“冲击波(Woim.MSBlast)"和2004年5月出现的“震荡波(WoimSasser)"[1]分别利用了Windows系统RPCDCOM和LSASS服务的缓冲区溢出漏洞进行攻击。
2016年9月份中国国家信息安全漏洞库[2]发布的漏洞类型分布如图1所示,缓冲区溢出类漏洞数量大幅度上升,达到122个,是上月数量(62个)的近2倍,占10月漏洞总量的17.38%,排名第一。
从中国国家信息安全漏洞库公布的统计数据中可以看出,无论是在绝对数量上还是相对比例上缓冲区溢出攻击的问题正在扩大。
如图1-1:
图1-1中国国家信息安全漏洞库2016年发布的漏洞类型、数量、比例
由于缓冲区溢出攻击危害的严重性,使它至今仍是人们研究的重要课题,文章在总结当前已有研究成果的基础上提出了解决该问题的方案。
第二章攻击原理及危害
要对缓冲区溢出攻击的原理有个清楚认识,就必须先对可执行文件执行时的内存结构[2]有个总体了解。
一般程序从逻辑上可分为两大部分:
代码区和数据区。
数据区从逻辑上可划分为静态数据、堆栈和堆三部分,它们之间的区别依赖于各部分对应内存分配的时间和方式以及数据存储的位置。
总体来说,Windowss平台下程序的内存结构如图2-1所示,Linux或UNIX平台下程序的内存结构如图2-2所示。
高端内存
未初始化静态数据
已初始化静态数据
代码段
堆
堆栈
低端内存
图2-1Windows下程序在内存中的结构
高端内存
堆栈
堆
未初始化静态数据
已初始化静态数据
代码段
低端内存
图2-2UNIX下程序在内存中的结构
通常所说的缓冲区溢出指的就是“堆栈和堆”这两部分空间中产生了溢出。
正如微软给缓冲区溢出所下定义中所说的,缓冲区溢出是因为人们向程序中提交的数据超出了数据接收区所能容纳的最大长度,从而使提交的数据超过相应的边界而进入了其他区域。
如果是人为蓄意提交超长数据且对系统正常运行造成了不良影响,那么我们就说发生了缓冲区溢出攻击。
缓冲区溢出攻击通常会带来以下后果:
1、过长的宇符串覆盖了相邻的存储单元而造成程序异常,严重的会造成死机、系统或进程重启等;
2、可让攻击者执行恶意代码或特定指令,甚至获得超级权限等,从而引发其他的攻击。
第三章造成攻击的技术原因
3.1缺少必要的边界检查
这方面最明显的例子是C和C++语言。
由于一开始设计的时候C和C++就没有为数组和宇符指针的引用提供任何的边界检查机制,从而导致了它们的不安全性。
而它们是日常开发中使用最广的语言,甚至连Windows/UNIX这两个广泛使用的操作系统的很多模块也是用它们开发的,所以造成现在缓冲区溢出漏洞频频暴露。
并且用它们开发的大部分软件在今后很长一段时间里仍会被使用,这也就给缓冲区溢出攻击的存在提供了有利环境。
3.2操作系统设计策略上的隐患
这方而主要是指堆栈和堆数据区的可执行性属性。
UNIX和MSWindows系统为实现更好的性能和功能,往往在数据段中动态地放入可执行的代码[4],以保持程序的兼容性,使堆栈和堆具有可执行的属性。
但从两者用途本质——存储数据来看,赋予堆栈和堆可执行的属性是不必要的。
而且堆栈和堆作为程序与用户交互的窗口,赋予其可执行的权力对系统安全构成了威肋。
第四章攻击类型
任何类型的缓冲区溢出攻击要达到预定的攻击口的通常要完成两个任务:
在程序的地址空间里安排适当的代码;通过适当初始化寄存器和存储器,让程序跳转到安排好的地址空间执行。
根据完成这两个任务时着眼点不同,可以将缓冲区溢出攻击分为以下三种主要类型。
4.1基于堆栈的缓冲区溢出攻击
当一个函数被调用的时候,系统总是先将被调用函数所需的参数以逆序方式入栈,然后将调用指令后面那条指令的地址(即返回地址)入栈。
随后控制转入被调用的函数去执行。
程序一般在将需要保存的寄存器的值入栈后开始为被调用函数内的局部变量分配所需的存储空间,从而形成如图4所示的堆栈的结构,然后接下去执行其他指令。
基于堆栈的缓冲区溢出攻击之所以会发生主要与堆栈对宇符串的处理方式有关(因为大部分溢出都是通过精心构造的宇符串来触发的,所以我们这里只考虑宇符串的处理),虽然堆栈在为宇符数组分配空间时是按其出现的先后顺序从高端内存向低端内存依次分配,但在实际为宇符数组赋值时却是按从低端内存向高端内存的方向来操作。
由于程序缺少必要的边界检查,所以从图4中我们不难发现,如果局部变量中有宇符数组存在,只要赋予该数组的宇符串足够长,我们就能将上而的返回地址给覆盖掉。
这样,缓冲区溢出也就发生了。
堆栈中的返回地址决定了函数执行完后的去向,所以只要精心构造溢出用的宇符串,将对应返回地址的那几个宇节替换成想让程序完成后转向的地址(记作A),那么在被调用函数执行完后,程序就会转到A所指定的地方。
如果地址A所指定的内存空间事先存放了设计好的攻击代码,那么攻击也就随之发生了。
现实中的很多此类攻击正是通过精心设计溢出所用的宇符串,通过该宇符串将攻击代码和所需的跳转地址植入有此漏洞的程序中的。
4.2基于堆的缓冲区溢出攻击
在引入一个基于堆的缓冲区溢出的例子前,首先简单介绍例题的意图:
在一个堆栈里边申请两块存储空间,处于低地址的buf1和处于高地址的buf2。
在buf2当中,存储了一个名为myoutfile的字符串,用来存储文件名;buf1用来接收输入,同时将这些输入字符写入到buf2存储的文件名myoutfile所指向的文件中。
图41是具体的代码。
图41具体代码
通过malloc命令,申请了两个堆的存储空间。
在这里要注意分配堆的存储空间时,存在一个顺序问题。
buf2的申请命令虽然在buf1的申请命令之前,但是在运行过程中,内存空间中buf2是在高地址位,buf1是在低地址位。
这个随操作系统和编译器的不同而不同。
接着定义了diff变量,它记录了buf1和buf2之间的地址距离,也就是说buf1和buf2之间还有多少存储空间。
fopen语句将buf2指向的文件打开,打开的形式是追加行,用了关键字“a”。
即打开这个文件后,如果这个文件是以前存在的,那么写入的文件就添加到已有的内容之后;如果是以前不存在的一个文件,就创建这个文件并写入相应的内容。
用fprint语句将buf1中已经获得的语句写入到这个文件里。
然后关闭文件。
那我们来看一下这个程序的执行效果。
在输入字符串之前,buf1的存储地址在低地址,buf2在高地址,存储的内容就是我们输入的myoutfile,两块存储区的距离是64字节(注:
两块存储区的距离随操作系统和编译器的不同而不同),如图42所示。
当输入长度为60字节的字符串的时候,效果如图43所示。
图4-2两块存储区的距离
图43输入长度为60字节
正常的存储空间如图44所示。
现在我们增加输入字符串长度,输入长度刚好为64个字节的字符串,系统弹出了一个出错的信息,如图3.5.35所示。
“Expression:
*file!
=_T(‘\0’)”的含义为输入的文件名不能为\0。
此时buf1中存储的内容是64个字节长的字符串,而buf2中已经没有任何内容了。
当我们输入了64个字节的字符串后,实际在内存中填充的并不仅仅是64个字节,而是65个字节。
这是由于一个字符串的结束是以\0为标志的,且是系统自动添加的。
当我们填充了64个字节的字符串后,从低地址向高地址方向增长,buf1已经被填充满了,而这个\0必然要突破buf1的存储空间,而扩展到了buf2存储空间的开始,所以buf2的起始地方就变成了\0。
当程序输出buf2字符串的时候,首先读到的是\0,因而认为是一个空字符串,出现了图45所示的警告。
图44内存中堆的存储空间
图45警告
再次执行这个程序,继续增加输入字符串的长度为大于64个字节,而且刻意构造一个自定义的字符串“hostility”,是输入为“64字节填充数据”+“hostility”。
可见buf1的内容长度是超过了64个字节的,而buf2的内容就变成了hostility。
按照程序的流程,将会将内容写入到了文件名为hostility的文件当中去。
如图46所示为在内存中堆的存储空间。
图46内存中堆的存储空间
首先buf1填充了大于64个字节的字符串,余下的hostility就扩展到了buf2的空间之中。
同样,字符串要以\0表示结束。
但是原先的buf2中的内容也有一个\0表示字符串的结束,但是这个\0落在了hostility的\0的后边,所以系统当看到hostility后边的\0时就认为字符串结束了,所以输出的是hostility。
而读取buf1的内容时候,到存储空间结束也没有遇到\0,那么它就继续往下读,直到遇见了\0,所以它读取的长度已经超过了它本身分配的存储空间的长度。
这样就构造了一个新的文件名覆盖了原先的内容,从而输出到一个我们定制的文件中,产生了基于堆的溢出。
由于程序所需的数据和空间并不是在一开始或程序编写的过程中就能完全确定的,这就要求有一种机制使我们能根据具体情况来分配所需的空间,堆正是应此需求而被提出的。
系统在创建新进程的时候为其分配相应的内存空间作为该进程的默认堆,当然在进程执行过程中用户可以根据需要申请新的堆空间,但不论是默认堆,还是用户后来申请的堆,它们的组织结构是一样的,均如图4-7所示。
其中,通过多次实验证实Windows平台下双指针区中重复存储了放有下次分配的起始地址的内存的地址。
高端内存
参数n
……
参数1
……
局部变量1
……
局部变量n
低端内存
图4-7堆栈结构
高端内存
……
双指针区
下一个空闲堆的管理结构
BufferN
BufferN管理结构
……
Buffer1
Buffer1管理结构
堆的总体管理结构
低端内存
图4-8堆的结构
由于堆在分配和释放时的动态性,使得利用堆进行缓冲区溢出攻击要比利用堆栈难得多,并且基于堆的缓冲区溢出攻击也不像基于堆栈的缓冲区溢出攻击那样有固定模式可用,这就是基于堆的溢出攻击在现实中比较少的原因。
基于堆的缓冲区溢出攻击会因为堆溢出后产生的后果不同而有不同的利用方式。
常见的利用方式有:
(1)改写内存参数。
通过改写程序中重要变量的值,比如某个宇符串的长度等,使程序在运行中再产生其他溢出。
这种方法一般只能改写数据段里而的东西,因为该位置相对固定并且可写。
(2)改变程序中函数指针值。
通过溢出将该函数指针的值改为攻击者想让程序跳转到的位置,当程序中调用该函数指针指向的函数时,系统转去执行那里的指令,从而达到攻击的口的。
从上而所述的两种利用方式也可以看出,基于堆的缓冲区溢出攻击并不像基于堆栈的那样简单,它没有较为通用的模式,所需的条件有时也比较苛刻。
4.3基于LB库的缓冲区溢出攻击
上而两类攻击都是利用自己开发的攻击代码来执行操作,需要解决攻击代码的定位和跳转问题,而基于LIB库的缓冲区溢出攻击方法避兔了这两个问题并躲过了堆栈和堆不可执行的保护措施。
该方法利用的是系统中现成的LIB库函数,不用手动植入攻击代码。
这种方法之所以能成功,是因为有些系统函数(如WinExec(),system()等)是根据参数中给出的函数名称(andexe)来调用相应的函数。
利用这种方法需要解决的问题是,将完成特定口的所需数据存放合适的位置,并想办法使程序跳转到特定库函数的入口。
这种方法会用到上而两类攻击的一些技巧。
第五章防范措施
面对缓冲区溢出攻击的挑战,根据各种攻击的机制,提出了不同的防范措施。
现在常见的防范措施主要有如下几种。
5.1安全编码
现在缓冲区溢出攻击之所以成为主要攻击手段,除了开发语言本身和操作系统设计策略上的缺陷外,人为因素也占了很大比重。
由于以前人们的安全编码意识不强或者急于完成任务而忽略了对所编代码安全性的检查,所以造成隐患。
提高编码者的安全意识,消除造成缓冲区溢出攻击的人为因素,可以大大减少这类攻击的发生。
这一点可以从已发生过的攻击事件中得以证实。
安全编码首先尽量选用自带边界检查的语言(如PerlPython和Java等)来进行程序开发;其次在使用像C这类的开发语言时要做到尽量调用安全的库函数,对不安全的调用进行必要的边界检查。
编写正确代码,除了人为注意外,还可以借助现有的一些工具。
例如,使用源代码扫描工具PurifyPlus可以帮助发现程序中可能导致缓冲区溢出的部分。
这种措施的缺点是:
对人的依赖性太强,现实中程序员要受多方而因素的影响,很难取得满意的效果。
5.2非可执行的缓冲区
由第4节,我们会发现除了基于LIB库的缓冲区溢出攻击外,所有其他的攻击方式之所以得逞正是由于操作系统赋予了缓冲区可执行的属性。
取消缓冲区的可执行性属性,虽然会引起操作系统作相应的变化,但对遏制缓冲区溢出攻击的作用却非常显著。
这种方法对基于堆栈和堆的缓冲溢出的攻击效果较好,但对基于LIB库的缓冲区溢出攻击却无能为力。
5.3数组边界检查
通过对所输入的或将传给函数的宇符串的长度做严格的边界检查,就可杜绝溢出的发生,也就不可能再发生缓冲区溢出攻击。
这种措施的缺点同上述,即对人的依赖性太强。
为了减轻编程者的操作量,人们开发了很多的工具来进行数组边界的检查,常见的有:
CanpaqC编译器,RichaniJones和Pau1Kelly珍开发的gcc补丁等。
5.4加强对返回地址的保护
返回地址在缓冲区溢出攻击中扮演了极其重要的角色,攻击者需要借助对它的修改来使程序转向选定的库函数或者向着预先植入的恶意代码方向去执行。
通过在系统的其他地方对正确的返回地址进行备份,在返回前对两者进行核对,可以成功地阻断攻击。
这种措施仅局限环境遏制通过修改返回地址来实现跳转的攻击方式。
5.5了解系统常见进程
这要求用户对系统的各种正常进程有个大体的了解。
用户通过了解系统中正在运行的进程,可以及时地发现可疑进程,及时终}卜其运行,从而降低遭受攻击的风险。
5.6及时打补丁或升级
经常关注网上公布的补丁和软件升级信息,这对那些经常上网的用户来说是一种简单有效的防范措施。
以上六种防范措施是口前最为常见的方法,但它们对人的依赖性太强,增加了相应的人员负担。
通过对缓冲区溢出攻击机制的研究,本文提出了第七种防范措施。
5.7从系统级和编译器两个方而来加强对内存空间的管理
该措施也是从加强边界检查的角度来防止缓冲区溢出攻击的发生,但又不同于5.3节,因为5.3节把边界检查的任务留给了编程者,受其他因素的影响太大,而这儿所说的措施是从系统和编译器两个方而来加强对边界的检查。
在系统级,所要做的改进是为系统中所有可能引起缓冲区溢出的函数增加用于进行溢出检查的代码,并且将其置于该函数的开始位置,以尽可能早地发现和防}卜溢出。
在编译器方而,当我们编译含有宇符串数组的程序时会发现编译器在程序开头预留出足够的空间后,接着就将这些空间进行初始化。
如下而的程序:
voidmain()
{
charbuf{8];
intnum=[512];
stcpy(buf“abcdefghijkl”);//此处产生溢出
mrcn[0]=1;
}
其汇编代码如下:
00401010pushebp
00401011movebpesp
00401013subesp848h
00401019pushebx
0040101Apushesi
0040101Bpushedi
0040101Cleaedi[ebp一848h]
00401022movecx212h
00401027moveax0CCCCCCCCh
0040102Crepstnsdwordptr[edi]
从这段汇编代码我们能够看出,虽然编译器为函数中的宇符串数组分配了空间,但并没有标志数组的末尾位置,所以根本无法正确测量宇符串数组的确切大小。
为了使前而在系统级所做的改进正常工作,我们应该修改现有编译器的初始化操作,使它在宇符串数组的末尾加上结束标志“b”。
这样,每当进行可能会引起溢出的操作时,总是先对源串和口的串的大小进行测量,然后将两者进行比较,如果源串的大小大于口的串的大小,那么就对源串进行截尾操作;或者直接报错,退出。
下面是对strcpy()函数所做的修改:
char*strcpy(char*strDestinationconstchar*strSource
{
intlenSourcelenDestinatior;
lenSource=strlen(strSource);
lenDestination=strlen(strDestination);
if(lenDestination<=lenSource)
//截尾或者报错退出
…..
}
上面是以堆栈为例进行说明,对于堆应对其相应的分配函数进行修改,使其在所分配空间最后加上结束标志“/0”。
该方案的优点在于:
所有的防范工作均由系统和编译器来完成,减轻了程序员的编程负担,与常见的防范措施相比它有更普遍的应用性,而且更为有效。
第六章结论
本文首先对缓冲区溢出攻击的原理、技术原因和攻击类型进行了探讨,然后给出了现在常见的几种防范措施,最后在对造成攻击的技术原因和现有防范措施研究
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 网络安全 课程设计 基于 缓冲区 溢出 漏洞 研究