设为首页 加入收藏

TOP

C/C++静态代码安全检查工具(一)
2018-05-21 15:48:36 】 浏览:215
Tags:C/C 静态 代码 安全 检查 工具

静态代码安全检查工具是一种能够帮助程序员自动检测出源程序中是否存在安全缺陷的软件。它通过逐行分析程序的源代码,发现软件中潜在的安全漏洞。本文针对 C/C++语言程序设计中容易存在的多种安全问题,分别分析了问题的根源,给出了具体可行的分析及检测方法。最后通过对静态代码安全检查工具优缺点的比较,给出了一些提高安全检查效果的建议。


软件漏洞的出现,除了程序员缺少编写高质量安全程序的意识外,编程语言本身的不安全性也使得程序员更容易在无意中编写出存在安全问题的代码。在众多编程语言中,C/C++语言是目前公认的最容易引起安全问题的语言,黑客往往就利用这些安全问题产生的漏洞来绕过安全策略,以达到网络攻击的目的。针对这种情况,在程序运行前,采用静态代码安全检查工具对源程序进行安全检查是一种很有效的方法。它面对的是问题本身而非征兆,所以有时它比动态监测更有效。


1 C/C++ 语言静态代码安全检查工具


静态代码安全检查工具的工作类似于软件测试中的静态测试。它们之间的不同之处在于软件测试是为了找出软件中的错误,而静态代码安全检查的主要目的是解决软件的安全问题,并以查找软件中容易被黑客利用的漏洞为目标。它的基本工作原理是:从前至后逐行读入源程序代码,定位可能的嫌疑,再逐步进行深入分析,直至得到确定的分析结果,最后根据不同的分析结果,依安全策略对其进行处理并报告处理结果。


2 C/C++ 语言静态代码安全检查原理分析


静态代码安全检查的工作过程是:首先读入不安全函数列表,然后先对欲扫描的源程序进行词法分析。根据不安全函数列表,有些函数会被找出来,并做相应的处理;对于需要进行语法分析的函数再做进一步语法分析,确定这些函数是否会引起安全问题,并做相应的处理。重复此过程直到分析完所有源程序,最后报告结果。


具体地说,针对不同类型的安全问题有以下几个方面的分析处理方法。


2.1 缓冲区溢出问题的解决途径


缓冲区溢出问题是目前软件中存在的最普遍的问题。从目前来看,找出了缓冲区溢出问题也就找出了绝大部分的安全问题。缓冲区溢出的最根本原因就是未检查动态缓冲区边界,当源数据长度超出缓冲区长度时产生溢出。要静态地分析出源程序代码中是否存在此类问题,首先就要计算出缓冲区长度。


针对缓冲区的不同类型,可有以下 4 种方法计算缓冲区长度:


(1) 字符串常量:如“satecode scan”,其缓冲区长度为字符数+ 1。它有两种存在方式,一是直接在函数中使用,另一种是出现在变量定义或赋值语句中。不论哪种都可以通过语法分析回归法计算;


(2) 静态缓冲区:如buf[1024],buf[MAX_len],对于前一种表示方式,可以直接根据 1024 计算缓冲区的大小。对于第 2 种情况,通过检查宏定义、常量定义,一般就可以确定缓冲区的大小;


(3) 动态缓冲区:动态缓冲区可以是通过new 进行分配,也可以通过 alloc、malloc 进行分配。对于前一种分配方法,需要考虑所分配的基类型,然后计算缓冲区长度。对于后一种分配方式,可直接通过表达式计算缓冲区大小;


(4) 指针引用:通过引用指针或数组下标,从而引用预先设好的缓冲区的一部分。对于这种情况,先用以上方法求出基缓冲区的大小,再通过表达式求值计算出其偏移。


除此之外,预填数据方法也可以检测出缓冲区溢出。例如:对于 strcpy (buf1, buf2),在调用前加入以下语句:memset


(buf1,'A',sizeof(buf2))。如果 buf2 比buf1 大,则在调试阶段发生缓冲区溢出。


此方法的特点是对于可能引起缓冲区溢出的函数,在调试阶段(debug),预填满源缓冲区数据,使溢出发生在调试阶段, 避免将不安全因素带到运行期。


具体地把C/C++中可能引起缓冲区溢出的函数分为以下几类,针对不同类的函数分别采用不同的分析与处理。


3.1.1 两个参数的字符串拷贝函数


此类的函数包括 strcpy、_mbscpy、strcat、wcscat 等。其特点是函数有两个参数,从一个参数向另一个参数拷贝字符串,当目标参数缓冲区长度小于源参数缓冲区长度时,发生缓冲区溢出。处理此类函数采用数据流跟踪的方法检查缓冲区长度。


例如下面一段程序:


(1) void transdata(char *str)


(2) {char buffer[24];


(3) strcpy(buffer,str); /*把buf[256] 中的内容拷到buffer[24] 里去*/


(4)


(5) char buf [256];


(6) for(i=0;i<255;i++)/*往buf[256]里写入 255 个M*/


(7) buf[i]='M';


(8) buf[255]=0;


(9) transdata (buf);


此段程序中,当程序调用 transdata(buf)时就会发生溢出。检查这个错误,首先在遇到 strcpy(buffer,str) 时,检查目的参数buffer,并找到在此之前出现的(第2 行),检测出它的长度应是24 个字节;接着,再检查源参数 str,发现它是经第 1 行(char  *str)→ 第 9 行(buf)-->第 5 行(char buf[256])的数据流得到的,并且检测出其长度是 256 字节。此时,已经能初步确定可能产生溢出了。也可以报告存在缓冲区溢出的位置(第 3 行)。但是,如果要更精确地定位,则需要利用语法分析器继续从第 5 行定义数组buf[256]开始检查所有路径,这样就可以检测出在调用transdata(buf)时确实会发生溢出,最后报告造成溢出的路径(第 3、2、5、6、7、8 行)。


3.1.2 3 个参数的字符串函数


这类函数包括 memcpy、strncpy、_mbsncpy、strncat、wcsncat等。其特点是有 3 个形式参数,例如memcpy(buf,"M", count),当 count 说明的字节数大于 buf 的缓冲区长度时,发生溢出。处理此类函数同样采用数据流跟踪的方法。在前面这个例子中,就是要检查并比较 count 的大小是否超过了buf 的缓冲区的大小。


3.1.3 格式化控制的字符串处理函数


这类函数有两种不同的情况:一种包括 printf、fprintf。其特点是函数不能确定数据参数在什么地方结束,因此缓冲区溢出情况一般发生在说明的参数的个数与格式化字符串不匹配时。此类问题要分析格式化字符串与参数是否匹配。


例如下面的一段程序:


(1)int  data=1234567890;


(2) printf("data=%d%n\n",data, &data);  /* 显示data 的值, 并把显示字符的长度写到变量data 中*/


(3) printf("data=%d\n",data);此程序正常结果是: data=1234567890


data=10


若第2 行写成printf("%d%n\n",data),执行时就会把显示内容的长度写到变量data 存储那个数值所在的指向的内存里[2]。当然,此地址不能被访问。但如果精心设计这个输入值,就会造成缓冲区溢出攻击。分析时,当遇到 printf 时,先用词法分析器分析并记录两个双引号中含有“%”且非“%%”的个数,然 后分析其参数的个数是否与之匹配,就能发现此类问题。


另一类函数包括sprintf、swprintf,它通过格式化字符串进

首页 上一页 1 2 下一页 尾页 1/2/2
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
上一篇用 Plumbum 开发 Python 命令行工.. 下一篇关于二叉树的遍历梳理(递归、非..

最新文章

热门文章

Hot 文章

Python

C 语言

C++基础

大数据基础

linux编程基础

C/C++面试题目