针对PHP应用的二阶漏洞检测方法

2018-04-19 05:09陈兴刚
信息安全研究 2018年4期
关键词:控制流污点数据流

周 航 方 勇 黄 诚 刘 亮 陈兴刚

1(四川大学电子信息学院 成都 610065)

2(四川大学网络空间安全学院 成都 610207)

3(成都市计量检定测试院 成都 610056)

(helloworld@stu.scu.edu.cn)

随着HTML5的快速发展,Web应用系统在各个行业中的应用越来越广泛,采用PHP开发的网站更是不计其数.据2014年相关报告统计,Github上PHP开源项目已经接近14万[1],而这一数据仍在不断增长.PHP作为脚本语言,存在入门简单、语法灵活、语法不严谨等特点.这些特点导致PHP语言开发的Web系统长期以来遭受网络攻击,针对PHP应用的安全研究刻不容缓.

目前针对程序源代码漏洞检测方法主要分为2类:动态检测技术和静态检测技术.动态检测技术可分为主动检测和被动检测2种方式:主动检测利用沙箱环境,将PHP源代码逐一在沙箱中运行,通过动态分析污点的汇聚点分析漏洞类型;被动检测主要是对用户行为进行监控,例如PHP扩展Taint,当用户输入的污染数据传入某些危险函数时扩展就会发出警告[2].静态分析主要采用了基于数据流分析的污点分析技术,对一个变量而言,它本身只有2种状态:污染状态和非污染状态[3].污点分析可以抽象为一个三元组〈sources,sinks,sanitizers〉,它的整个过程就是分析程序中污点源引入的数据是否不经过无害处理而直接进入污点汇聚点[4].相比于动态检测,静态检测不需要在运行源代码的情况下进行分析,有着执行速度快、效率高、代码覆盖面广等优点[5].

针对Web二阶漏洞检测技术,国内外的专家学者作了如下研究:Yan等人[6]采用识别准则的方式对二阶SQL注入漏洞进行检测,该方法对准则库依赖极强并且准则库需要人为添加维护,在实际环境中不可取;田玉杰等人[7]提出了一种基于改进参数化的二阶SQL注入攻击防御模型,但是该模型的建立是以正常用户输入中不允许包含SQL代码为前提的,误报率较高且通用性差.Backes等人[8]提出了一种基于语法相似性的方法进行漏洞检测,该方法针对大规模漏洞检测非常有效,但是它对模板代码有着很高的要求,对特定系统的漏洞检测十分局限.上述文献中提到的二阶漏洞检测方法普遍存在依赖规则、通用性较差的缺点.针对这些问题,本文主要进行了如下研究及工作:

1)研究了二阶漏洞的产生原理以及当前针对此类问题的检测方法,分析了这些方法在进行二阶漏洞检测时的不足.

2)提出了二阶漏洞的静态检测方法.在抽象语法树的基础上提出了控制流图的构建方法,利用控制流图以及语法分析技术重建数据库读写操作模型,结合数据流分析检测源码中可能存在的二阶漏洞.

3)基于上述方法实现原型系统CodeAn,并选取Github上PHP开源项目进行漏洞检测.实验结果表明:该系统误报率为9%,低于同类漏洞检测工具.

1 关键技术研究

1.1 二阶漏洞分析及示例

在常见的一阶漏洞中,污点源通常定义为用户的输入[9].污点分析的过程就是分析用户的输入在到达敏感函数之前是否经过了适当的净化处理.但是如果污点源引入的数据不直接进入污点汇聚点而是先存入数据库,当污染的数据再次从数据库中取出来并且没有经过适当的净化处理就进入污点汇聚点,此过程就可能会导致新的Web应用漏洞,这类漏洞通常被定义为二阶漏洞.针对此类漏洞的污点分析就可以抽象为一个四元组〈sources,database,sinks,santizers〉.

图1展示了二阶漏洞的模型:攻击者向服务端发起恶意请求;服务端接收恶意数据后存入数据库之中;在程序的运行过程中,数据库中的污染数据被取出来并且没有进行适当地过滤就直接进入危险函数,导致Web二阶漏洞产生.

图1 二阶漏洞模型

本文以存储型XSS为例(存储型XSS可以看作是二阶XSS漏洞),介绍二阶漏洞的产生原理.图2为1段存储用户输入数据、读取用户输入数据并输出的代码.在程序的第2行,服务端获取用户的数据并对数据进行SQL注入过滤;第3行将过滤后的数据存入数据库中;第5行读取数据库内容,并且不经过任何过滤直接将内容输出到页面.

图2 二阶漏洞代码示例

在程序执行过程中,系统对数据进行了addslashes过滤防止SQL注入.在系统取出数据之后并没有进行第2次针对性地过滤,导致XSS跨站脚本漏洞的产生.

用户需要发送2次请求就可以造成XSS攻击,如图3所示:

图3 用户攻击请求

1.2 数据库结构重建

在分析数据库读写操作时,若SELECT语句使用星号查询所有字段,数据流分析时会无法准确定位数据库操作的具体列;其次列本身的数据类型和长度可能对数据存在隐式净化.为了提高数据流分析的准确率和减少不必要的工作量,提出如下方法进行处理.

遍历源码中.sql后缀以及.php后缀的文件,利用正则表达式匹配文件中所有CREATE TABLE的SQL语句.使用语法解析器解析并重建数据库的表结构:包括所有表名、列名、列类型和长度.在MySQL中,字符串之外的数据类型都存在隐式净化,例如:整数类型Int、时间类型Time等等.针对字符串之外的数据类型,不对该列进行数据库读写分析;而针对字符串类型,设置长度阈值为10.通常长度小于10的列缺乏构造有效攻击载荷的条件,也不对其进行数据库读写分析.通过处理,得到表1所示的数据库结构信息:

表1 数据库结构信息

1.3 针对数据库的读操作模型分析

二阶漏洞模型如图1所示,由图1可知漏洞产生的根本原因是数据库中的污染数据传入了敏感函数.本文将PHP中的100多个敏感函数根据漏洞类型分为8类,部分信息如表2所示:

表2 敏感函数及分类

为了分析数据在databases→sinks之间的传播,本文进行了如下研究:

在控制流图中,函数调用的语句可以抽象为Expr-FuncCall〈name,args,result〉,其中name表示函数名,args表示参数,result表示函数返回值;数组元素的访问可以抽象为Expr-ArrayDim-Fetch〈var,dim,result〉,其中var表示数组名,dim表示数组键名,result表示返回值.

PHP中使用内置的query系列函数获取数据库资源标识符,为了构建数据库的读操作模型,利用控制流图获取query函数的参数args,此参数为待执行的SQL语句.通过语法解析器分析数据库读操作查询的相关表名以及字段名.如果存在UNION或者JOIN操作,则可能存在多个表;如果存在别名操作,则需要通过数据库结构信息进行别名映射.PHP中使用内置的fetch系列函数将数据库资源标识符转换为关联数组或索引数组.在对数据库查询结果数组进行访问时,若Expr-ArrayDimFetch中的属性dim为字符串类型,则其值与数据库中的列名一致;若属性dim为数字类型,则通过数据库结构信息查找相应的列名.

遍历控制流图中的基本块,获取基本块中所有函数调用语句Expr-FuncCall及其属性name和args.根据表2提供的列表,提取敏感函数调用的相关信息.以敏感函数所在的控制流图基本块为起点进行后向数据流分析,对敏感函数的参数args构建数据依赖关系,标记敏感参数args到数据库资源标识符的所有有效路径.

1.4 针对数据库的写操作模型分析

从二阶漏洞模型可知,漏洞产生的另外一个原因是用户输入的污染数据sources存储进数据库之中.sources点规则定义如表3所示:

表3 sources列表

为了分析数据在sources→databases之间的传播,本文进行了如下研究:

MySQL中存在3种数据库写操作语句:INSERT,REPLACE,UPDATE.INSERT和REPLACE用于向数据库中插入数据,UPDATE用于向数据库中更新数据.此处对UPDATE语句进行分析,其语法结构如下所示:

在构建数据库写操作模型时,主要针对表、列以及列输入变量进行分析.UPDATE语法中的assignment的结构为col-name=value,通常列输入变量为value.而语法结构中的WHERE子句用于界定数据更新的条件,LIMIT用于界定可更新的行数.本文只关注外部数据到数据库之间的传递,对限定语句不进行研究.

遍历控制流图中的基本块,获取数据库语句执行函数query的参数args,此参数为待执行的SQL语句.通过语法解析器进行解析[10]提取数据库写操作的表、列以及输入变量,结合数据库结构得到表4所示的数据库写操作模型.而针对存在隐式净化的列字段,不对其相应变量进行下一步的数据依赖关系分析.

表4 数据库写操作模型

以列的输入变量所在控制流图基本块为起点进行后向数据流分析,对输入变量构建数据依赖关系.在依赖关系中,依赖变量来自表3中的sources列表,则标记一条有效路径并结束当前变量的分析,直到所有变量的路径标记完毕.

1.5 基于控制流图的数据流分析技术

1.5.1 控制流图构建过程

控制流图[11](control flow graph,CFG)也称控制流程图,由图形符号表示程序在执行期间可能通过的所有执行路径.控制流图可通过遍历AST节点,利用控制节点分割基本块得到.PHP中控制节点及其分类如图4所示,构建方法如过程1所示.

图4 用户攻击请求

过程1.CFG生成过程.

1)遍历AST节点;

2)如果节点属于STMT-Jump,即为每个分支建立新的基本块,并且将新的基本块用有向边连接到前一个基本块,跳转条件被添加到有向边上;

3)如果节点属于STMT-Loop,即建立一个新的基本块,在数据流分析期间对循环条件进行分析;

4)如果节点属于STMT-Stop或STMT-Return,则停止解析;

5)一旦创建新的基本块,即对基本块进行数据流模拟并创建块摘要;

6)所有AST节点遍历结束之后停止本过程.

1.5.2 基于控制流图的数据流分析

数据流分析以控制流图中的基本块为最小单位,在控制流图的构建过程中模拟每个基本块的数据流.

最常见的数据依赖[12]情况就是赋值运算.如果变量$x的取值决定于$y,那么就可以认为$x依赖于$y.在分析的过程中,对每个基本块的变量进行搜集,构建数据依赖关系.

但是PHP中允许使用多个变量指向同一个内容[13],这种关系称为引用.如果存在引用关系,则可能导致分析存在缺陷.因此在基本块的数据流模拟时,将所有引用关系指向保存的一个引用结构中.

数据流分析的关键就在于为每个数据汇聚点构建数据依赖图,由于当前块中数据只依赖于之前基本块中的数据[14],在控制流图的基础上使用后向的数据流分析方法:循环遍历当前基本块的所有入口边缘,并在每个数据块摘要的属性中查找污点变量的名称.如果找到匹配项,则通过依赖分析以及引用分析将变量替换为对应的依赖变量,并复制所有污点标记以及净化标记.最后通过链接到基本块的所有入口边缘继续跟踪,直到标记出所有的路径.数据依赖图示例如图5所示:

图5 数据依赖图

在数据流分析的过程中,内置函数对数据的处理会改变其原有的污点属性[15].本文把内置的净化函数分为4类:编解码类、安全类、散列类、强制转换类.

编解码类:例如base64-decode,base64-encode等,在进行污点分析的过程中,数据经过编码函数处理之后则去除污点标记,经过解码函数处理之后恢复原有污点标记.

安全类:例如addslashes,stripslashes等,在数据流的分析过程中,数据经过前者处理之后去除对应的污点标记,经过后者处理之后恢复对应的污点标记.

散列类:例如md5等,数据经过此类函数处理之后,污染源的所有污点属性被清除.

强制转换类:例如intval等,与散列类函数一样,去除所有污点属性.

2 系统框架及实现

本文提出了一种针对PHP源代码Web二阶漏洞的检测模型,系统整体框架如图6所示.系统第1部分使用语法解析器对PHP源码进行预处理,读取源码并转换为token序列,然后通过语法规则将token序列转换为AST.第2部分遍历抽象语法树节点,并利用上文提到的方法构建程序控制流图:利用控制节点将源码分割成单独的基本块,并在基本块中进行数据流模拟,并提取基本块的块摘要.第3部分以数据库为中心,对其读写操作进行建模:利用正则表达式提取PHP应用中创建表的SQL语句,通过语法分析构建数据库结构信息.在抽象语法树和控制流图的基础上重构SQL执行语句,对数据库读写操作模型进行重建.对于数据库的读写分析分为2部分:databases→sinks以及sources→databases之间的数据流传播.本文利用后向数据流分析技术对敏感变量构建数据依赖图,标记所有的有效路径.在敏感函数和内置净化函数的基础上分析可能存在的二阶漏洞.

3 实 验

3.1 实验步骤及环境

为了验证理论的可行性及有效性,本文实现了原型系统CodeAn.选择了Github上10个PHP开源项目进行性能分析.实验环境如表5所示,测试采用了误报率以及总耗时2个关键要素进行评估.实验步骤如下:

图6 系统框架图

1)选取Github上10个PHP开源项目,分别选取某一版本作为检测对象并统计其公开的二阶漏洞.

2)搭建原型系统CodeAn,分别使用常见漏洞检测工具Fortify,RIPS,CodeAn对PHP开源项目进行漏洞检测.

3)从检测漏洞数、总耗时、误报率3个方面对检测结果进行统计,得到实验结果.

3.2 实验结果及分析

实验结果如表5所示,RIPS检测漏洞数23,误报率为17%,总耗时3 733 s;Fortify检测漏洞数31,误报率为23%,总耗时4 033 s;CodeAn检测漏洞数28,误报率为9%,总耗时2550s.通过分析发现,Fortify和RIPS产生的误报事件都集中在2个方面:一方面是未考虑数据库中字段类型以及长度对数据产生的隐式净化;另一方面是在数据流分析的过程中,没有考虑解码函数以及散列函数对数据产生的影响,而前者会恢复数据的污点标记,后者会去除数据的污点标记.

相比Fortify和RIPS而言,本系统有着更低误报率和更快的响应时间.

表5 实验结果

4 总 结

本文阐述了二阶漏洞的产生原理并提出了针对此类漏洞的检测方法:利用控制流图和语法分析技术对数据库读写操作进行建模,以数据库为中心进行数据流分析.实验结果表明,文中提到的二阶漏洞检测方法和常见工具相比,误报率更低,耗时更短.

本文主要针对面向过程的PHP应用程序,针对面向对象的PHP应用程序检测效果不佳.下阶段将针对此方向进行更深入的研究.

[1]Zapponi C.Programming languages and Git Hub[J/OL].[2017-11-10].http://githut.info/

[2]Nguyen-Tuong A,Guarnieri S,Greene D,et al.Automatically hardening Web applications using precise tainting[C]//Porc of Int Federation for Information Processing.Berlin:Springer,2005:295-307

[3]霍志鹏.基于静态分析的PHP代码缺陷检测[D].北京:北京邮电大学,2015

[4]王蕾,李丰,李炼,等.污点分析技术的原理和实践应用[J].软件学报,2017,28(4):860-882

[5]王耀辉,王丹,付利华.面向PHP程序的SQL漏洞检测系统[J].计算机工程,2016,42(4):112-118

[6]Yan L,Li X,Feng R,et al.Detection method of the second-order SQL injection in Web applications[G]//LNCS 8332:Proc of Int Workshop on Structured Object-Oriented Formal Language and Method.Berlin:Springer,2013:154-165

[7]田玉杰,赵泽茂,张海川,等.二阶SQL注入攻击防御模型[J].信息网络安全,2014(11):70-73

[8]Backes M,Rieck K,Skoruppa M,et al.Efficient and flexible discovery of PHP application vulnerabilities[C]//Proc of IEEE European Symp on Security and Privacy.Piscataway,NJ:IEEE,2017:334-349

[9]Papagiannis I,Migliavacca M,Pietzuch P.PHP aspis:Using partial taint tracking to protect against injection attacks[C]//Proc of USENIX Conf on Web Application Development.Berkeley:USENIX Association,2011:2- 2

[10]Cao D,Bai D.Design and implementation for SQL parser based on ANTLR[C]//Proc of Int Conf on Computer Engineering and Technology.Piscataway,NJ:IEEE,2010:V4-276-V4-279

[11]夏玉辉,张威,万琳,等.一种基于控制流图的静态测试方法[C]//全国软件测试会议与移动计算、栅格、智能化高级论坛会议录.武汉:中国计算机学会容错计算专业委员会,2009

[12]聂世超.PHP程序静态分析系统的设计与实现[D].长春:吉林大学,2011

[13]The PHP Group.References explained[EB/OL].[2017-11-10].http://php.net/manual/zh/language.references.php

[14]Xie Y,Aiken A.Static detection of security vulnerabilities in scripting languages[C]//Proc of USENIX Security Symp.Berkeley:USENIX Association,2006:179-192

[15]Ouni A,Kessentini M,Inoue K,et al.Search-based Web service antipatterns detection[J].IEEE Trans on Services Computing,2015,10(4):603-617

猜你喜欢
控制流污点数据流
基于代码重写的动态污点分析
抵御控制流分析的Python 程序混淆算法
汽车维修数据流基础(上)
基于返回地址签名的控制流攻击检测方法
汽车维修数据流基础(下)
基于控制流的盒图动态建模与测试
污点
基于Petri网数据流约束下的业务流程变化域分析
使用Lightroom污点去除工具清理照片中的瑕疵
基于数据流的结构化功能安全分析方法