A Deep Learning-Based System for Vulnerability Detection

本篇文献做者提出了一种基于深度学习来检测软件漏洞的方案git

      摘要:做者开始基于深度学习的漏洞检测研究,是为了减轻专家手工定义特性的繁琐任务,须要制定一些指导性原则来适用于深度学习去进行漏洞探测。出于这个目的,做者用代码 gadgets 来表明程序,而后把它们转化为向量,其中代码gadget是一些彼此语义相关的代码行。基于这设计了评估系统VulDeePecker,做者为深度学习方法提供了最初始的漏洞数据集,实验结果代表:与其余方法相比,系统可以实现更少的误报,将系统用于Xen,Seamonkey和Libav这3个软件产品检测到了4个未报告的漏洞。github

  现有的漏洞检测的解决方案有两个主要缺陷:强制执行繁重的体力劳动和致使较高的误报率。在本文中做者针对如下漏洞检测提出了一个解决方案,同时考虑到这些局限性:给定目标程序的源代码,如何肯定目标程序是否脆弱,若是是,漏洞在哪里。算法

  基于以上,做者作了三部分工做:(1)开始利用深度学习进行漏洞检测的研究。这种方法具备很大的潜力,由于深度学习不须要人工定义特性,这意味着漏洞的检测能够自动化。固然深度学习的有一些指导性的初步原则,包括使深度学习应用于漏洞检测的软件程序的表示,基于深度学习的漏洞检测的粒度的肯定以及漏洞检测的特定神经网络的选择。建议使用代码小部件来表示程序,代码小部件是一些(不必定是连续的)代码行,它们在语义上相互关联,能够向量化为深度学习的输入。(2)介绍了一种基于深度学习的漏洞检测系统的设计与实现,该系统被称为漏洞深度学习识别系统(VulDeePecker).有效性体如今能识别多种类型的漏洞,这就解释了VulDeePecker使用漏洞模式(做为深度神经网络学习)来检测漏洞。(3)提供了第一个用于评估VulDeePecker和其余基于深度学习的漏洞检测系统的数据集,该数据集来自美国国家标准与技术研究所(NIST)维护的两个数据源NVD[10]和软件保证参考数据集(SARD)项目[12]。数据集包含61638个代码小部件,包括17725个易受攻击的代码小部件和43913个不易受攻击的代码小部件。在17725个易受攻击的代码小部件中,10440个代码小部件对应于缓冲区错误漏洞(CWE-119),其他7285个代码小部件对应于资源管理错误漏洞(CWE-399),做者已经在https://github.com/CGCL-codes/VulDeePecker上提供了数据集。数组

  接下来主要研究基于深度学习的漏洞检测的一些初步指导原则和VulDeePecker的设计网络

一.深度学习检测漏洞的初步原则,其核心是回答三个问题(1)如何表示基于深度学习的漏洞检测程序?(2)深度学习漏洞检测的适当粒度是多少?(3)如何选择特定的神经网络进行漏洞检测?函数

如何表示软件程序?学习

  因为深度学习或神经网络以向量做为输入,须要将程序表示为具备语义意义的向量,即须要将程序编码成向量,这些向量是深度学习所须要的输入。指导原则1.程序能够首先转换成某种中间表示,称为代码gadget。术语“代码小部件”的灵感来自代码重用攻击上下文中的术语"小部件"[18],代码小部件是少许(不必定是连续的)代码行。编码

什么是适当的粒度?spa

  因为不只须要检测程序是否易受攻击,并且还须要肯定漏洞的位置,所以须要更细的粒度来进行基于深度学习的漏洞检测。这意味着漏洞检测不该该在程序或函数级别进行,这是很是粗粒度的,由于程序或函数可能有不少行代码,肯定其漏洞位置自己就是一项困难的任务。指导原则2.为了帮助Pin定位漏洞位置,程序应该被表示为更细的粒度,而不是函数或者程序级别的。代码小部件适用于指导原则2。设计

如何选择神经网络?

  神经网络在图像处理,语音识别,天然语言处理([21][30][40])等不一样于漏洞检测的领域很是成功。这意味着许多神经网络可能不适合漏洞检测,须要一些原则来指导选择适合漏洞检测的神经网络。指导原则3.由于一行代码是否包含漏洞可能取决于上下文,可以处理上下文的神经网络可能适用于漏洞检测。这一原理代表,用于天然语言处理的神经网络可能适用于漏洞检测,由于上下文在天然语言处理[33]中很重要。将上下文的概念引入到本文的设置中,观察到程序函数调用的参数常常是受到程序中较早操做的影响,也可能受到程序中较晚操做的影响。

  因为天然语言处理有许多神经网络,首先从递归神经网络(RNNs)[51][53]开始,这些神经网络在处理顺序数据方面是有效的,而且确实被用于程序分析(但不是漏洞检测的目的)[20][48][56][57].然而RNNs存在消失梯度(VG)问题,致使模型训练[16]失效。注意,VG问题是由RNNs的双向变体(BRNNs[47])继承的。

  VG问题能够经过将记忆细胞植入RNNs来解决,包括长期记忆(LSTM)细胞和门控循环单元(GRU)细胞[17][22]。因为GRU在语言建模[27]上没有超过LSTM,因此做者选择LSTM进行漏洞检测。因为程序函数调用的参数可能受到程序中较早的语句影响,也有可能受到较晚的语句影响,这说明单向LSTM可能还不够,应该使用双向LSTM(BLSTM)进行漏洞检测。BLSTM神经网络图以下:

有多个BLSTM层,一个Dense层和一个Softmax层。学习过程的输入是一个肯定的表示向量,BLSTM层有两个方向,向前和向后。Dense层减小了从BLSTM层接收到的向量维数,Softmax层以Dense层接收到的低维向量做为输入,负责表示和格式化结果,为学习阶段更新神经网络参数提供反馈。学习阶段的输出是一个调好模型参数的BLSTM神经网络,检测阶段的输出就是分类结果。

 二.VulDeePecker的设计

 A.定义代码小部件

  为了用适合神经网络输入的向量表示程序,提出了将程序转换为代码小部件的表示,其定义以下:代码小部件是由许多程序语句组成的(例如,这些代码行),它们在数据依赖关系或控制关系方面在语义上彼此相关。为了生成代码小部件,提出了从关键点的启发式概念,来从特定的角度表示程序。关键点在缓冲区溢出漏洞中能够是:库/API函数调用,数组和指针。本文中,将重点讨论如何使用库/API函数调用的特定关键点来证实它在基于深度学习的漏洞检测中的有效性。

  与库/API函数调用相同的关键点对应,代码小部件能够经过数据流或者程序控制流分析的方式生成,其中著名的[23]算法,[50]算法和Checkmax[2]等易于使用的商业产品。

 B.VulDeePecker的概述

  系统有两个阶段:学习训练阶段和检测阶段。学习阶段的输入是带有脆弱和不脆弱的大量训练项目,所谓脆弱指的是包含已知的漏洞。学习阶段的输出为被编码成BLSTM神经网络的漏洞模式。

  学习阶段有4个步骤:

Step 1:提取库/API函数调用和相关的的程序片断

1.1从训练程序中库/API函数的调用,同时注意VulDeePecker有关库/API函数调用的关键点。

1.2为在步骤1.1中提取的库/API函数调用的每一个参数(或者变量)提取一个或多个程序片断。

Step 2:生成训练程序的代码小部件及其标定好的真实数据

2.1将步骤2.2中得到的程序片断组装为代码小片断,每个库/API函数调用对应一个代码小部件。代码小部件不必定对应某些连续的代码行,相反,它是由多行语义相关的代码组成。

2.2对代码小部件标记真实数据。这个步骤将每一个代码小部件标记为1(或0不是脆弱的),代码小部件的真实数据标签是可用的,由于咱们知道训练程序是否脆弱,若是脆弱,咱们就知道了脆弱的位置。

Step 3:将代码小部件转换为向量表示

3.1将代码小部件转换为特定的符号表示,稍后将对此进行详细说明。这个步骤的目的在于保存一些训练程序的语义信息。

3.2对3.1步骤中的符号表示的代码小部件进行编码为向量,这向量做为训练BLSTM神经网络的输入。

Step 4:训练BLSTM神经网络

4.1将编码小部件编码成向量并得到其标定好的真实数据后,这种训练过程对于学习BLSTM神经网络是标准的。

  检测阶段是给定一个或者多个目标程序,从它们中提取库/API函数调用以及相应的程序片断,这些程序片断组装成代码小部件。这些代码小部件被转化成符号表示,而后编码成向量做为训练后的BLSTM神经网络的输入。网络输出哪些向量,所以哪些代码小部件是脆弱的("1")或者是不脆弱的("0"),若是一个代码小部件很脆弱,它会肯定目标程序中漏洞的位置。如图所示:

  检测阶段有2个步骤:

Step 5:将目标程序转换为代码小部件和向量

5.1从目标程序提取库/API函数调用(相似步骤1.1)

5.2根据库/API函数调用的参数提取程序片断(相似步骤1.2)

5.3将程序片断组成为代码小部件(相似步骤2.1)

5.4将代码小部件转换为它们的符号表示(相似步骤3.1)

5.5将代码小部件的符号表示编码为向量(相似步骤3.2)

Step 6:检测。这个使用学习到的BLSTM神经网络对从目标程序中提取的代码小部件相关的向量进行分类。当这个向量被分类为“1”,意味着相关的代码小部件是脆弱的,而且肯定了漏洞的位置。不然队对应的相关代码小部件不是脆弱的("0")。

 

具体每一个步骤的实现,因为时间和篇幅关系,下一节进行探讨。

相关文章
相关标签/搜索