基于深度学习的动静结合的漏洞挖掘方法*

2021-03-21 04:34馨,易
通信技术 2021年2期
关键词:切片漏洞代码

宁 馨,易 平

(上海交通大学,上海 200240)

0 引言

随着互联网在全球的普及、物联网技术的不断发展、数字经济的广泛应用,围绕网络和数据的服务与应用呈现爆发式增长。丰富的应用场景暴露出越来越多的网络安全风险和问题,并在全球范围内产生广泛而深远的影响。图1显示了自2019年来CNNVD收录的漏洞数量变化[1],平均每月新增漏洞数量约1 500个。

图1 CNNVD采集的漏洞数量(2019/01—2020/10)

安全漏洞是网络安全风险中最主要的部分。安全漏洞是在硬件、软件以及协议的具体实现或系统安全策略上存在的缺陷,使攻击者能够在未经授权的情况下访问和修改系统。安全漏洞不仅是病毒、蠕虫等的重要传播途径,也是网络攻防的焦点,是网络安全领域的核心问题。因此,漏洞挖掘一直是热门的研究领域。

符号执行和模糊测试是目前比较常用的漏洞检测方法。符号执行(Symbolic Execution)由King等[2]首次提出,是一种程序分析技术,使用符号值代替具体值作为程序的输入,根据漏洞分析规则,通过约束求解等过程得到初步结果,再对结果进行分析处理找出漏洞检测。模糊测试(Fuzzing)的概念最早由Miller[3]等人提出,已经发展成为一种快速有效地检测程序中漏洞的方法[4-6]。模糊测试是一种通过向目标系统提供非预期的输入并监视异常结果来发现软件漏洞的方法。

随着人工智能的不断发展,用深度学习的方法来进行漏洞检测逐渐成为热门研究领域。目前已经发表了很多用深度学习的方法来检测软件漏洞的论文,包括源码层面的检测和基于中间语言的检测。但是,这类方法相较于传统的模糊测试等方法误报较多,且由于模型可能会学习到较多训练集上的特征,泛化性较差。它在训练集和测试集上效果可能很好,但是在真实代码中的准确率下降严重。

本文提出了一种将深度学习与漏洞代码检测和模糊测试结合的方法,通过对待测代码进行切片和用深度学习模型检测,先定位到可能触发漏洞的敏感点,再利用定向模糊测试的方法对代码进行测试,确定检测模型判断的漏洞的可触发性。

本文的组织结构如下:第1节介绍漏洞检测及模糊测试方面的相关研究;第2节介绍所采用的方法,包括代码切片、检测模型的训练及定向模糊测试;第3节是模型训练和模糊测试的实验结果;第4节是总结。

1 相关研究

1.1 漏洞检测

随着深度学习的发展,用深度学习的方法分析程序中的漏洞成为可能。

邹德清[7]等人提出了第一个基于深度学习进行漏洞检测的系统化框架SySeVR,并构建了基于深度学习的细粒度漏洞检测系统VulDeePecker,将人类专家从烦琐、主观的手工定义feature中解放出来。与静态漏洞检测方法相比,它显著降低了漏报率。该系统以基于语义的漏洞(Semantics-based Vulnerability Candidates,SeVC)为粒度进行检测,无法准确定位到漏洞行。

刘强[8]等人提出了一种基于程序切片的相似度匹配的漏洞检测方法,研究了根据关键点对代码进行切片、特征抽取和向量化的方法,通过计算待测代码切片与漏洞样本切片的相似度,判断待测样本中是否含有漏洞。该系统没有使用深度学习的方法,后续可以引入机器学习的方法进行优化。

此外,还有利用中间语言代码[9]和深度表征学习[10]来进行漏洞检测的研究,取得了一定的成效。

1.2 模糊测试

模糊测试(Fuzzing)是一种通过向目标系统提供非预期输入并监视异常结果发现软件漏洞的方法。它主要通过输入大量数据发现程序中存在的问题。可以通过使程序某些内容溢出出现异常,或者输入程序规定范围内的数据结果出现异常,找出程序漏洞。模糊测试的概念最早由Miller[3]等人提出,已经发展成为一种快速有效的检测程序漏洞的方法[4-6]。

AFL(American Fuzzy Lop)[11]最初是由Michal Zalewski开发的一个模糊测试工具,通过使用一种特殊的编译工具和遗传算法来自动发现有效的测试用例。这些测试用例会触发目标文件中的新状态,大大提高了模糊测试的覆盖率,且具有适度的性能开销。

AFLgo[12]是基于AFL开发的一个定向灰盒模糊测试的工具,通过设置一个目标点来进行定向模糊测试。对于每个种子,AFLgo会计算其执行路径到目标点的距离,并计划为更接近目标点的种子提供更多能量。其中,能量高的种子会有更多的变异机会。它的算法核心是模拟退火算法,每次随机变异种子,通过计算能量来判断此次变异是否是在向更优的方向靠近,以此来不断逼近目标点,实现定向的功能。

此外,微软研究院[13]还将模糊测试和强化学习结合起来,提出了一种利用强化学习来进行模糊测试的方法。利用马尔可夫决策过程的概念,将模糊测试转化为强化学习的问题,利用Q-Learning算法进行决策,通过在初始程序输入上执行一组种子变异方法后计算的奖励学习一个策略,以指导下一步种子变异所使用的方法,从而获得更高的回报。这种利用强化学习进行的模糊测试优于采用随机变异的模糊测试。

2 实现方法

项目总体流程,如图2所示。它主要通过代码切片、模型训练及检测、定向模糊测试3个步骤来实现漏洞检测,具体步骤如下:

(1)利用切片程序根据敏感点对代码进行切片,获得漏洞切片;

(2)利用获得的漏洞切片进行检测模型的训练及漏洞检测;

(3)根据模型检测的结果,对模型检测出的有漏洞的代码进行定向模糊测试。

图2 项目总体流程

2.1 程序切片

漏洞代码在用于模型训练前要进行数据预处理,其中最主要的步骤就是对漏洞进行切片,剔除漏洞代码中与漏洞触发无关的语句,使模型更容易学习到漏洞代码的特征。通过对代码进行切片,也可以减少向检测模型中输入的代码长度。

本文实现了一个简单的用于源码切片的工具,实现了跨函数、跨文件切片,同时支持自动扫描敏感函数和手动选择敏感行两种切片方式。具体的切片过程如图3所示。

将所有要合并在一起进行切片的文件路径作为切片工具的输入,如果要手动选择切片点,则还要将切片点所在的文件及其行号输入到切片工具。

步骤1:切片程序先在所有要切片的文件中扫描敏感函数(如果手动选择了切片点,则会跳过这一步)。

步骤2:程序会将扫描到的敏感函数或手动选择的敏感行中包含的函数及变量标记为被污染的标识符。

步骤3:对于被污染的函数,将其所有参数及调用该函数的行也标记为被污染。

步骤4:对于被污染的变量,程序将遍历该变量的作用域,寻找包含该变量的行,并将这些行中出现的新的函数与变量也标记为被污染。

步骤5:重复步骤3和步骤4,直到不再出现新的被污染标识符。

步骤6:将所有包含被污染标识符的代码行记录下来,输出只保留这些行的切片文件,最终得到代码的切片。

模型训练时多是已知漏洞代码中漏洞触发点的行号,所以采用手动选择敏感行的方式,以漏洞的触发点为切片点进行切片。在利用模型进行漏洞检测时,因为无法得知漏洞触发点的位置,甚至不能确定待测代码中是否含有漏洞,所以采用自动扫描敏感函数的方式进行切片,扫描程序中可能触发漏洞的敏感行,并将其作为切片点进行切片。

2.2 模型训练及检测

本文训练一个基于代码的相似性检测代码漏洞的10分类的检测模型。对于得到的代码切片,还要进行数据预处理才能用于模型训练,流程如图4所示。预处理主要包括把代码中的宏定义替换掉和对代码进行函数名和变量名的替换。替换函数名和变量名的主要目的是剔除自定义的函数名和变量名对检测模型的影响,将除了敏感函数之外的函数名统一替换为FUN1、FUN2的形式,将所有变量名统一替换为VAR1、VAR2的形式。

图3 切片程序工作流程

图4 代码预处理流程

经过预处理的样本先进行分词,将代码转换成由词组成的列表,之后对每个词进行编号,将编号的结果存储在一个字典中,再把所有的词替换成对应的编号,利用Word2Vec把所有的词编号转换为词向量,从而将所有的样本都转换成向量的形式。因为是基于代码的相似性来判断代码中是否含有漏洞,所以将正负样本组成不相似样本对,将两个同类漏洞的负样本组成相似样本对(正样本是无漏洞代码,负样本为有漏洞代码),并将这些样本对输入到Siamese孪生网络中进行训练。本文利用多个二分类模型实现多分类效果,共训练了10个二分类检测模型,每个模型检测一种类型的漏洞,整合10个模型的分类结果,最终得到漏洞检测结果。

在进行漏洞检测时,对于一段待检测的代码切片也要先进行预处理,之后分别用10种模型对代码进行相似性检测。每个模型返回的结果是一个取值范围在0~1之间的浮点数。该数值越接近1,说明这段待检测的代码与这种类型的漏洞的相似性越高。取10种模型中相似性最高(即模型返回的数值最大)的一类判断为待测代码的漏洞类型。若相似性最高的模型返回的分值也没有达到设定的阈值,则判断待测代码无漏洞。模型训练和检测的流程,分别如图5和图6所示。

2.3 定向模糊测试

对于模型预测存在漏洞的结果,利用定向模糊测试验证其漏洞的可触发性。

本文使用AFLgo[12]对代码进行定向模糊测试,将切片时记录的敏感点所在行标记为定向模糊测试的目标,并在BBtargets.txt文件中设置。之后利用afl-gcc对源代码进行插桩,并利用AFLgo计算种子到目标点的距离,进行定向模糊测试。具体的路径计算方法如下。

图5 模型训练流程

图6 检测流程

通过Clang得知目标行所在的函数Tf和基本块Tb,利用LLVM在调用图中计算两个函数间最短的距离(最短路径的边数)df(n1,n2)对于一个函数,它到所有目标行最短距离的调和平均数记为函数级的目标距离df(n,Tf)。对于函数中的每个基本块计算它到下一个可以跳转的函数的基本块的距离(调用图中两个基本块之间最短路径的边数),再加上待跳转的函数与目标函数的距离,即为基本块级的距离db(m,Tb)。最后,根据种子执行路径中经过的基本块,计算种子到目标点的距离db(s,Tb)。

AFLgo会给予距离目标点更近的种子更高的能量。这些种子将获得更多的变异机会,使AFLgo能更快逼近目标点,测试感兴趣的路径。

3 实 验

本文用于模型训练及检测的样本主要来自于SARD[14]数据集。该数据集是由NIST制作并维护的一个公开的漏洞样本集,由许多精心编写的小程序。每个样本都包含一个good版本和一个bad版本,分别对应无漏洞代码和有漏洞代码。

实验在miniconda3创建的虚拟环境中进行,虚拟环境的python版本为3.6,安装的其他软件版本信息为:scikit-learn为0.23.1,tensorflow-gpu为2.2.0,keras-gpu为2.3.1,gensim为3.8.0,smart_open为1.9.0。

训练的模型是针对源代码进行检测的。对于SARD数据集中的每个样本,根据good和bad的标签进行分割,其中bad版本作为漏洞样本,good版本为对应的无漏洞样本。在进行模糊测试时,通过SARD数据集中带有的OMITGOOD和OMITBAD标记,可以分别将样本编译成good版本和bad版本进行测试,且编译成的程序跟源代码分割出的good版本代码和bad版本代码一一对应。

实验过程中,通过对SARD数据集进行处理,共得到了135 776个样本,其中good和bad样本各占一半且一一对应。利用其中的113 612个样本进行模型训练,剩下的22 164个样本用于检测。在进行漏洞检测时,首先用模型去对这22 164个样本进行预测,将预测结果写入csv文件。若模型的检测结果表明某个样本有漏洞,利用定向模糊测试对该样本所对应的程序进行测试。FP、FN、TP、TN的定义,如表1所示。

表1 FP、FN、TP、TN的定义

统计检测结果中FP、FN、TP、TN的数量,并计算精确率(Precision)、召回率(Recall)和准确率(Accuracy),计算结果如表2所示。

从实验结果来看,训练的模型达到了72.38%的准确率,但是仍有较多的误报和漏报。结合模糊测试的方法后,通过对模型预测的漏洞进行定向模糊测试,可以消除误报,一定程度上提高了整个检测的准确率。

表2 模型检测结果

此外,采用这种动静结合的方法对glftpd软件1.23版本进行检测,通过切片和深度学习模型检测定位软件中的敏感点,再结合定向模糊测试,对glftpd源代码中的dupscan.c文件生成崩溃文件,结合漏洞利用的方法,验证了该崩溃是可以利用的漏洞。

4 结语

本文提出了一种将深度学习漏洞代码检测和模糊测试结合的方法,通过对代码进行切片,定位敏感点。先利用深度学习模型对代码切片进行检测,再通过定向模糊测试的方法将敏感点设置为目标点,对模型预测的有漏洞的代码进行测试,确定检测模型判断的漏洞的是否为误报。实验结果表明,通过这种方式可以显著降低误报率,提高可用性。

整个实验过程主要在SARD[14]数据集上进行,未来可以通过扩充数据集来重新训练检测模型,提高其泛化能力。目前主要是利用模糊测试来对模型预测的结果进行漏洞可触发性的检测,消除了模型的误报,但对模型的漏报还有待改进。后续可以考虑对模型预测的无漏洞代码中分值较高的一部分进行模糊测试,以降低漏报率。此外,由于SARD数据集中的代码相对短小,无法体现出该方法对模糊测试效率的提升。未来可通过检测工程文件,测试该方法对模糊测试效率的提升。

猜你喜欢
切片漏洞代码
漏洞
新局势下5G网络切片技术的强化思考
5G网络切片技术增强研究
基于selenium的SQL注入漏洞检测方法
网络切片标准分析与发展现状
创世代码
创世代码
创世代码
创世代码
浅析5G网络切片安全