32
基于源代码的软件安全性测试研究
刘仁千, 张玉中,张超永
(国家电网许继集团软件测试室,河南 许昌 461000)
摘 要:随着软件产品的广泛应用和其规模、复杂度的不断提高,软件中的安全漏洞也不断增多,由此所引起的软件安全性问题也日益突出。源代码安全是软件安全的基础,所以源代码的安全性测试成了保证软件安全最强有力的措施之一。明确了源代码安全性测试的主要内容和基本概念,论述了基于源代码的软件安全性测试方法和测试工具,并对测试方法和测试工具的选用提出自己的见解。
关键词:软件测试,源代码安全 ;源代码测试方法 ;源代码测试工具
Research on Software Security Testing based on Source Code
LIU Ren-qian, ZHANG Yu-zhong, ZHANG Chao-yong
( Software Testing Room of State Grid XJ Group , Xuchang, Henan 461000,China)
Abstract :Software application has become wider and the size and complexity has been ever increasing. Secur- ity flaws and vulnerabilities in the software are growing. Software security problems have become increasingly pr- ominent. Source code security is the foundation of software security, so the security testing of the source code bec- ome one of the most powerful measures to ensure the safety of software. The main content of the source code sec- urity testing and basic concepts is designated. The software security testing methods and testing tool based on the source code are discussed. The view about the selection of testing methods and tools is proposed.Key words :software testing;  source code security; source code testing method ; source code testing tools
0 引言
软件安全性[1]是衡量软件整体质量的一项重要指标,特别是近年来由于软件原因导致的安全事故频发,更使软件安全的重要性上升到前所未有的高度。
软件安全主要包括以下几个方面:数据库安全,随着数据库在系统软件开发中的比重越来越高,数据的安全成为了软件系统中的重中之重。网络安全,随着网络技术的快速发展,网络安全问题更不容忽视,如何保证软件产品之间的安全通信是网络安全的一项重要内容;应用安全,随着软件产品的应用范围越来越广,特别是军工、医疗、电力等对安全性要求极高的领域,软件的安全应用更是不容忽视;主机安
全,软件所运行环境的安全是保障软件产品安全运行的有力保障,所以主机安全,即:软件的运行环境的安全很重要;源代码安全,源代码是软件产品的主要组成
部分,更是基础部分,所以软件安全主要是源代码安全;本次研究的重点也是源代码安全。
源代码安全性测试方法主要是静态分析和动态测试两种,相应的测试工具也是静态扫描和动态分析两大类。
1 源代码安全
源代码安全是指代码中安全漏洞少,代码质量高。源代码中安全漏洞主要有:缓存区溢出、非法指针、整数溢出、内存泄露等,以下具体介绍这几类问题。
1.1 缓存区溢出
缓冲区溢出是一种非常普遍、非常危险的漏洞,在各种操作系统、应用软件中广泛存在。利用缓冲区溢出攻击,可以导致程序运行失败、系统宕机、重新启动等后果。更为严重的是,可以利用它执行非授权
33指令,甚至可以取得系统特权,进而进行各种非法操
作。以下是几种常见缓存区漏洞情况[3]:
(1)C中不进行自变量检查的、有问题的字符串
操作。标准 C 库中有很多不进行自变量检查的、有
问题的字符串操作函数。如,strcpy()函数将源字符
串复制到缓冲区。没有指定要复制字符的具体数目,
如果源字符串的数目大于缓存区的空间,由于没有专
门限制其大小,则有可能引起缓冲区溢出。sprintf(),
vsprintf(),strcat()函数非常类似于 strcpy(),都很
容易对程序造成缓冲区溢出。在使用这类函数时一定
要对操作字符串的数目做限制。
(2)C++语言中,很多操作字符串的库函数,允
许直接读入外界输入后对变量赋值,如果这些未经检
验的输入超出系统允许范围,将造成缓冲区溢出。同
时,一些系统内部分配内存的函数,也会造成同样的
问题。
1.2 非法指针
有人说,在C++中指针是天使更是魔鬼,这说
明指针给我们带来方便的同时,如果使用不当更会给
我们带来麻烦甚至是灾难。使用指针很容易出错,并
且一旦出错还很难查,因为指针出错时一般不会在
程序中马上体现,有的过了很久,程序才会出现错误,
出错的地方通常也不是代码出错的地方,更有甚者是
程序偶尔出现一次b u g,很难重现缺陷,这样的缺陷
让测试人员和开发人员都很头痛。以下是几类常见的
非法指针情况[5]:
(1)使用未初始化的指针,而且这种错误常常难
以检测。其结果常常是修改一个不相关的值。
(2)使用N U L L指针,它可以赋值给一个指针,
用于表示那个指针并不指向任何值。对N U L L指针执
行间接访问操作的后果因编译器而异,两个常见的后
果分别是返回内存位置零的值以及终止程序。总之操
作一个指针前最好让它指向一个实际的地址。
(3)指针运算只有作用于数组中其结果才是可以
预测的。对任何并非指向数组元素的指针执行算术运
算是非法的(但常常很难被检测到),这样很容易造
成越界。
(4)越界操作指针,如,一个指针减去一个整数
后,运算结果产生的指针所指向的位置在数组第一个
元素之前。
如果指针指向数组最后一个元素后面的那个内存
位置仍是合法(但不能对这个指针指向间接访问操
作),再往后就不合法了。
(5)不要返回指向栈内存的指针或引用,因为栈
内存在函数结束时会被释放。
1.3 整数溢出
整数溢出是缓冲区溢出的一种,一个整数是一个
固定的长度,它能存储的最大值也是固定,当试图去
存储一个大于这个固定的最大值时,将会导致一个整
数溢出。整数溢出类型的b u g很难用工具发现,因为
测试工具无法判断计算的结果是否为正确结果。
没有对Integer overflow进行说明可能会导致逻辑
错误或buffer overflow。程序没有对以下事实进行说
明时,会产生Integer overflow错误:算术运算会导致
数值大于数据类型的最大值或者小于数据类型的最小
值。用户输入在与带符号的值和不带符号的值之间的
隐式转换进行交互时会产生一些错误,而这些错误经
常会导致内存分配函数出现问题。如果攻击者能够使
程序分配的内存不足或是在进行内存操作时,将一个
带符号的值作为不带符号的值来解析,将会使程序很
容易出现 buffer overflow。
例 1:以下是一个经典的 integer overflow 案例:
nresp = packet_get_int();
if (nresp > 0) {
response = xmalloc(nresp*sizeof(char*));
for (i = 0; i < nresp; i++)
response[i] = packet_get_string(NULL);
}
34
如果nresp 已赋值1073741824,并且sizeof(char*)也有了它的值4,那么操作nresp*sizeof(char*)的结果将会出现溢出,而且xmalloc() 的参数将变为0。大多数 malloc()接口都会乐于分配一个0 字节的缓存,因此会造成无限循环而致使溢出堆缓存 response。
1.4 内存泄露
一般我们常说的内存泄漏是指堆内存(在c 中,指堆;在c ++中,指堆和自由存储区)的泄漏。堆内存是指程序从堆中分配的,大小任意的(内存块的大小可以在程序运行期决定),使用完后必须显示释放的内存。应用程序一般使用malloc,realloc,new 等函数从堆中分配到一块内存,使用完后,程序必须负责相应的调用free 或delete 释放该内存块,否则,这块内存就不能被再次使用,我们就说这块内存泄漏了。
内存泄露的形式分四种:常发性内存泄露,偶发性内存泄露,一次性内存泄露和隐式内存泄露,其中常发性和隐式内存泄露的危害性最大,可直接导致系统崩溃等致命性的错误。
1.5 其他安全性问题
对软件构成威胁的代码问题还很多,以上只是几种严重的问题。还有一些如
:未初始化变量,数组越界,S Q L 注入,格式化字符串,不安全的函数,死代码等漏洞在一定程度上也对软件安全构成威胁。
2 源代码安全性测试方法
2.1 静态分析源代码
静态分析是人工走读代码或用工具扫描源程序然后再进行人工分析,从中出可能导致错误的结构异常、控制流异常及数据流异常。静态分析较动态而言更容易实现,不依赖于特定的运行环境。目前静态安全性分析方法可分为[5~6]模型检验、词法分析、语义分析等。静态分析由于操作过程比较固定,很容易实现自动化,所以静态分析的工具比较多,有商用的,
有开源的。可以根据实际项目需要选择合适的工具。对软件安全性构成重大威胁的缓存区溢出问题和部分非法指针大多都是通过静态分析发现的。
图1 源代码静态分析流程
很多时候工具分析的结果不能直接作为测试结果,因为工具都存在误报或重报问题,必须对工具分析的结果进行人工分析确认、最终形成测试报告。动态测试也是如此,不再赘述。
2.2 动态测试源代码怎么写代码做软件
动态测试,顾名思义就是把测试对象运行起来进行分析,这样能更直观地发现问题,当然与静态分析比较需要测试人员投入更多的精力,首先要搭建测试环境对软件产品所运行的实际场景进行仿真、模拟;然后需要设计恰当的测试用例,这就对测试人员有较高的技术和经验要求,对测试的软件产品一定要熟悉,对该类软件的缺陷可能分布情况要有一定的把握,这样才能设计出既全面又典型的好用例。最后要对测试数据的采集和分析,这一步任务量大又繁琐,一般是借助动态分析工具完成的。大多内存泄露问题和部分非法指针是通过动态分析发现的。
图2 源代码动态分析流程
2.3 静态和动态相结合测试源代码
对于源代码的测试来说,在很多情况下,静态测试和动态测试都不是分开来做的。静态分析指导动态测试是一种很有效的测试方法,如通过静态分析源代码可以到哪些函数的调用频率高,哪些模块的复杂度大,动态测试时我们就可以有针对性地设计用例。
35另外,静态分析发现漏洞有时也可以在动态测试中验
证,这样问题更直观,更有说服力。而在动态测试时
发现的漏洞又需要通过对代码分析加以确认,这就又
回到了静态分析上,总之静态分析是源代码测试的基
础,动态分析是代码测试的有效手段,两者相辅相成。
3 源代码安全工具的分析选择
随着软件测试自动化技术的不断发展,自动化
测试工具也越来越多,有商业的,开源的,琳琅满
目,种类繁多[2]。针对源代码的测试工具,静态的
有:Fortify Software公司的Fortify SCA,IBM公司
的Logiscope,Parasoft公司的C++test等;动态的
有:IBM的Rational PurifyPlus,Micro Focus公司的
DevPartner Studio Professional等等。
面对这么多的工具我们应如何选择呢?首先我们
必须明确测试项,即测试内容,如源代码的安全性测
试的主要测试项就是前面第二部分所述的。有了明确
的测试项再选工具就明确了,每个工具都有自己的侧
重点,有的工具对缓存区溢出漏洞检测很有效,而有
些对内存泄露检查效果比较好。其次再考虑工具的易
用性,借助工具本来就是提高测试效率的,如果一款
测试工具使用起来比测试任务本身的工作量还大,那
我们借助这个工具的必要性就要重新考虑了。最后再
考虑工具的灵活性,即:可定制性;有些功能我们可
能用不到或者与具体项目需要有些偏差,能够通过改
变工具的配置文件来达到我们的要求。如,静态规则
检测工具,就要有测试人员自定规则或改变规则的功
能。
总之,一款好的测试工具至少应该满足三点要
求:(1)功能性强;(2)易用性强;(3)可配置性强。
4 结束语
源代码安全性测试是软件安全的有力保障,越来
越多的开发人员和测试人员都意识到代码安全性测试
的重要性[4]。文章详细阐述了代码安全的主要测试内
容和基本概念,并从静态和动态两方面对代码安全性
测试方法进行说明。最后提出选择安全性测试工具的
要点,其实我个人认为,这也是以后工具发展的一个
方向。未来源代码安全性测试的重点依然是缓存区溢
出和内存泄露两大类,到目前为止还没有一种好的测
试技术能保证软件中不存在这两类缺陷。特别是缓存
区溢出中的整数溢出问题,无论是人工还是工具都很
难发现,真可谓是隐蔽性强,危害性大。随着人们对
软件安全的要求越来越高,对测试工作者来说根除这
两类漏洞的测试技术研究仍然是重点。
参考文献
[1] Gary McGraw,Bruce Potter.Software security testing[J].
IEEE Security&Privacy, 2004,2(5):81-85.
[2] 施寅生,邓世伟,谷天阳.软件安全性测试方法与
工具[J].计算机工程与技术, 2008, 29(1):27-29.
[3] 张泽华,饶若楠,凌君逸.基于风险测试揭错能力
分析[J].计算机工程,2004,30:72-73.
[4] 吴芳美等.安全软件测试评估[M].北京:中国铁
道出版社,2001.
[5] O d e d T a l,S c o t t K n i g h t,T o m D e a n.S y n t a x-b a s e d
vulnerability testing of frame- based network protocols [C].
Fredericton New Brunswick, Canada: Proc Second Annual
Conference on Privacy, Security and Trust, 2004: 155-
160.
[6] Du Wenliang,Mathur A P.Vulnerability testing of software
system using fault injection [R].CoastTR98-02,1998.
作者简介:刘仁千(1977- ),男,河南南阳人,学士,
工程师,主要从事软件测试工作;张玉中(1983- ),男,
河南周口人,硕士研究生,研究方向为软件测试技术;
张超永(1983- ),男,河南郑州人,学士,助理工程
师,主要从事软件测试工作。
收稿日期:2013-07-11