sql 时间函数_基于函数摘要的静态代码分析

概念和范围

2ac7376a8865bd85661fb6e094e74ca6.png 本文的静态代码分析,指的是基于源代码的静态代码分析,虽然相关的知识可以应用到基于二进制反汇编的程序的分析上,但是因为我自己主要是做源代码静态分析的,所以难免介绍的时候,会有跟二进制分析有冲突的地方。 函数摘要,指一个函数的行为的描述,比如,函数的第2个入参,构造了一个sql命令并执行,这就是关于一个函数的描述,如果函数的第2个入参是一个未校验的数据,那么调用该函数就可能有SQL注入的风险。 本文只是对部分概念和使用场景的澄清,算是科普文,不涉及到具体的算法。而且,本文介绍的内容,应该算是基于源码的静态代码分析工具都应该具有的基本的能力。 按照惯例,为了能发公众号,整个图片放上去,介绍下整个文章的行文思路:

de9f27bd2e61be14903aa5e9cddea5af.png

函数摘要的分类

2ac7376a8865bd85661fb6e094e74ca6.png   根据函数摘要的生成的方式的不同,我们将函数摘要分为两类:

第三方库函数摘要

在静态代码分析开始前,就对第三方库函数生成函数摘要。因为静态代码分析过程,涉及到数据流分析的操作,正常都会涉及到跨过程的调用,此时如果分析到第三方库时,如果无法知道第三方库函数的行为,就会导致分析中断,进而无法继续分析。 例如上面的例子,如果我们有一个函数,这个函数的实现在一个第三方库中(执行时,通过so库动态链接),如果这个函数有这样的行为:第2个参数参与构造一个sql语句,并执行。那么我们自然会考虑到,如果第2个参数没有校验,可能会存在SQL注入风险。但是此时,分析时,如果我们并不知道该函数的实现,肯定无法分析到这个函数的调用可能有sql注入的风险。 通过上面的描述,在分析前,对第三方库函数生成摘要,可以在一定程度上减少误报和漏报,但是,并不能减少分析时间,因为对第三方库函数生成摘要,并不能减少任何分析的工作量

程序分析中生成的函数摘要

在程序分析过程中,涉及到函数调用时,针对被调用函数先进行分析,生成函数摘要,将函数摘要提供给上层的调用函数进行分析,这是跨过程分析中,基于摘要分析的方式。基于摘要分析,有一个好处,就是可以节省时间,比如,如果某个函数被其他10个函数调用,那么当我们对这个函数生成摘要,就只需要分析一次,另外10个函数在分析时,调用到该函数时,只需要结合摘要分析即可。 在程序分析过程中生成函数摘要,好处,至少体现在下面的三个方面: ①   减少公共函数的分析次数,节省当次分析时间; ②   通过对不变的函数生成函数摘要,在下次分析时使用,可以有效节省后面工程的分析时间; ③   如果当前工程是其他工程的依赖,那么在分析过程中生成的函数摘要自然就可以作为其他依赖当前工程的第三方库的摘要,可以减少分析的漏报和误报。

第三方库函数摘要

2ac7376a8865bd85661fb6e094e74ca6.png 第三方库函数摘要可以有效减少误报和漏报,上面已经有进行介绍。那么如何定制第三方库函数摘要呢?当前业界有两种不错的实践,可以进行参考。

函数行为描述应用到程序分析

函数行为描述,实际上,就是程序分析时,对这个函数的处理方式。其实这种方式比较容易理解,而且也是我们通常介绍第三方库函数摘要的通常方法,并且很多静态代码分析工具都是这样的实现方式。 还是拿之前的示例来举例,我们当前有个函数(函数为int test(int x, int y, string z)),该函数的第2个参数会参与构造一个sql语句,并且有sql执行,那么自然我们就要标记该函数执行时,如果第2个参数没有校验,那么就会有SQL注入风险。 我们用下面的格式来描述这样的函数行为描述方式:
if (call test(x, y, z) and isTaint(z)) {    report SQL_INJECTION;}
如果调用了test() 函数,并且第2个参数是污染的,就报一个SQL_INJECTION的issue。

添加函数行为标记生成到中间表示

其实这种方式,也是很正常的或者是顺其自然的一种思路。因为这是第三方库,因为我们并不知道第三方库的实现,所以可能导致误报和漏报,那我们就给它一个实现好了。 如下面的操作:
int test(int x, int y, string z) {    SQL_EXECUTION(z);}
SQL_EXECUTION() 是针对SQL执行定制的一个函数,那么如果我们将上面的代码,传递给静态代码分析工具时,拿上面的代码,替代掉没有实现的第三方库的函数时,就可以分析下去,并且在我们给的实现中,发现了SQL_EXECUTION 操作,那么就可以在test函数调用的地方给标记为SQL_INJECTION了。 上面两种方式,在业界都是广泛使用的,都是很好的实践。

程序分析中生成函数摘要

2ac7376a8865bd85661fb6e094e74ca6.png 在面向过程间调用的程序分析中,有两种方法,一种是基于克隆的跨过程分析方法,一种是基于摘要的函数分析方法。这些是跨过程的静态代码分析的基本方法。 北大熊老师的《程序分析技术》ppt中,关于这两方面的技术讲解得很到位,在《编译原理》龙书中,也有关于跨过程分析的关于基于克隆和基于摘要分析的方法。这里就不详细介绍深层次的内容了,完全可以看着两个资料学习。这里,简单介绍些皮毛,让大家有点儿印象。

基于克隆的跨过程分析

基于克隆的跨过程分析方法,大家可以用C/C++中的inline关键字的使用来理解。Inline,内联函数,在编译生成结果文件时,这个函数的调用全部都直接换成了这个函数的实现,这样可以让程序执行的更快,但是会导致结果变大,因为一个函数的实现,展开在了很多地方,对于静态代码分析,很容易就能发现,这种跨过程分析方式,可能会导致一个函数被分析很多遍,性能非常低。这种分析方法的应用场景,也跟inline的应用场景类似:inline函数实现很短很简单,甚至就是一条语句。

基于摘要的跨过程分析

基于摘要的跨过程分析方法,当然还是静态代码分析工具的主流方法,几乎所有的静态代码分析工具,都是采用类似的方法来实现的,而且在前面有介绍,基于摘要的跨过程分析方法,可以带来性能的提升。 下面,介绍一点儿第三方库摘要和程序分析过程中摘要的不同点收尾,是我今天中午跟同事遛弯儿时讲到的,在程序分析时建立摘要和在分析前预先建立第三方库摘要的对比:第三方库摘要建立的目的是为了分析更准确,减少漏报误报,但是无法提高分析性能,而分析过程中建立摘要目的是为了提高分析性能,但是由此是可能导致漏报和误报的。
int getNum(int x) {    return x <= 0 ? 0 : 99;}int min(void) {    int x = 3;    int y = 5 / getNum(x);    return y;}
如上,是一个非常简单的例子,在main函数的第2行,调用 getNum(x)方法,此时计算可知,getNum(x) 为 99,不可能有除0的错误的。 但是,如果是基于摘要的分析方法呢?此时,针对getNum() 建立摘要,我们可以得到的一个结论是 getNum() 的返回值为0 或者 99(如果跟x的值关联,那么还是每次进入函数分析),如果我们基于摘要进行分析,在int y = 5 / getNum(x); 的位置,getNum(x) 的值就可能是0 或者 99,此时,就可能会产生一个除0的误报。

总结

2ac7376a8865bd85661fb6e094e74ca6.png 本文介绍了一下在静态代码分析中,函数摘要的用法,不同的函数摘要的作用。当然,算是个入门介绍,如果读者自己对某个具体的点感兴趣,可以搜相关的论文来看。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值