APP下载

采用图遍历算法的服务端请求伪造漏洞检测

2020-10-10印鸿吉

计算机工程与应用 2020年19期
关键词:控制流污点漏洞

印鸿吉,陈 伟

南京邮电大学 计算机学院,南京210023

1 引言

随着互联网的快速发展,Web技术在科教、运输、金融等重要领域得到了广泛的普及和运用,互联网俨然成为了现代社会必不可少的重要元素。根据中国互联网协会最新发布的《中国互联网发展报告2018》[1],我国目前有7.72 亿网民,相比2016 年新增网民4 074 万人,同时中国网站数量高达533 万个,网页数量共计2 604 亿个。而根据CNCERT/CC发布的《2017年中国网络安全报告》[2]显示,近年来国家信息安全漏洞共享平台所收录的安全漏洞数量持续走高,按漏洞影响对象分类统计,Web应用漏洞占比17.6%。同时CNCERT/CC监测发现境内外约2.4万个IP 地址对我国境内2.9万余个网站植入后门,被植入后门的网站数量较2016年的8.2万个有大幅下降,同时又约2 万个网站被篡改,较2016 年的约1.7 万个增长了20.0%,因此可见网站安全形势十分严峻。并且由于Web 系统往往需要存储用户的个人信息和商业数据等高价值信息,因此Web系统逐渐成为黑客攻击的首选目标。

根据W3Tech[3]的最新统计结果,83.5%的网站使用PHP作为他们的网站语言,并且这个比例在2018年6月份之后一直居高不下,从2018年6月份开始,有37个新的Web 应用系统使用PHP 作为他们的编程语言,但是PHP 语言的脆弱性使得这些Web 应用系统或多或少都存在一些安全漏洞,如SQL 注入、XSS、任意文件读取、命令执行等。根据2017年发布的OWASP TOP 10[4],服务端请求伪造漏洞(Server Side Request Forgery,SSRF)属于失效的访问控制漏洞,这是一种由攻击者构造形成由服务端发起请求的一个安全漏洞。一般情况下服务端请求伪造漏洞的攻击目标是从外网无法访问的内部系统,因为它是由服务端发起的,所以它能够请求到与它相连而与外网隔离的内部系统,最终可以读取服务器的文件信息或探测内网信息[5]。SSRF 形成的原因大都是由于服务端提供了从其他服务器应用获取数据的功能且没有对目标地址做过滤与限制,比如从指定URL地址获取网页文本内容、加载指定地址的图片等等。相较于2013 年发布的OWASP TOP 10,由于这类漏洞是新增漏洞类型,传统的污点分析方法和工具尚不支持检测此类漏洞或者检测成功率较低。

因此,本文提出基于图遍历算法的SSRF 漏洞检测方法。通过构建每个PHP文件的抽象语法树,获取每个文件的数据流信息,进而利用数据流中变量间的传递关系和函数间的依赖关系构造全局的代码属性图,接着使用图遍历算法对生成的代码属性图进行污点分析,得到污点变量的代码传递依赖路径图,最后使用约束求解的方法对路径图中的经过函数信息进行分析,发现潜在的服务端请求伪造漏洞并自动化生成可用的攻击向量。

2 相关文献

自20 世纪70 年代以来,静态检测技术就被应用于源代码审计工作中,此后几十年间,国内外专家学者针对静态审计中污点型漏洞的检测技术做了大量研究,不断改进污点分析技术,致力于提高分析精度。麻荣宽等人[6]提出了一种生成控制流程图的算法,基于PHP内置函数解析PHP程序,生成抽象解析树,对内置特征、入口点和敏感点进行建模、精确分析数据流并提出了基于有效路径的污点分析方法,实现了基于变量回溯的路径遍历算法。霍志鹏[7]提出了一种静态检测的方法,在沙箱(HipHop Virtual Machine,HHVM)的基础上提出了一个针对PHP语言的流敏感、上下文敏感和过程间的前向数据流分析方法,针对PHP 的变量进行数据建模,并在此基础上实现了别名分析,同时还结合了一种基于有限自动机的字符串分析方法,重点关注污染传播类型的漏洞。Backes等人[8]提出了一种基于代码属性图的静态检测方法,通过抽象语法树和代码间的内在关系来构建代码属性图,并对代码属性图进行遍历来挖掘污点变量的数据流信息和潜在的安全风险。

但是静态检测技术由于无法验证漏洞是否真实存在,所以存在一定的局限性,因此越来越多人研究动态检测技术,这种技术可以准确的发现程序中的异常行为,从而找出目标程序存在的漏洞。孙基男等人[9]提出一种基于符号执行的注入类安全漏洞的分析技术,采用符号值作为输入,模拟程序执行,提取执行路径上相应的约束条件,构造可满足矩阵以及不可满足矩阵来对注入类安全漏洞进行检测和分析。Alhuzali等人[10]将动态检测和静态审计结合起来,提出了一种能够自动化生成攻击向量的污点分析模型,通过对污点变量的分析,结合数据库后端架构和其他模块的特性,精确生成数据流模型,以实现高质量的漏洞利用生成。文献[11]提出了一种自动化绕过的攻击向量生成方案,通过静态审计来对用户输入变量进行污点分析,采集污点变量的净化过程,同时结合动态检测和符号执行来重构输入参数并将其进行模拟攻击以提高准确率和降低误报率,最终生成能够被攻击者绕过的攻击向量。

3 基于图遍历算法的SSRF漏洞检测

由于SSRF 漏洞不同于传统的Web 漏洞,利用方式更多样,漏洞成因更复杂,所以文献[10]和[11]均不支持检测此类漏洞。如图1流程图所示,为检测SSRF漏洞,本文首先根据源代码构建其代码属性图[12],由于SSRF漏洞的本质是没有对用户输入作一个很好的防范,所以利用图遍历算法对代码属性图做污点分析,挖掘其中的污点变量传递路径并根据路径信息统计使攻击成功的约束条件,最后根据约束条件作约束求解自动化生成可利用的攻击向量。

图1 SSRF漏洞检测流程图

3.1 代码属性图

传统的污点分析方法都是基于代码控制流图,在分析变量传递和函数依赖时对数据建模要求较高,随着大数据时代的到来,关系型数据库逐渐无法适应数据建模的需求,NoSQL 数据库应运而生[13],其中图数据库在近年来得到的关注度最高。“图”是计算机领域的经典数据结构,它由一系列边和节点组成,节点上可以定义多种属性,边有名字和方向,同时也可以在边上定义属性。图论中有很多经典的算法,如深度优先算法、广度优先算法等,提高了在图中进行搜索、遍历等操作的效率。图数据库正是利用这种数据结构,解决复杂的关系查询问题[14]。因此本文借助图数据库来对代码控制流图进行存储,以便后续利用图遍历算法进行污点分析,如图2所示,扩展后的代码属性图包括控制流图、变量传递图和函数依赖图。

图2 代码属性图构建流程

3.1.1 控制流图

由于无法直接对PHP 代码进行分析,因此需要将PHP 代码编译转化为能够分析的中间形式。首先通过开源工具PHP-Parser[15]构建每个PHP 文件的抽象语法树,获得当前文件的所有抽象语法树节点,然后根据特定的抽象语法树节点类型作为父亲节点进行构建,如变量定义、变量赋值、函数调用等操作,这类操作节点一般都含有子节点,接下来根据父亲节点的语法树信息填充叶子节点,如具体的变量名称、函数名称等信息,同时为每一个节点填充节点信息,如代码所在的行数、调用函数是否为PHP 内置函数等相关信息。最后添加文件名作为每一个文件的抽象语法树的根节点,并且增加程序的入口节点和退出节点。

在构建完所有的抽象语法树节点后需要对各父亲节点进行关系建立和嵌套处理,关系建立的依据是通过查看节点类型,判断哪些父亲节点既是抽象语法树节点又是控制流节点,一般来说变量赋值和函数调用由于涉及到多个节点信息,因此在构建控制流图时仅需对各父亲节点进行关系建立,即可构建全局的控制流图。另外由于变量赋值中也可能会出现函数调用,因此这里的函数调用父节点会嵌套在变量赋值的父节点中,作为其子节点存在于控制流图中。

在构建控制流图时常常会遇到一些结构化控制流语句(for/while)和非结构化控制流语句(continue/break),本文对结构化控制流语句定义相应的路径规则,从而建立起初步的控制流路径图,其次对非结构化控制流语句做路径图修正处理,增加或删除某些控制流路径。

3.1.2 变量传递图

根据控制流图,本文通过对变量的定义节点作分析来判断变量的状态,在变量被定义之后与重新被定义之前,建立变量使用路径中各父亲节点的传递关系,传递关系为变量名。这样构建为后续的图遍历算法提供了遍历依据,在一定条件下仅需对传递路径作遍历回溯,从而减少了污点分析的时间复杂度和空间复杂度。

3.1.3 函数依赖图

在构建完控制流图和变量传递图后,由于没有对变量的函数调用建立依赖关系,所以在图数据库当中就会表现为自定义函数控制流与文件整体控制流的不连通性,在后续进行图遍历时就会导致遍历路径的终止,从而获取不到完整的数据流信息。

因此在这一步需要对函数类型建立函数调用的依赖关系,函数调用主要分为四种类型:自定义函数调用(test())、静态方法调用(test::test())、构造函数调用(new test())和动态方法调用($a->test())。针对前三种函数调用类型由于函数调用名没有任何歧义,因此可以直接建立经过函数的变量的父亲节点与函数调用间的依赖关系,针对最后一种动态方法调用,如果函数调用名为文件内唯一函数名称,则直接建立依赖关系,如果为不同类中的同一函数调用名称,则不建立函数依赖关系,因为在这种情况下如果仍想要构建函数依赖关系则需要对变量进行回溯,解析其定义的原始类名,这种情况在实际的代码环境中出现几率非常小,并且利用静态分析来解析原始类名时会出现非常复杂的类型判断。

3.2 污点分析

污点分析技术是信息流分析技术的一种实践方法,在信息泄露检测、漏洞探测、逆向工程等方面有广泛的应用,并被移植到各种不同的环境和平台当中[15]。污点分析技术将系统或应用程序中的数据标记为污点或非污点,当污点数据根据信息流传播策略可影响到非污点数据时,则将该数据标记为污点,当污点标签最终随数据传播到指定的存储区域或者信息泄露点时,则认定该系统违反了信息流策略[17]。

由于SSRF漏洞的本质是没有对用户输入的目标地址变量做很好的限制,因此在将代码转化为代码属性图并将其存储到图数据库中后,需要使用图遍历算法来对节点及节点间的关系进行污点分析,其中图遍历算法包括反向遍历和正向遍历。

3.2.1 反向遍历

如图3 所示,首先基于SSRF 的漏洞特点,构造了一个能够触发SSRF 漏洞的危险函数库,如file_get_contents、curl、fsockopen等函数,另外由于先前已经构造完代码属性图,因此在图中直接根据函数名称进行节点搜寻,确立潜在污点路径的终止节点。

接着根据危险函数节点进行变量搜寻,由于现在已经构造父亲节点和子节点的关系,这其中函数调用为父节点,子节点为调用函数名称和变量名,因此根据危险函数名节点进行父节点的回溯,获取其经过函数的变量名。其中curl函数由于会有配置项的存在,且能够触发SSRF 漏洞的配置项仅有CURLOPT_URL 项,因此针对curl函数获取其危险变量时,需要对函数配置项进行额外核查,提高污点路径的识别率。

然后根据调用函数的父节点再进行判断,这是因为函数调用极有可能发生在变量赋值阶段,在这个阶段我们既要获得经过函数名,又要获得映射变量名,同时在构造变量传递图时都是对各个子树的父节点进行关系建立,所以这里需要对父节点进行判断,进一步丰富污点路径图。

图3 反向遍历流程图

至此,已经获得变量的经过函数和潜在的映射变量名,由于本文采用的是反向遍历,因此污点分析的结束条件是判断变量类型是否为污点变量,这在代码属性图中表现为变量由用户输入,输入类型包含$_GET、$_POST、$_COOKIE 等常见的获取用户输入变量的方法。由于在构建变量传递图,传递关系为变量名,因此在这一步如果变量类型不为污点变量,那么则需要根据传递关系进行节点的反向回溯,对上一层父节点进行判断;如果为污点变量则输出污点路径图,其中包含路径上的关键父亲节点、外部输入类型和外部输入节点所在的控制流入口节点,即所在文件名等信息。

3.2.2 正向遍历

在实际的Web应用系统源代码中,常常会出现自定义函数的情况,前面所描述的函数依赖图也是为了解决这类情况的发生而构造的,在分析污点路径时发现当漏洞函数不存在于自定义函数段中且自定义函数被调用,由于反向遍历的根据是变量传递关系,但是在自定义函数中,数据流是自上而下的,在这种情况下采用反向遍历方法无法获取完整的污点路径信息。同样文献[10]中所提出的图遍历算法也会面临这样的问题,因此提出了一种正向遍历的方法。

当反向遍历获得调用函数名并发现当前调用函数为自定义函数,根据先前构造的函数调用图,这里就能回溯到自定义函数的代码属性图中去,接着对调用变量做映射,将其映射为自定义函数内对应的变量名,然后采用正向遍历的方式获取其变量的数据流路径图,这里遍历的依据也是变量间的传递关系,通过不断的依赖传递最终进入到自定义函数的终止节点,退出当前遍历流程并将正向遍历得到的数据流路径加入到原始变量的路径中去,从而不断丰富和完善污点路径。

3.3 符号执行

符号执行技术面临的主要问题是分析的对象包含大量的路径分支,求解工具不能在有限的时间内完成穷举过程,即存在路径爆炸问题[18]。如何有效地缓解路径爆炸问题是当前符号执行领域的热点之一,主要包括搜索约束和搜索策略这两个方面的研究:搜索约束即对程序的输入进行建模,或以目标位置为导向排除无关路径,这类方法是通过约束对搜索路径进行裁剪,从而达到降低复杂度的目的;搜索策略除了传统的深度优先或广度优先之外,还包括随机路径搜索和覆盖率优化等新的搜索方式。由于本文的检测是基于污点分析,因此这里采用搜索约束的方法来裁剪测试路径,利用约束求解的方式获得使攻击成功的攻击向量[19]。

如图4所示,由于先前通过污点分析已经获得了目标程序中的所有污点路径图,接下来针对污点路径图中的节点信息做具体判断,基于经过函数信息构造约束条件,约束条件函数分为几类:替换函数、解密函数、字符串匹配函数、净化函数、长度判断函数等。其中后三类通过编写约束条件语言代码来进行约束,如addslashes函数的约束条件语言表示为攻击向量不能出现单引号、双引号、反斜杠及NULL等特殊字符;intval函数的约束条件语言表示为攻击向量中不能出现字母;strlen 函数的约束条件语言表示为限制攻击向量的长度,当面对替换函数时首先判断替换后的字符串,如果为空则对替换正则表达式做解析,为攻击向量中的匹配值做双写处理,如果不为空则对攻击向量的匹配值做限制处理,第二类解密函数的约束条件语言表示为对攻击向量做相应的加密处理,确保最终的攻击向量能够被解密从而进入到目标函数中。

图4 符号执行流程图

在构造完污点路径图中的所有节点信息的约束表达式后,需要传入设定好的约束变量,因此本文预先构造了一个内置的攻击向量库,当前攻击库涵盖了各类能够绕过SSRF 漏洞防护手段的攻击向量,其中包括“File:///etc/passwd”“http://0177.0.0.1/”“127.0.0.1.xip.io”等能够获取服务器文件信息或探测内网的攻击向量。最终,通过约束条件的构造将所有的约束条件和约束向量传至约束求解器进行求解获得可利用的变形的攻击向量。

4 实验

为了评估本文所提出的检测方法,选取了一些测试样本集对实现方案进行评估,并与其他类似的PHP静态代码审计工具进行了实验结果的对比和分析,从而得出最终的实验结论。

4.1 数据集

由于基于静态分析的代码缺陷检测不可避免的会给出漏洞和误报,所以其扫描结果需要进行人工分析。通过人工分析,可以确定静态扫描给出的安全缺陷是否真实存在,从而可以得出该静态分析程序在误报方面的性能,然而对于程序中存在的漏洞总数是很难确定的,因此即使是频繁更新和维护的Web 应用系统也会不断的被发现存在漏洞,所以关于静态分析程序在漏洞方面的性能很难确定。

本文选取了5个实际环境下的Web应用系统代码,包括Wordpress、Joomla、Appcms 等开源代码,其中也包括已知漏洞位置和漏洞数量的开源系统,并将实验结果与RIPS[21]和Cobra[22]等知名静态代码审计系统进行对比。如表1,为各Web应用系统的PHP文件数和代码总行数。

表1 数据集基本信息

4.2 实验环境

由于本文是基于静态分析的SSRF 漏洞检测,因此不需要运行任何代码,所以测试环境比较简单,具体环境如下:操作系统macOS 10.13.4,处理器2.8 GHz Intel Core i7 4核,内存16 GB,硬盘250 GB。

4.3 实验结果分析

如表2 所示,在污点分析时间上,本文方案快于RIPS 代码审计工具,但是明显慢于Cobra 代码审计系统,这是因为Cobra 的检测原理是基于黑名单规则,当其进行漏洞检测时没有建立抽象语法树和控制流图来进行污点分析,因此速度最快。

表2 污点分析时间 min

本文把正确检测的SSRF 漏洞记为TP,把良性的PHP 代码错误地识别为SSRF 漏洞标记为FP。在本文所选取的实际系统中,存在已知SSRF漏洞的为Appcms(CNVD-2017-36541)、OpenSNS(CNVD-2016-07649)、Nelio AB Testing(CVE-2016-4029)。如表3 所示,在SSRF漏洞发现数上,由于RIPS尚未支持对该类漏洞的检测,因此无法检测出SSRF漏洞,而Cobra由于是基于字符串规则匹配来进行漏洞检测,当代码中出现黑名单函数则直接判定为漏洞,因此误报率较高,相比较之下本文方案由于会进行污点分析,当代码中出现敏感函数时会利用图遍历算法去分析污点路径,因此误报率较低,且针对目前已知的SSRF漏洞均能检测出来。

表3 SSRF漏洞发现数

如图5 是Appcms 中获取远程图片内容的代码,该代码通过接收外部参数来设定图片的HTTP 链接及图片格式,如果通过程序中一系列的参数检查后最终进入到“readfile”函数代码,并通过该函数获取远程图片内容。其中包含两个污点变量($_GET[‘url’]和$_GET[‘type’]),经过多步变量传递后$_GET[‘url’]变量进入到能够触发SSRF 漏洞的“readfile”函数,虽然先前有对变量进行base64编码的解密代码和检查的代码,但是均不能起到防护SSRF 漏洞的作用,所以最终通过构造PHP 伪协议的base64 加密的攻击向量就能够让目标服务器发起恶意请求。

图5 Appcms中的SSRF漏洞

本文预先内置的攻击向量库中包含针对Windows操作系统和Linux操作系统的攻击向量,但是在进行污点分析时由于无法判断目标服务器的操作系统类型,因此生成的攻击向量中会含有少量误报。从表4 可以看出均存在攻击向量的误报情况,原因是所生成的向量不能同时作用于Windows操作系统和Linux操作系统。

表4 攻击向量生成数

另外,本文针对部分加解密函数和净化函数也做了对应的约束处理,如针对Appcms 自动化审计所得到的污点路径中出现了base64 编码的解密函数,以及针对OpenSNS 自动化审计所得到的污点路径中包含“strip_tags”函数,前者需要建立base64 编码加密的条件约束,后者需要建立攻击向量中不能出现HTML、XML 及PHP标签的条件约束,最后通过约束求解的方式生成带有一定变形性质的攻击向量。从表4可以看出,针对目前已知的SSRF 漏洞,通过本文的检测方法均能生成可利用的带一定加密性质的攻击向量,其中考虑到SSRF漏洞利用的多样性,因此最终生成的攻击向量也会呈现多样性的特点,具有不同的攻击效果,产生多条攻击向量。

5 结束语

本文提出并实现了一种基于图遍历算法的SSRF漏洞检测方案。通过构建抽象语法树和扩展控制流图,构造了基于图数据库的代码属性图,接着使用反向遍历和正向遍历的算法进行污点分析获得污点路径图,最后使用搜索约束的方式对污点路径进行约束求解,获得可利用的攻击向量。实验结果表明,这种检测方案能够很好地发现服务端请求伪造漏洞,并能够自动化生成可绕过的攻击向量。后续的研究工作将从两个方面开展:一方面是反向遍历时进一步丰富节点类型判断,完善污点路径图;另一方面是进一步丰富和完善约束条件函数,覆盖通用的PHP内置函数。

猜你喜欢

控制流污点漏洞
漏洞
基于代码重写的动态污点分析
抵御控制流分析的Python 程序混淆算法
基于返回地址签名的控制流攻击检测方法
基于控制流的盒图动态建模与测试
污点
基于Petri网数据流约束下的业务流程变化域分析
使用Lightroom污点去除工具清理照片中的瑕疵
三明:“两票制”堵住加价漏洞
漏洞在哪儿