毕业设计(论文)-CC++程序安全漏洞知识库初探.docx_第1页
毕业设计(论文)-CC++程序安全漏洞知识库初探.docx_第2页
毕业设计(论文)-CC++程序安全漏洞知识库初探.docx_第3页
毕业设计(论文)-CC++程序安全漏洞知识库初探.docx_第4页
毕业设计(论文)-CC++程序安全漏洞知识库初探.docx_第5页
已阅读5页,还剩37页未读 继续免费阅读

下载本文档

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

文档简介

盐城师范学院毕业设计C/C+程序安全漏洞知识库初探学生姓名 学 院 信息工程学院 专 业 计算机科学与技术 班 级 12(2) 学 号 指导教师 2016年5月16日盐城师范学院毕业设计C/C+程序安全漏洞知识库初探摘 要全套设计加扣 3012250582计算机网络的飞速发展和软件被广泛地使用使得软件安全问题备受关注。各行各业都会使用不同的软件,无论是系统软件还是应用软件,没有软件是完美的。当攻击者或者病毒利用一些缺陷对软件或者系统进行攻击时, 可能会造成系统瘫痪,用户信息泄露等严重的危害。目前,C和C+语言使用广泛,在TIOBE 2016年4月 编程语言排行榜中C和C+分别位于第二和第三名。C和C+具有可移植性好,可直接访问物理地址,代码重用性高等优点,我们熟悉的操作系统Windows,Linux,数据库MySql都是基于C/C+开发设计的。在C/C+开发设计的程序存在一些安全漏洞,如缓冲区溢出,整型溢出,格式化字符串漏洞等,攻击者利用这些漏洞可以使程序中断,运行恶意代码或者获得系统的Root权限等。造成这些漏洞的根本原因可能是程序设计语言本身的缺陷,也有可能是开发者的疏忽。分析常见的漏洞,帮助程序员提升安全意识是一个很好的解决方法。本次设计的工作分为三个部分。一是构造程序漏洞及其机理分析框架: 现象威胁原因检测方法修复建议预防方法;二是基于漏洞分析框架,针对典型漏洞进行分析;三是基于漏洞分析,构造漏洞知识库系统。构造这个漏洞知识库系统可以帮助程序员更加全面深入了解常见的漏洞,掌握编程规范,同时也能提高他们的软件安全意识,提高软件的安全性。对于正在学习C/C+的同学们也有参考作用,可以帮助他们更加深入的了解C/C+语言,指导他们规范地开发较为安全的软件。【关键字】软件安全;C/C+;漏洞;机理分析框架;漏洞知识库Briefly discussion of C / C + application security vulnerabilities knowledge databaseAbstractWith the rapid development of computer network and the wide usage of software, software security becomes a major concern.Businesses use different software.There is no perfect software no matter system software or application software.When an attacker or a virus takes advantage of some bugs to attack the software ,it will lead to system failures,disclosure of user information, and other serious harm.Currently, C / C + programming language is widely used and popular .In TIOBE index for April 2016, C and C+ is second and third.C and C + have better portability, directly access to a physical address, code reuse, we are familiar with operating systems Windows, Linux, MySql database which is developed and designed based on C / C +.There are some security vulnerabilities, such as buffer overflows, integer overflows, format string vulnerabilities, and so an attacker can exploit these vulnerabilities make the program break,run malicious code or obtain system Root permissions.Defects in the programming language itself or developers negligence maybe cause these vulnerabilities.It is a good solution for programmers to promote the awareness of security awareness.The thesis is divided into three parts.First, structure vulnerability and buildvulnerability analysis framework: Phenomenon - Threat - Cause - Detection - Repair advice - Prevention methods.Second ,analyze typical vulnerabilities based on vulnerability analysis framework.Third, based on vulnerability analysis, build a vulnerability knowledge database system .Construction of this vulnerability knowledge database can help programmers better develop more secure software,and programmers can also make a very comprehensive understanding of common vulnerabilities, master the methods of prevention,and learn to develop a more standardized procedures.There is a useful reference for students who are learning C/C+ programming language and a deep understanding to guide them to develop more safety software.KeywordsSoftwaresecurity, C/C+, Vulnerabilities, Vulnerability analysis framework, Vulnerability knowledge database目 录1 引言11.1 研究背景及思路11.2 主要研究工作11.3 论文工作11.4 论文组织22 背景知识22.1 程序设计语言22.2 缺陷与漏洞32.3 漏洞检测与修复方法33 C/C+程序漏洞分析框架33.1 安全漏洞分析框架33.2 传统缓冲区溢出43.2.1 现象和威胁后果43.2.2 机理分析43.2.3 引起缓冲区溢出的原因53.2.4 检测工具63.2.5 预防建议73.3 整型溢出73.3.1 现象73.3.2 机理分析和造成原因73.3.3 预防建议113.4 不受控制的格式化字符串113.4.1 现象和威胁后果123.4.2 机理分析123.4.3 如何利用格式化字符串漏洞143.4.4 检测工具153.4.5 预防建议153.5 对数组索引验证不当163.5.1 现象和威胁后果163.5.2 代码示例163.5.3 预防建议163.6 错误计算缓存大小173.6.1 现象和威胁后果173.6.2 可能产生的原因173.6.3 预防建议193.7 使用了具有潜在危险的函数193.7.1 现象和威胁后果193.7.2 具有潜在危险的函数203.7.3 预防建议254 漏洞知识库系统的设计与实现254.1 需求分析254.2 开发环境介绍264.3 系统功能的设计264.4系统功能的实现274.4.1 登陆功能的实现274.4.2 注册功能的实现294.4.3 漏洞知识库展示功能的实现304.5运行与测试315 结论34参考文献36致谢371 引言1.1 研究背景及思路随着计算机网络的飞速发展,软件的广泛应用。软件安全问题备受瞩目。软件安全问题可能是由软件自身缺陷或者是网络问题引起的。软件在开发过程中存在的一些编程问题或者开发者的疏忽造成的安全隐患,极有可能被攻击者利用,可能造成进程中断、敏感信息暴露等后果。根据TIOBE 2016年4月编程语言排行榜, C和C+分别位于第二和第三名1,可见C和C+在软件开发设计中比较热门。C/C+是在软件开发设计中最常使用的编程语言之一。很多系统软件都是基于C/C+开发设计,如我们熟悉的操作系统Windows,Linux,数据库MySql等,还有一些开源软件。所以熟悉和了解C/C+程序安全还是有必要的。大多是软件安全事件都是与软件编程有一定的关联。软件中存在漏洞可能是开发者在开发过程的疏忽或者是编程语言的局限性造成的,结合CWE/SANS 2010 TOP 252提出的最具有威胁的漏洞,提取出与C/C+密切有关的也是开发人员在编码过程中容易疏忽的漏洞,针对这些漏洞给出相应的代码分析和机理研究,开发人员可以根据这些信息降低在开发过程中产生这些漏洞的可能,也可以为正在学习的编程的同学提供一些意见和建议使得他们编写的程序更具有安全性。1.2 主要研究工作本次研究工作是主要是为正在学习C/C+的学生或者程序开发人员解决以下问题:(1)可以列举出在软件中比较常见并且造成后果较为严重的漏洞。(2)能够查询程序漏洞的相关信息,如漏洞造成的原因、漏洞被触发造成的后果、修复方法等。(3)能够具有将漏洞的相关信息简单有条理的展示的功能,同时也兼具安全性。1.3 论文工作论文工作主要包括:(1)根据CWE/SANS 2010 TOP 25提取出与C/C+有密切联系的最具有威胁的漏洞,本文涉及的漏洞有:传统缓冲区溢出漏洞、整型溢出、不受控制的格式化字符串、对数组索引验证不当、错误计算内存大小、使用了具有潜在危险的函数。(2)构造程序漏洞及其机理分析框架:现象威胁原因检测方法修复建议预防办法。对涉及的漏洞按照这个框架进行分析。(3)基于漏洞分析,设计一个单机版基于C#的WinForm应用程序-漏洞知识库系统。该系统具有登陆和注册功能,同时系统将每个漏洞的分析结果进行汇总,展示功能是将分析结果简单明了的进行展示。1.4 论文组织第一章,引言。简单描述了研究背景和研究思路,同时也介绍了本次毕业设计的研究工作和主要工作。第二章,背景知识。简单描述了C和C+的发展过程以及其优缺点以及对一些名词的解释,如“漏洞”、“缺陷”等与本次设计相关的背景知识。第三章,C/C+程序漏洞分析框架。提出了漏洞的分析框架,并且按照该框架详细介绍了各个漏洞的现象,威胁后果等方面内容。第四章,漏洞知识库系统的设计与实现。主要讲述了系统的设计,需要包括登陆、注册功能和展示功能。同时也介绍了相关的测试内容。第五章,结论。总体描述了本次工作的内容以及对未来可以考虑继续做得内容。2 背景知识2.1 程序设计语言程序设计语言是用于书写计算机程序语言的,C和C+是目前最受欢迎的程序设计语言之一。C语言在1972年由贝尔实验室(Bell Laboratories)的D.M.Ritchiez在B语言的基础上开发设计的。现在应用广泛同时也是每个计算机工程师的必修课。美国国家标准化协会制定了现有的C语言标准。C语言有可移植性好,语言简洁,可直接访问物理地址等特性,同时它也具有对语法限制不严格,对变量的类型约束不严格,缺少对数据边界检查等缺点。C+语言是以C语言为基础贝尔实验室设计并实现的一个面向对象的程序设计语言,很多应用程序都是基于C+语言开发和实现的。C+语言继承了C语言的特定,它还具有其他的优点如:代码重用性高,性能优良,优异的错误处理机制等,但是由于C+语言本身比较复杂开发实现的应用程序中的错误难以发现,安全性无法保障3。2.2 缺陷与漏洞软件存在问题我们会说该软件有软件缺陷,也是我们常说的软件有“Bug”。软件缺陷,即计算机系统或者在程序中存在任何导致其无法正常运行的问题、错误,或者隐藏的功能缺陷、瑕疵。缺陷会导致软件产品在某种程度上不能满足用户的需求。IEEE729-1983对缺陷有一个标准的定义:从产品内部看,缺陷是软件产品开发维护中存在的错误、毛病等各种问题;从产品外部看,缺陷是系统所需要实现的某种功能的失效或违背。软件缺陷就是软件产品中所存在的问题,最终表现为用户所需要的功能没有完全实现,用户需求没有得到满足4。漏洞就是存在于自动化系统安全过程、管理控制和内部控制等过程中的弱点,利用这些弱点可以获取对信息的非授权访问或者终止关键的进程5。在C/C+开发设计的程序存在一些安全漏洞,如缓冲区溢出,整型溢出,格式化字符串漏洞等,攻击者利用这些漏洞可以使程序中断,运行恶意代码或者获得系统的Root权限等。造成这些漏洞的根本原因可能是程序设计语言本身的缺陷,也有可能是开发者的疏忽。2.3 漏洞检测与修复方法漏洞检测就是对重要的计算机系统或者软件进行检查,发现其中可以被黑客利用的漏洞6。检测方法可以分为静态检测和动态检测。目前,有很可供选择的软件检测工具,如与C/C+有关的检测工具有Splint7、Its48和Flawfinder9。利用检测工具可以帮助程序员在开过程中发现可能错在的漏洞。修复方法就是将存在安全缺陷的代码修改成正确的,规范的以此来降低或者避免被攻击者利用的可能的建议或方法。将漏洞进行修复是成本最低的措施,例如我们用的Windows操作系统,微软公司会不定期地提供补丁供用户下载安装以此来修复系统中的存在的漏洞。3 C/C+程序漏洞分析框架3.1 安全漏洞分析框架不同漏洞被触发时会产生不同的表现或者现象,根据漏洞类型的不同,收集不同的现象信息;当漏洞被攻击者利用时,由于被利用的方式的不同造成的后果和威胁也会有所不同;针对不同类型的漏洞或者同一个漏洞不同的触发方法进行机理分析,深入分析产生漏洞的原因;接着提出检测方法,每种漏洞都有相应的检测方法和检测工具,利用这些检测工具发现在开发软件过程存在的漏洞,给出可供参考的正确的修复方法或者修复建议;最后根据造成漏洞的原因提出一些有效的预防方法。框架图如图3-1所示:图3-1漏洞分析框架图3.2 传统缓冲区溢出3.2.1 现象和威胁后果当一个程序试图在一个缓冲区中存放超过它的最大容量或者是存放在内存中的数据的超出了该缓冲区的边界就会产生缓冲区溢出的情况。在缓冲区溢出问题中,最简单同时也是最普遍的就是传统缓冲区溢出。许多问题都被叫做BufferOverflow 实际上与 Classic Buffer Overflow (传统缓存溢出)不一样,包括依赖于溢出攻击技术的不同类型缺陷,例如整型符号性错误,整型溢出和格式化字符串输出漏洞,也是与传统缓冲区溢出不同的。本章节描述的缓冲区溢出是指传统缓冲区溢出。造成传统缓存区溢出原因就是没有对输入数据大小进行验证的7。在尝试将数据存放到缓冲区时缺少对数据大小的验证,导致存放的数据大小大于缓冲区能容纳的最大数量,导致缓冲区溢出。利用缓存区溢出实施攻击,可以导致程序退出,系统重新启动或者当机,也可能利用它会执行未经授权的代码或命令,进行一些非法操作等。3.2.2 机理分析结合代码段一的例子对缓冲区溢出的基本原理进行讲解。1) /代码段一2) void function( int a,int b )3) char buf15;4) char buf215;5) 6) void main()7) function(1,2);8) 调用function()时,栈中数据分布情况如图3-2所示:图3-2栈内数据存储结构从图3-2可以看出,当输入的buf1过长,就会发生缓冲区溢出,会直接覆盖下面的数据(EBP,RET,等),如果攻击者精心设计一个恶意代码,利用缓冲区溢出漏洞,改写RET(即修改function()的返回地址),就可以跳转到任意攻击者想要跳转的地方。除此之外也可以修改局部变量(即图3-2中的function()的参数)。当试图直接存储大于缓冲区最大容量的数据时就会发生这种传统型缓冲区溢出,下面将会介绍一些可能会引起的这种问题的编码。3.2.3 引起缓冲区溢出的原因(1)缺少边界检查程序编译时在堆栈上分配了固定大小的缓存区,并且在对缓存区进行访问时没有提供边界检查 。对输入的数据没有进行验证,直接复制到分配的内存区中,然而输入数据的大小超过了内存区的存储范围,导致靠近内存区的数据被覆盖,使得程序崩溃,甚至导致执行恶意代码,如代码段二所示:1) /代码段二2) char s10;3) printf(input some words:n);4) scanf(%s,s);上述的代码里,向长度为10的数组里输入字符,由于没有约束或者限制用户输入字符的大小,用户可以随意输入字符。如果用户输入“abcdefghijklmn”,一共有14个字符,大于指定的长度10,那么就会产生溢出。正确的修改:“scanf(“%10s,s”);”。指定最多只能输入10个字符,这样就不会发生缓冲区溢出的问题。(2)使用了没有边界检测的函数程序调用了没有进行边界检查的函数来访问(写操作)缓存区,这些函数没有对访问的缓存区的大小进行判断,如strcpy(),strcat(),gets(),等。代码段三展示的就是一个使用了strcpy()可能产生传统缓冲区溢出的代码:1) /代码段三2) void copy(char *p)3) char buf16;4) strcpy(buf,p);5) printf(buf=%s,buf);6) copy()的功能就是将字符串p中数据复制到变量buf中,最后输出buf中的数据。值得注意的地方是,strcpy()只具有复制数据的功能缺少边界检查功能,如果字符串p的长度大于16,就会产生缓冲区溢出,造成程序中断,同时极有可能被攻击者利用这个缺陷执行恶意代码。这里可以使用strncpy()函数以避免这个问题。将代码改写成strncpy(buf,p,16),指定了最大复制的数量16,这样在复制数据的过程中就不会发生溢出问题。3.2.4 检测工具检测工具有Splint、ITS4和Flawfinder。Splint是Secure Programming Lint 的全称,它是静态检查C程序安全漏洞和编码错误的编程工具。它能够解释源代码中的一些特殊注释,与只检查源代码的工具相比,它的检查能力更强。ITS4的全称是Its the Software Stupid!(Security Scanner)是一个静态源代码分析工具,它可以寻找潜在的缓冲区溢出漏洞,它的工作原理就是查找出具有潜在危险的操作,如strcpy()。当找到它时,ITS4会进一步分析来,决定这个操作有多么危险,是否应该被报告为可能的漏洞。Flawfinder是由Dave Wheeler 使用Python脚本语言编写的,它是一种检查源代码并且通过危险等级报告可能的安全漏洞(“缺陷”)的程序。3.2.5 预防建议(1)在编写程序时,要重复检查你已分配的缓存区大小是否与你指定字符串的大小一致,当在一个循环中访问缓存时,需要检查缓存区的边界,确保你越界操作的风险。(2)如果有必要的话,可以把输入的字符串分截成多段合理的长度之后,再传给复制或者链接函数。(3)用类似的支持长度参数的函数去代替无边界检查的函数,如用strncpy替代strcpy(),但是这钟方法还是容易出现错误计算缓存长度的问题。(4)使用一个静态代码分析工具去排除软件中可能存在的一些漏洞。3.3 整型溢出当整数值递增到一个过大的值,保存到一个变量里时,可能发生整型溢出或者回绕,当发生这种情形时,只可能变成一个非常小的数或者负数,如果再将这个结果用来控制循环,做一个安全决定或者用来确定偏移或者大小,例如内存的分配,复制等,将会很危险。3.3.1 现象在相同的环境下,每种类型的整数都有其固定的长度,所以它能表示数的范围也是固定的(即最大值和最小值是固定的),当试图保存一个大于它最大值的一个数时,就会发生整数溢出。(小于最小值时,会发生整数下溢),整数溢出很难发现,根据ISO C99得知,整型溢出是未定义行为(undefined behavior),因此编译器会忽略这个溢出。虽然很多整数溢出没有直接改写内存,但是有时也会引起其他类型的漏洞,如缓存区溢出。当整数溢出发生时,一个意想不到的结果被存储在内存中,如果该结果被用来计算缓存区大小,控制循环次数,表示数组的下标,作为数组的边界,作为内存分配函数的实参,在任何指针运算中或者存在安全关键的代码中,这将会很危险。3.3.2 机理分析和造成原因每种类型的整数都有其固定长度,例如int在本实验环境中int 占4个字节,能表示整数的范围是-21474836482147483647(即-231231-1)。有符号数在计算机内是以二进制补码的形式存储的,所以int表示的数的范围在计算机内存储形式如下所示:02147483647 表示为00000000 00000000 00000000 0000000001111111 11111111 11111111 11111111-2147483647-1表示为11111111 11111111 11111111 1111111110000000 00000000 00000000 00000001-2147483648表示为10000000 00000000 00000000 00000000当n表示的是int类型的最大值2147483647时,对n进行加1操作,超出它表示数的范围,就会发生整数溢出,输入n 的结果为-2147483647。因为2147483647在计算机中存储的形式为01111111 11111111 11111111 11111111,我们进行加1操作时,结果为10000000 00000000 00000000 00000000,表示的数为-2147483648,整数溢出就这样发生了。同样的道理,当n表示的int类型最小值,对n进行减1运算时,运算结果将会变成int类型的最大值。对于unsigned int 能表示的数的范围是04294967295(即0232-1)。根据C99第6.2.5节:涉及无符号操作数的计算不会溢出,因为无法由最终的无符号整数类型表示的结果将会根据这种最终类型可以表示的最大值加1执行求模操作。这指定了当无符号整数发生“溢出”时的正确操作。也可以称之为无符号数的回绕。当n表示的是unsigned int 类型的最小数0,对n进行减1操作,结果存储在内存中的形式为11111111 11111111 11111111 11111111,以无符号数形式输出最高位就是普通位,最终输出的结果为4294967295;当n表示的是unsigned int 类型的最大数4294967295,对n进行加1运算,根据C99中的规定我们可以算出最终结果为4294967296%(4294967295+1)=0; 运行Integer_Overflow01.c文件,运行结果如图3-3所示:1) /Integer_Overflow01.c2) #include3) #define INT_MAX 21474836474) #define INT_MIN -21474836485) #define UINT_MAX 42949672956) #define UINT_MIN 07) void main()8) int i,j;9) unsigned int k,l;10) i=INT_MAX;11) i+;12) printf(“i=%dn”,i);13) j= INT_MIN;14) j-;15) printf(“j=%dn”,j);16) k=UINT_MAX;17) k+;18) printf(“k=%dn”,k);19) l=UINT_MIN;20) l-;21) printf(“l=%dn”,l);22) 图3-3 运行结果整数溢出漏洞不易被发现,所以就需要程序员在编写代码的过程中充分考虑到这一点,需要对数据进行严格的边界检查,正确地对数据进行定义声明等操作。造成整数溢出有很多原因,下面将介绍几种常见的原因。(1)整数缺陷通常情况下我们都会考虑到输入的数值是否会造成整数溢出,可有时会忽略在代码运行过程中涉及的整数运算同样极有可能造成整数溢出漏洞。代码段四正是在运算过程中发生了整数溢出:1) /代码段四2) n=get_input();3) if(n0) 4) response=malloc(n*sizeof(char*);5) for(i=0;i0&n1073741824)”。这样在进行下面的乘法运算时,结果不会超出溢出,后续的程序也能的正确运行。同样其他的运算,如加、减、除等也会造成整数溢出漏洞。请及时添加必要的整数范围检查。(2)截断错误有符号数与无符号数之间表示的数的范围不同,原因是无符号数的最高位是普通位而不是符号位。当尝试把有符号数尤其是负数转化为无符号数时就会发生意想不到的错误。Integer_Overflow02.c中的代码可能会发生这样的符号错误。1) /Integer_Overflow02.c2) #include3) #include4) #include5) #define SIZE 206) void main()7) int len;8) char buffSIZE;9) char src100;10) fgets(src,20,stdin);11) len=atoi(src); /atoi()将字符串中的数字转换成整数12) printf(“len=%dn,len”);13) if(len0&lenSIZE)”。(3)符号错误当一个较小的存储区存放能表示一个很大数的变量,最终结果只能容纳小变量能够存放的位数,而其他位被截断。有一点值得注意是不同宽度整数类型之间的的转换,当两个大小不同类型的的操作数进行计算时(如int 与 short),通常是将较小的操作数转化成较大的操作数(即将short转化成int)。如果较小变量用来存放这个结果时,这个结果将会被截断导致数据丢失。代码段五展示了可能发生整数截断错误的代码:1) /代码段五2) short s;3) int i;4) s=i;这里i和s是不同类型,要将i的值赋给变量s,变量s被提升为32位的整型,然后整数i的数据被赋值给提升后的s,提升后的变量为了能存放在s里面被降回16位,如果存储的结果大于变量s能存储的最大值那么降位将导致结果截断。代码段六同样存在这样的问题:1) /代码段六2) void function(char*s, char *p)3) unsigned short int t;4) t=strlen(s)+strlen(p)+1;5) char *buf=(char*)malloc(t);6) strcpy(buf,s);7) strcat(buf,p);8) printf(buf=%sn,buf);9) function()接受两个字符型参数。根据两个字符串的长度动态分配内存空间,将这两个字符串连接起来。值得注意的一点是,在上述代码里,strlen()返回的类型是size_t,通常是unsigned int,能表示的数的范围04294967295(即0232 -1),然而t是一个unsigned short int,在本实验环境中是16位,它能表示的范围只有065535(即0216-1)。如果当两个字符串的总长度值大于变量t能表示的范围,这将导致结果被截断。例如当两个字符串的总长度是65536,那么总和再加1就是65537,要将这个值存放到t中,要进行的计算就是65537%65536=1。之后调用malloc()时只能动态分配1个字节的空间大小,接着调用strcpy()和strcat()时会造成缓冲区溢出的问题。3.3.3 预防建议整数漏洞产生的原因就是缺少整数范围验证,针对上述章节中介绍的一些可能会引起整数溢出漏洞的问题,提出了下面的几条预防建议:(1)对非信任来源的数据进行上下边界范围检查。(2)使用安全的整数库(例如IntergerLib)。例如在涉及非信任来源的数据进行乘法运算时,我们就可以使用库中的相应的工具函数来避免整数溢出。(3)根据实际需求确定变量合适的定义类型。对于某些数值不能为负的变量,可以定义为无符号型,同时也需要对其进行范围检查。3.4 不受控制的格式化字符串格式字符串是由普通字符和转换规范构成的字符序列。普通字符被原封不地复制到输出流中,转换规范根据与实参对应的转换指示符对其进行转换,然后将结果写入到输出流中。主要格式化函数有printf还有sprintf,fprintf等c库中print家族的函数。例如:printf函数,它的一般形式为:printf(format, 输出表列)。format的结构:%标志输出最小宽度.精确度长度修饰符。这些格式化函数可以接受可变数量的参数。3.4.1 现象和威胁后果当格式化函数中实参数量与转换指示符数量不一致时很有可能会产生格式化字符串漏洞。例如 printf(str)。当发生格式化字符串漏洞时,可能造成如下的威胁后果:(1)使程序崩溃。(2)可能被偷看内存内容。 (3)可能造成缓存区溢出。(4)攻击者可以利用”%n”参数直接修改返回地址。3.4.2 机理分析图3-4展示的是栈与格式化字符串简单关系示意图:图3-4栈与格式化字符串简单关系示意图接下来将结合图3-5中的一段代码进行讲解栈与格式化字符串之间的关系,格式化输出函数是如何输出变量的。图3-5格式化输入从代码中可以清楚的看出,转换指示符的数量多于实参数量,多三个%x,在栈中存储情况如图3-8所示图3-6调用print()栈中存储分布图结合图3-7和图3-8可以看出没有字符串参数也能输出内容,当我们能控制输入format时,我们就可以输出内存中我们需要的地址上的数据,或者使用一些特殊的字符转换符对内存中指定地址中的数据修改,例如当攻击者能控制format时,利用%x和%n可以读取内存中的数据或者修改函数的返回地址等。3.4.3节将讨论一些利用格式化字符串漏洞的方法。3.4.3 如何利用格式化字符串漏洞(1)利用%s当运行这样的代码时 printf(“%s%s%s%s%s%s”)可以使得程序崩溃。在需要打印参数指定地址内存时,可以使用%s,但是上述代码中缺少字符串参数,所以printf()函数可能读取到一个没有映射的地址或者是一个无效指针导致程序崩溃 (2)偷看内存内容利用%x可以查看以十六进制显示的栈内存储的信息。当运行Format_01.c时,结果如3-7所示:1) /Format_01.c2) #inclde3) void function(int a,int b,int c)4) printf(“The stack is:%d,%d,%d,%x,%x,%xn”,a,b,c);5) 6) void main()7) function(1,2,3);8) 运行结果:图3-7利用%x运行结果图function函数中,在调用printf函数时,格式化字符参数要求后面有6个参数,以十进制和十六进制的形式输出,但是printf函数调用却只提供了3个需要打印的参数,图3-7中可以看到输出结果:将第三个参数打印出来后,printf()又从栈上参数3之后的地址取得3个字的内容以十六进制的形式打印出,格式化输出将以这种形式持续显示内存中的其他内容,直到在格式字符串中遇到一个空字节。“%x,%x,%x”可以连续显示内存中的数据。攻击者可以利用%x查看栈内大部分数据的同时也可以确定程序的偏移量,再配合%n对函数的返回地址进行修改就可以跳转到任意攻击者想要跳转的位置。(3)修改返回地址使用%n达到修改返回的目的。在格式化字符串函数中,%n的作用是把已经写入缓冲区的字符个数保存到参数指定的地址中。如代码段七所示:1) /代码段七2) int i ;3) printf(“hello world!%nn”,&i);4) printf(“i=%dn”,i);这段代码输出的结果为i=12,就是“hello world!”的长度。也能通过使用具体的宽度或精度的转换规范来控制写入的字符个数达到同样的效果。例如代码段八:1) /代码段八2) int a;3) printf(“%5u%n”,1,&a); / a=54) printf(“%50u%n”,1,&a); /a=50可以使用与查看指定地址的内存相同的技术来指定地址。在下面的调用中:printf(“x40xf4x42x01%.08x%.08x%n”),就将表示将输出字符个数的整数写入地址0x0142f440中,在本例中,写入的值是20(8*2+4=20),这里可以用某些shellcode的地址来覆写地址(例如栈上的返回地址)。(4)缓冲区溢出使用sprintf()可以向字符数组中写入数据,但是它会假设存在任意长度的缓冲区,从而导致它们容易产生缓冲区溢出问题。1) /代码段九2) char buf1512;3) char buf2512;4) sprintf(buf1,”err wrong command:%400s”,user_input);5) sprintf(buf2,buf1);结合代码段九,当user_input的值是“%500dhello”,在调用第一个sprintf(),因为有%400s的限制,所以它能正常运行,但是执行到第二个sprintf()时,%500d指示sprintf()向buf2中写入500个字符,再加上其他普通字符,最终写入buf2中的字符数大于512,发生了缓冲区溢出。如果攻击者精心构造了user_input,就可以将函数的返回地址改写成指向shellcode的地址,以此达到某种目的,破坏程序或者获得程序的控制权等。观察上面的例子能够很容易发现这样的问题,可是在实际项目中,并不是那么明显。3.4.4 检测工具可以选择的FlawFinder检测工具。Flawfinder是一种静态代码检查工具,可以立即发现代码中潜在编码漏洞。在使用Flawfinder时需要关注它所存在的缺陷,如对数据类型不敏感,只执行句法,不执行上下文分析。3.4.5 预防建议(1)养成良好的编程习惯,格式化字符串中的转换符与参数之间数量要匹配,使用正确。(2)限制字节的写入。(3)根据实际需求使用一些防范工具如LibSafe,FormatGuard等。3.5 对数组索引验证不当3.5.1 现象和威胁后果程序接受了一个不受信任的输入数据,当在计算或者使用一个索引时,程序没有对其进行验证或者验证错误,这就难以确保这个索引的的值是在数组范围之内的。这样就可能导致越界的问题。可能会引起这样的后果:(1)如果使用了一个越界的索引将会导致相关的内或者指令存损坏或者导致程序崩溃。(2)如果内存损坏的部分是数据,而不是指令,系统将会使用这个错误的数据继续运行。(3)使用了一个越界的索引也能够触发一个越界读或者写操作,或者在错误的对象进行操作等,不仅会发生缓冲区溢出,也可能暴露或者修改敏感信息,若利用缓冲区溢出漏洞,攻击者可以获取控制权,可以执行恶意代码。3.5.2 代码示例1) /代码段十2) int getValue(int index,int len,int *arr)3) int value;4) if(index=0&indexlen)”。3.5.3 预防建议(1)对输入作为索引的数据要进行及时的正确的范围验证。(2)对缓冲区的边界值的验证可以添加必要的注释,及时提醒自己或者团队其他成员关注对索引数据的验证操作是否正确。3.6 错误计算缓存大小3.6.1 现象和威胁后果当程序运行过程中算错将要分配的缓存空间大小,这将会导致后续的操作无法正确运如无法动态分配正确大小的内存空间。可能造成缓存区溢出,也可能导致越界的读写操作,进而引起系统的崩溃,或者允许恶意代码执行,暴露敏感数据等。3.6.2 可能产生的原因造成错误计算缓存大小的原因有很多,可能是程序员错误估计变量需要的合适的内存空间,可能是在编程过程中的失误,也有可能是因为对C库中的某些函数理解错误。(1)off-by-one错误一个字符数组在不正确的循环条件下读取,该错误就会变现出来:1) /代码段十一2) #define SIZE 303) int arrySIZE;4) for(i=0;i

温馨提示

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

评论

0/150

提交评论