2024年4月28日发(作者:)
由指针和数组带来的软件安全性缺陷
吕金和
(沈阳市电化教育馆,辽宁沈阳110032)
摘要:随着软件规模的不断扩大,软件系统深入到社会的各个领域,软件安全性测试的需求也日益扩张。软件的安全性问题
主要是由于语言和程序本身的缺陷带来的后遗症。指针和数组能够导致多种软件安全性缺陷,其中最有名的就是“缓存区的溢
出”。详细介绍了由指针和数组能够引发的一些安全性缺陷模型,并探讨了为这些缺陷设计测试方案所遇到的问题及解决方法。
关键词:软件测试;软件安全;指针
Brought about by the Pointer and an Array of Software Security Flaws
LV Jjn—he
{Shenyang Audio—ViSual Educag/on, ̄.e/'VICS,Shenyang,Liaonlng IIO05Z,
Abstract:With the continued expansion of software size,software systems deep into all areas of society,software,security,the ever-growing
demand for testing.Software security issues mainly due to deficiencies in language and the process itself had serious consequences.Pointers and
arrays can lead to a variety of software security flaws.ode of the most famous is the”buffer overflow.”This paper describes the pointer and
the array can be triggered by a number of security flaws model,and discusses the design of test scenarios for these shortcomings encountered
problems and solutions.
Key words:Testing;Software Security;Pointer
1软件测试与软件的安全性问题
1.1什么是软件测试
金融和银行领域。软件的安全性问题一方面由于语言本身
存在的缺陷,另一方面是由于程序员的忽视或经验不足。
软件测试就是发现软件中错误和缺陷的主要手段,在
软件工程的过程中占有相当重要的地位。测试的目标是以
最少的时间和人力系统找出软件中潜在的各种错误和缺陷。
如果成功地进行了测试,就能够发现软件中的错误。同时
能够证明软件的功能和性能与需求说明是否相符合。测试
软件的安全性缺陷中,由于指针和数组带来的软件安■
全性缺陷模式种类非常繁多。这跟数组和指针天生的非安一
全性有很大关系。后面的章节将深入讨论数组和指针带来
的安全性缺陷模式以及其对软件测试带来的一些挑战。
是为了证明程序有错,而不是证明程序无错误;一个好 2数组和指针
的测试用例是在于它能发现至今未发现的错误;一个成功 程序设计中,为了处理方便,把具有相同类型的若干
的测试是发现了至今未发现的错误的测试。
软件测试根据是否运行被测软件来分,可分为静态测
变量按有序的形式组织起来。这些按序排列的同类数据元
素的集合称为数组。在C语言中,数组属于构造数据类型。
试和动态测试。动态测试是指通过运行被测程序,检查运
行结果与预期结果的差异,来检查软件的动态行为和运行
静态测试是一种在不执行程序的情况下对程序行为进行分
一个数组可以分解为多个数组元素,这些数组元素可以是
基本数据类型或是构造类型。因此按数组元素的类型不同,
等各种类别。
结果的正确性,因此,动态测试只能发生在编码阶段以后。 数组又可分为数值数组、字符数组、指针数组、结构数组
析的理论和技术。 指针,是一个无符号整数(unsigned int),它是一
1.2软件的安全性问题
软件安全性缺陷是指有意或无意引入到系统的,可能
导致系统违背安全需求的不正确行为的程序和数据。
随着计算机在全世界的日益普及,计算机软件系统已
经深入到社会的各个领域,从视图桌面系统到手机嵌入式
系统,从个人笔记本电脑到超市结算终端。随着人们对软
个以当前系统寻址范围为取值范围的整数。32位系统下
寻址能力(地址空间)是4G—byte(0"2 32-1)二进制表
示长度为32bit(也就是4B)。具体来说,指针存的是另
一个对象的地址。
数组本身就是一个指针,指向数组的首地址。C/C++
程序中,指针和数组在不少地方可以相互替换着用。因此,
件功能的要求越来越高,软件的复杂性线性增长,软件的
安全性问题也越来越突出。特别是在安全性要求高的航空、
数组可以带来指针能够导致的一切问题。由于数组有长度
限制,还能带来其他一些问题。
指针和数组的灵活性在于它能让程序员方便地对内存
进行操作,当这种灵活性成为问题的所在,在一定程度上
就限制了C/C++的发展。JAVA虽然不提供malloc和
指针这些操作内存的机制,也不需要程序员自动释放申请
的资源,但是依然保留了数组类型,仍然会导致一些跟内
存有关的安全性缺陷的产生。内存错误是件麻烦的事情,
编译器不能够自动发现这些错误,而且错误的发生具有偶
然性,也许调试好的软件,到了客户的机器上就出现问题
了。这些问题出现的主要原因有内存分配未成功却使用了
它;内存分配虽然成功,但是尚未初始化就引用它;内存
分配成功并且已经初始化,但是操作越过了内存的边界。
内存分配成功并且已经初始化,操作也为超越内存的边界,
但是没有释放内存资源,造成了内存泄露。
3指针和数组带来的安全性缺陷模式
3.1指针的重复释放
对已经释放的内存资源进行再次释放称为指针的重复
释放。即对同一块内存地址两次调用free()函数。例如
在下面的例子中,函数release()中已经对资源进行了释放,
而main()中在release()后又对资源进行释放,从而
行成重复释放。
1 typedef struct X{
2 char}field;
3 }tx:
4 void release(tx a)f
5 b();
6 free(a->field);
7 free(a);
8 }
9 void main(){
1 0 tx}a=(tx*)malloc(sizeof(tx)){
1 1 if(a==NULL)return;
l2 a一>field=(char*)malloc(10);
13 release(a);
14 free(a->field);
15 free(a);
16 }
3.2内存泄露
内存泄露是内存资源申请后没有被释放。它可能导致
数据丢失。在大型或复杂的软件系统中,如果只申请内存
资源而没有将其释放,可能导致内存资源枯竭最终导致计
算机死机。例如在下面的例子中,P在程序结束前没有被
释放,导致了内存泄露。
1. #include<stdio.h>
2. #include<stdlib-l1>
3. #include<string.h>
4.
5. void
放在一块的,初始化的全局变量和静态变量在一块区域,
溢出。
未初始化的全局变量和未初始化的静态变量在相邻的另一
块区域。
一
例如下表:buf的大小为20,如果str+str2的长度大
于20,将导致栈缓冲区溢出。这给攻击者带来了入侵的
程序结束释放。
机会,它可以让攻击者重写内存中的数据。
1.#indude<stdio.h>
2.#indude<string.h>
3.#define MAXSIZE 20
4.另外还有一个专门放常量的地方。 一程序结束
释放。
在所有函数体外定义的是全局量,加了static修饰符
后不管在哪里都存放在全局区(静态区),在所有函数体
外定义的static变量表示在该文件中有效,不能extern
4.void test(char*str,char*str2){
5.
6.
7.
char pre[2】=”<”;
char buf[MAXSIZE】=””;
char post[2]=”>”;
到别的文件用,在函数体内定义的static表示只在该函数
体内有效。另外,函数中的“adgfdf”这样的字符串存放
在常量区。
用malloc,caUoc,realloc等分配内存的函数分配得
到的内存就是在堆上。程序员自己负责在何时用free或
delete释放内存。动态内存的生存期由程序员决定,使用
非常灵活,但问题也最多。
缓冲区溢出是一种非常普遍、非常危险的漏洞,在各
种操作系统、应用软件中广泛存在。利用缓冲区溢出攻
击,可以导致程序运行失败、系统当机、重新启动等后
果。更为严重的是,可以利用它执行非授权指令,甚至可
以取得系统特权,进而进行各种非法操作。缓冲区溢出攻
击有多种英文名称:buffer overflow,buffer overrun,
smash the stack,trash the stack,scribble the stack,
mangle the stack,memory leak,overrun screw;它
们指的都是同一种攻击手段。第一个缓冲区溢出攻击
一一
MOrris蠕虫,发生在二十年前,它曾造成了全世界
6000多台网络服务器瘫痪。
C/C++的一些标准库函数提供了往分配的内存空间
内存储数据的函数,如果控制不当,导致往里面写入数据
的长度大于分配空间的长度,将导致堆缓冲区溢出。例如
下表中,buf分配的空间大小为256,如果外界输入的参
数argv的长度大于256,将导致堆缓冲区溢出。这提供
了让外部攻击者将任何内容写入内存的机会。
1.#define BUFSIZE 256
2.int main(int argc,char }argv){
3.char,bur;
4.bur=(char幸)maⅡoc(BUFSIZE);
5.strcpy(buf,argv[1])}
6.}
3.5栈缓冲区溢出
在执行函数时,函数内局部变量的存储单元都可
以在栈上创建,如函数体内定义整型数组类型a:int
a[21={1,2)。函数执行结束时这些存储单元自动被释放。
栈内存分配运算内置于处理器的指令集中,效率很高,但
是分配的内存容量有限。C/C++/JAVA提供的一些对
数组进行操作的标准库函数的使用不当可能导致栈缓冲区
8. if(strlen(str)<MAXSIZE)
9. strcpy(buf,str);
10.printf(”strcpy:%s%s%s\n”,pre,buf,post);
l1. if(strlen(buf)+strlen(str2)<=MAXSIZE)//
theoretical integer overflow
l2. strcat(buf,str2);//CWE一121
13.printf(”results:%s%s%s\n”,pre,buf,post);
14.}
1 5.
16.nit main(int argc,char**argv){
17. char*userstr:
18. char*userstr2l
19. if(argc>2){
20. userstr=argv[1]t
21. userstr2=argv[2】;
22.test(userstr,userstr2)}
23. 1
24.prnitf(”donekn”)}
25. return 0I
26.}
4指针别名给软件测试带来的难题
由于数组名是指向数组首地址的指针,在后面的讨论
中将不区别其中的差别,统一使用指针这个名称。
当程序中有两个或两个以上的指针表达式指向同一块
内存空间时,则这些指针表达式关于该内存空间形成别名
关系。
别名关系能够增加软件测试复杂度,例如下面的例
子,由于在主程序中有语句b=c,如果缺少拷贝构造函
数base(base&a),则当程序执行析构函数时,对指针 p
就执行了两次释放操作,可能会造成死机。b和C就属于
指针别名,如果在测试的过程中不能记录这一层关系,就
没法获知最后使用free()函数释放的是同一块内存空间,
可能造成漏报。
class base
f public:
char p;
base()
发布者:admin,转转请注明出处:http://www.yc00.com/web/1714259670a2412161.html
评论列表(0条)