本论文相关内容

  1. 论文下载地址——Engineering Village
  2. 论文中文翻译——VulDeePecker: A Deep Learning-Based System for Vulnerability Detection
  3. 论文阅读笔记——VulDeePecker: A Deep Learning-Based System for Vulnerability Detection

文章目录

  • 本论文相关内容
  • 前言
  • VulDeePecker:基于深度学习的漏洞检测系统
    • 作者信息
    • 摘要
    • I. 引言
    • II. 基于深度学习的漏洞检测指导原则
      • A. 如何表示软件程序?
      • B. 什么是合适的粒度?
      • C. 如何选择神经网络?
    • III. VulDeePecker的设计
      • A. 定义代码小工具
      • B. VulDeePecker概述
      • C. 第一步:提取库/API函数调用和程序切片
      • D. 第二步:提取代码小工具并标记其基本真实标签
      • E. 第三步:将代码小工具转换为向量
    • IV. 实验和结果
      • A. 评估漏洞检测系统的指标
      • B. 准备VulDeePecker的输入
      • C. 训练BLSTM神经网络
      • D. 实验结果与启示
    • V. 局限性
    • VI. 相关工作
      • A. 漏洞检测方面的前期工作
      • B. 与使用深度学习进行程序分析相关的前期工作
    • VII. 结论
    • 致谢
    • 附录
      • A. LSTM核
      • B. Checkmarx选择的库/API函数调用
  • 总结

前言

本文为VulDeePecker: A Deep Learning-Based System for Vulnerability Detection论文的中文翻译,此论文为第一篇使用深度学习技术应用到漏洞检测的技术文章,很有参考价值。本文经过仔细翻译并检查后整理为文档,当然可能仍有疏忽,还请指正。上面的链接为关于本论文的下载地址以及本论文的详细阅读笔记,感兴趣的读者可以翻阅。


VulDeePecker:基于深度学习的漏洞检测系统

作者信息

甄莉,邹德清,许寿怀,新余欧,海金,王素娟,邓志军,余义忠
服务计算技术与系统实验室、大数据技术与系统室
计算机科学与技术学院集群与网格计算实验室
华中科技大学
deqingzou@hust.edu.cn
河北大学网络安全与计算机学院
深圳华中科技大学研究院
德克萨斯大学圣安东尼奥分校计算机科学系

摘要

软件漏洞的自动检测是一个重要的研究课题。然而,该问题的现有解决方案依赖于人类专家来定义特征,并且往往遗漏了许多漏洞(即导致高假阴性率)。在本文中,我们发起了使用基于深度学习的漏洞检测的研究,将人类专家从手动定义特征的繁琐和主观任务中解脱出来。由于深度学习的动机是处理与漏洞检测问题截然不同的问题,因此我们需要一些指导原则来将深度学习应用于漏洞检测。特别是,我们需要找到适合深度学习的软件程序的表示。为此,我们建议使用代码小工具表示程序,然后将其转换为向量,其中代码小工具是语义上相互关联的多行(不一定是连续的)代码。这引导设计和实现了一个基于深度学习的漏洞检测系统,称为Vulnerability Deep Pecker (VulDeePecker)。为了评估VulDeePecker,我们提供了第一个用于深度学习方法的漏洞数据集。实验结果表明,与其他方法相比,VulDeePecker可以实现更少的误报(具有合理的误报率)。我们进一步将VulDeePecker应用于3种软件产品(即 Xen、Seamonkey和Libav),并检测到4个漏洞,这些漏洞未在国家漏洞数据库中报告,但在发布这些产品的更高版本时由供应商“悄悄”修补;相比之下,我们试验过其他漏洞检测系统几乎完全忽略了这些漏洞。

I. 引言

许多网络攻击都源于软件漏洞。尽管在追求安全编程方面投入了大量精力,但软件漏洞仍然是一个重大问题,并将持续存在。这可以通过在2010年Common中注册的漏洞数量的事实来证明漏洞和暴露(CVE)约为4600。2016年增长到约6500。另一种方法是自动检测软件程序中的漏洞,简称程序。为此,已有许多静态漏洞检测系统和研究,从开源工具到商业工具,再到学术研究项目。然后,现有的检测漏洞的解决方案有两个主要缺点:繁重的体力劳动和较高的误报率,下文对此进行了详细阐述。

一方面,现有的漏洞检测解决方案依赖于人类专家来定义特征。即使对于来说,由于问题的复杂性,这也是一项繁琐、主观、有时容易出错的任务。换言之,特征的识别在很大程度上是一门艺术,这意味着结果特征的质量,以及由此产生的检测系统的有效性,因定义特征的个人而异。原则上,这个问题可以通过让多个专家定义他们自己的特征,然后选择一组能够提高效率的特征或使用这些特征的组合来缓解。然而,这带来了更加繁琐的工作。事实上,人们总是希望尽可能减少甚至消除对人类专家密集劳动的依赖。这可以通过网络防御自动化的趋势来证明,这是由DARPA的网络大挑战等倡议推动的。因此,将人类专家从手动定义漏洞检测特征的繁琐和主观任务中解脱出来是很重要的。

另一方面,现有的解决方案往往会漏掉许多漏洞或导致较高的误报率。例如,两个最新的漏洞检测系统VUDDY和VulPecker分别产生了18.2%(当检测Apache HTTPD 2.4.23的漏洞时)和38%(当应用于455个漏洞样本时)的误报率。我们自己的独立实验表明,它们的假阴性率分别为95.1%和89.8%(见第四节表五)。请注意,[28]、[32]中报告的假负率与我们实验得出的假负率之间的巨大差异是由使用不同的数据集造成的。这些高假阴性率可以通过强调低假阳性率来证明,假阳性率分别为VUDDY的0%和VulPecker的未报告。我们的独立实验表明,VUDDY和VulPecker的假阳性率分别为0%和1.9%(见第四节表五)。这表明VUDDY和VulPecker旨在实现低误报率,这似乎是检测由代码克隆引起的漏洞的方法所固有的;相反,当使用这种方法检测不是由代码克隆引起的漏洞时,会出现较高的误报率。

公平的说,具有高误报率的漏洞检测系统可能不可用,具有高漏报率的漏洞检测系统可能没有用处。这证明了寻求能够实现低误报率和低漏报率的漏洞检测系统的重要性。当无法做到这一点时(因为假阳性和假阴性常常相互矛盾),只要假阳性率不太高,我们就可以把重点放在降低假阴性率上。

现有的解决方案的上述两个局限性激发了设计漏洞检测系统的重要性,该系统无需要求人类专家手动定义特征,也无需产生较高的误报率和漏报率。在本文中,我们提出了以下漏洞检测问题的解决方案,同时考虑到这些限制:给定目标程序的源代码,我们如何确定目标程序是否存在漏洞,如果存在,漏洞在哪里?

我们的贡献。本文最终解决上述问题的第一步。具体而言,我们做出了三项贡献。

首先,我们启动了使用深度学习进行漏洞检测的研究。这种方法有很大的潜力,因为深度学习不需要人类专家手动定义功能,这意味着漏洞检测可以自动化。然而,这种方法具有挑战性,因为深度学习并不是为此类应用而发明的,这意味着我们需要一些指导原则来将深度学习应用于漏洞检测。为此,我们讨论了一些初步的指导原则,包括表示使深度学习适用于漏洞检测的软件程序,确定基于深度学习的漏洞检测的粒度,以及选择用于漏洞检测的特定神经网络。特别是,我们建议使用代码小工具来表示程序。代码小工具是一系列(不一定是连续的)代码行,它们在语义上相互关联,可以作为深度学习的输入进行向量化。

其次,我们介绍了一个基于深度学习漏洞检测系统的设计和实现,称为Vulnerability Deep Pecker(VulDeePecker) 。我们从以下角度评估VulDeePecker的有效性:

  • VulDeePecker能否同时处理多种类型的漏洞?这个观点很重要,因为有问题的目标程序可能包含多种类型的漏洞,这意味着一个只能检测到一种类型漏洞的漏洞检测系统将是非常有限的。实验结果肯定地回答了这个问题。
  • 人类专业知识能否帮助提高VulDeePecker的效率?实验结果表明,VulDeePecker的有效性可以通过结合人类专业知识而进一步提高,但这并不是为了定义特征。这表明,自动漏洞检测系统虽然能够将人类专家从繁琐的定义特征的劳动中解脱出来,但可能仍需要从其他目的中利用人类专业知识。这为今后的研究提出了一个重要的开放问题。
  • 与其他漏洞检测方法相比,VulDeePecker的有效性如何?实验结果表明,VulDeePecker比其他静态分析工具要有效得多,这些工具要求人类专家定义检测漏洞的规则,以及最先进的基于代码相似性的漏洞检测系统(即VUDDY和VulPecker)。

这些问题可能被视为确定评估基于深度学习的漏洞检测系统有效性的基准的初步努力。

为了展示VulDeePecker的有用性,我们将其进一步应用于3种软件产品(即 Xen、Seamonkey和Libav )。VulDeePecker能够检测到4个漏洞,这些漏洞未在国家漏洞数据库(NVD)中报告,但在发布这些产品的更高版本时,供应商“无声”修补了这些漏洞。相比之下,我们试验地其他漏洞检测系统几乎完全忽略了这些漏洞。更准确的说,其中一个漏洞检测系统能够检测到4个漏洞中的一个(即,4个漏洞缺失3个),而其他系统则全部缺失4个漏洞。我们将进行更多实验,以证明VulDeePecker能否检测到尚未识别的漏洞,包括可能的0天漏洞。

第三, 由于没有现成的数据集来回答上述问题,我们提供了第一个用于评估VulDeePecker和其他未来将开发的基于深度学习的漏洞检测系统的数据集。该数据集源自美国国家标准技术研究院(NIST)维护的两个数据源:NVD和软件保证参考数据集(SARD)项目。该数据集包含61638个代码小工具,包括17725个易受攻击的代码小工具和43913个不易受到攻击的代码小工具。在17725个易受攻击的代码小工具中,10440个代码小工具与缓冲区错误漏洞(CWE-119)相对应,其余7285个代码小工具与资源管理错误漏洞相对应(CWE-399)。我们已在以下位置提供数据集:https://github.com/CGCL-codes/VulDeePecker。

论文组织。本文的其余部分组织如下。第二节介绍了基于深度学习的漏洞检测的一些初步指导原则。第三节讨论了VulDeePecker的设计。第四节描述了我们对VulDeePecker的实验评估和结果。第五节讨论了VulDeePecker的局限性和未来研究的开放问题。第六节描述了相关的前期工作。第七节总结了本论文。

II. 基于深度学习的漏洞检测指导原则

在本节中,我们提出了一些使用深度学习检测漏洞的初步指导原则。这些原则对于本研究来说已经足够了,但可能需要进一步完善,以满足基于深度学习的漏洞检测的更一般目的。这些原则集中于回答三个基本问题:(i)如何表示基于深度学习的漏洞检测程序?(ii)基于深度学习的漏洞检测的适当粒度是多少?(iii)如何选择用于漏洞检测的特定神经网络?

A. 如何表示软件程序?

由于深度学习或神经网络将向量作为输入,我们需要将程序表示为对漏洞检测具有语义意义的向量。换句话说,我们需要将程序编码为向量,这些向量是深度学习所需的输入。注意,我们不能任意地将程序转换为向量,因为向量需要保留程序的语义信息。这建议我们使用一些中间表示作为程序与其向量表示之间的“桥梁”,向量表示是深度学习的实际输入。这将导致以下结果:

指导原则1: 程序可以首先转换为一些中间表示,可以保留程序元素之间的(部分)语义关系(例如,数据依赖性和控制依赖性)。然后,中间表示可以转换为向量表示,即神经网络的实际输入。

正如我们稍后将阐述的那样,指导原则1引导我们提出一种称为代码小工具的中间表示法。“代码小工具”一词的灵感来源于代码重用攻击上下文中的小工具一词,因为代码小工具是少量(不一定是连续的)代码行。

B. 什么是合适的粒度?

由于不仅需要检测程序是否存在漏洞,而且需要确定漏洞的位置,因此应使用更细的粒度进行基于深度学习的漏洞检测。这意味着漏洞检测不应在程序或函数级别进行,因为程序或函数可能有许多行代码,而确定其漏洞的位置本身可能是一项困难的任务。这将导致:

指导原则2:为了帮助确定漏洞的位置,应该以更细的粒度表示程序,而不是将程序或函数作为一个单元来处理。

事实上,前面提到的代码小工具表示可以实现漏洞检测的细粒度,因为代码小工具通常由少量代码行组成。这意味着代码小工具表示自然满足指导原则2。

C. 如何选择神经网络?

神经网络在图像处理、语音识别和自然语言处理等不同于漏洞检测的领域取得了很大成功。这意味着许多神经网络可能不适合漏洞检测,我们需要一些原则来指导选择适合漏洞检测的神经网络。我们的实验表明如下:

指导原则3:由于一行代码是否包含漏洞可能取决于上下文,因此可以处理上下文的神经网络可能适合于漏洞检测。

这一原则表明,自然语言处理的神经网络可能适用于漏洞检测,因为上下文在自然语言处理中也很重要。把上下文的概念放在本文的背景中,我们发现程序函数调用的参数经常受到程序中早期操作的影响,也可能受到程序中后期操作的影响。

由于有许多用于自然语言处理的神经网络,让我们从递归神经网络(RNNs)开始。这些神经网络在处理顺序数据方面很有效,实际上已经用于程序分析(但不用于漏洞检测)。然而,RNNs存在Vanishing Gradient(VG)问题,这可能导致模型训练无效。请注意,VG问题由RNNs的双向变体(称为BRNNs)继承。我们更喜欢不受VG问题影响的神经网络。

VG问题可以通过将存储单元转换为RNNs来解决,包括长短期记忆(LSTM)核和选通递归单元(GRU)核。由于GRU在语言建模方面没有优于LSTM,因此我们选择LSTM进行漏洞检测,并将其与GRU的比较推迟到未来的工作中。然而,即使LSTM也不足以检测漏洞,因为它是单向的(即从早期LSTM核到后期LSTM核)。这是因为程序函数调用的参数可能会受到程序中前面语句的影响,也可能会受到后面语句的影响。这表明单向LSTM可能不能胜任此项工作,我们应该使用双向LSTM(BLSTM)进行漏洞检测。

图1.BLSTM神经网络简介

图1突出显示了BLSTM神经网络的结构,该网络具有多个BLSTM层、一个密集层和一个softmax层。学习过程的输入是以某种矢量表示的。BLSTM层有两个方向,向前和向后。BLSTM层包含一些复杂的LSTM核,它们在本文中被视为黑盒,因此此部分内容写到附录A。密集层减少了从BLSTM层接收到的矢量的维数。softmax层将从密集层接收到的低维向量作为输入,并负责表示和格式化分类结果,为学习阶段更新神经网络参数提供反馈。学习阶段的输出是具有微调模型参数的BLSTM神经网络,检测阶段的输出为分类结果。

III. VulDeePecker的设计

我们的目标是设计一个漏洞检测系统,该系统可以自动判断源代码中的给定程序是否存在漏洞,如果存在漏洞,还可以判断漏洞的位置。这应该在不要求人类专家手动定义特征和不产生高假阴性率的情况下实现(只要假阳性率合理)。在本节中,我们将介绍VulDeePecker的设计。我们首先讨论代码小工具的概念,因为它对程序的表示至关重要。然后,我们概述了VulDeePecker并详细介绍了其组件。

A. 定义代码小工具

为了以适合神经网络输入的向量表示程序,我们首先建议将程序转换为代码小工具的表示,其定义如下:

定义1:(代码小工具)代码小工具由许多程序语句(即代码行)组成,这些语句在数据依赖性或控制依赖性方面相互语义相关。

为了生成代码小工具,我们提出了关键点的启发式概念,关键点可以看作是一个“透镜”,通过它我们可以从某个角度表示程序。直观地看,关键点的启发式概念在某种意义上可以被视为漏洞的“中心”或暗示存在漏洞的代码段。 对于不恰当使用库/API函数调用而导致的漏洞,其关键点是库/API函数调用; 对于不正确使用数组导致的漏洞,关键是数组。需要注意的是,一类漏洞可能有多种关键点。例如,缓冲区错误漏洞可能与以下关键点相对应:库/API函数调用、数组和指针。此外,相同的关键点可能存在于多种类型的漏洞中。例如,缓冲区错误和资源管理错误漏洞都可能包含库/API函数调用的关键点。准确定义关键点的启发式概念超出了本文的范围,是一个值得未来研究的有趣问题;相反,我们将重点放在使用这个启发式概念作为“透镜”,使用深度学习来学习漏洞模式。

在本文中,我们重点关注使用库/API函数调用的特殊关键点来证明其在基于深度学习的漏洞检测中的有用性。这是由于观察到许多漏洞与库/API函数调用有关。研究其他类型关键点的有用性也是一项有趣的未来工作。

对应于库/API函数调用的关键点,代码小工具可以通过程序的数据流或控制流分析来生成,其中有众所周知的算法和易于使用的商业产品,如Checkmarx。值得一提的是,Checkmarx还根据人类专家手动定义的一些规则检测漏洞。然而,我们不使用其规则进行漏洞检测;相反,我们将对比VulDeePecker和Checkmarx的有效性。

B. VulDeePecker概述

如图2所示,VulDeePecker有两个阶段:学习(即训练)阶段和检测阶段。学习阶段的投入是大量的训练计划,其中一些是易受攻击的,另一些则不是。所谓“易受攻击”,是指一个程序包含一个或多个已知的漏洞。学习阶段的输出是脆弱性模式,这些模式被编码到BLSTM神经网络中。

(a)学习阶段

(b)检测阶段 图2. VulDeePecker概述:学习阶段生成漏洞模式,检测阶段使用这些漏洞模式来确定目标程序是否存在漏洞,如果存在,则确定漏洞的位置(即相应的代码小工具)。

1)学习阶段:如图2(a)所示,学习阶段有4个步骤。

第一步:提取库/API函数调用和相应的程序切片。这有两个子步骤,在下文中重点介绍,并在第III-C节中详细阐述。

  • 步骤I.1:从训练计划中提取库/API函数调用,同时注意当前版本的VulDeePecker重点关注与库/API功能调用关键点相关的漏洞。
  • 步骤I.2:为步骤I.1中提取的库/API函数调用的每个参数(或变量)提取一个或多个程序切片。在本文中,程序切片表示与库/API功能调用的参数语义相关的程序语句(即代码行),同时注意到,最初引入程序切片的概念是为了表示程序关于程序点或变量的语句。

第二步:生成训练程序的代码小工具及其基本真实标签。这一步骤有两个子步骤,在下文中重点介绍,并在第III-D节中详细阐述。

  • 第二步。1: 将步骤I.2中获得的程序切片组装成代码小工具,每个库/API函数调用一个代码小工具。代码小工具不一定对应于某些连续的代码行。相反,它由语义上相互关联的多行代码组成(即继承在这些程序切片中编码的语义关系)。

  • 第二步。2: 标记代码小工具的基本事实。此步骤将每个代码小工具标记为“1”(即易受攻击)或“0”(即不易受攻击的)。代码小工具的基本真实标签是可用的,因为我们知道训练计划是否易受攻击,如果易受攻击的话,我们也知道漏洞的位置。

第三步:将代码小工具转换为矢量表示。这一步骤有两个子步骤,下面将重点介绍,并在第III-E节中详细阐述。

  • 步骤III.1:将代码小工具转换为特定的符号表示,稍后将对此进行详细说明。此步骤旨在保留训练计划的一些语义信息。
  • 步骤III.2:将步骤III.1中获得的符号表示中的代码小工具编码为向量,这些向量是训练BLSTM神经网络的输入。一般来说,为了使用神经网络,这是必要的。

第四步:训练BLSTM神经网络。将代码小工具编码为向量并获得其基本真值标签后,学习BLSTM神经网络的训练过程是标准的。

2)检测阶段:给定一个或多个目标程序,我们从中提取库/API函数调用以及相应的程序片段,这些片段被组装成代码小工具。代码小工具被转换成它们的符号表示,这些符号表示被编码成向量,并用作训练的BLSTM神经网络的输入。网络输出哪些矢量以及哪些代码小工具易受攻击(“1”)或不易受到攻击(“0”)。如果代码小工具存在漏洞,它会在目标程序中确定漏洞的位置。如图2(b)所示,这个阶段有两个步骤。

第五步:将目标程序转换为代码小工具和向量。它有五个子步骤。

  • 步骤V.1:从目标程序中提取库/API函数调用(类似于步骤I.1)。

  • 步骤V.2:根据库/API函数调用的参数提取程序切片(类似于步骤I.2)。

  • 步骤V.3:将程序切片组装成代码小工具(类似于步骤II.1)。

  • 步骤V.4:将代码小工具转换为符号表示(类似于步骤III.1)。

  • 步骤V.5:将代码小工具的符号表示编码为向量(类似于步骤III.2)。

第六步:检测。这一步使用学习到的BLSTM神经网络对从目标程序中提取的代码小工具对应的向量进行分类。当向量被分类为“1”(即易受攻击)时,这意味着相应的代码小工具易受攻击,并且漏洞的位置被锁定。否则,相应的代码小工具被归类为“0”(即不易受攻击)。

以下小节分别阐述了步骤I-III。步骤IV和VI是标准步骤,步骤V类似于步骤I-III中的一些步骤。

C. 第一步:提取库/API函数调用和程序切片

1)步骤I.1:提取库/API函数调用:我们将库/API功能调用分为两类:前向库/API调用和后向库/ADI函数调用。正向库/API函数调用是直接从外部输入(如命令行、程序、套接字或文件)接收一个或多个输入的函数调用。例如,recv函数调用是向前库/API函数调用,因为它直接从套接字接收数据。向后库/API函数调用是不直接从程序运行的环境接收任何外部输入的函数调用。

图3. 说明从(训练)程序中提取库/API函数调用(步骤I.1),其中包含一个向后函数调用(即strcpy),该函数调用也用作示例来演示提取程序切片(步骤I.2)和将程序切片组装成代码小工具(步骤II.1)。

图3显示了向后库/API函数调用strcpy的示例(第9行)。它是向后库/API函数调用,因为它不直接接收任何外部输入。

我们强调向前和向后库/API函数调用之间的区别。对于前向库/API函数调用,受输入参数影响的语句至关重要,因为它们可能容易受到不正确(例如,精心编制的)参数值的影响;对于向后库/API函数调用,影响参数值的语句至关重要,因为它们可能使库/API功能调用易受攻击。这一发现将用于指导代码小工具向量表示的启发式填充。

2)步骤I.2:提取程序切片:此步骤生成与从训练程序中提取的库/API函数调用的参数相对应的程序切片。我们定义了两种切片:向前切片和向后切片,其中向前切片对应于受所讨论的参数影响的语句,向后切片对应于可能影响所讨论参数的语句。我们利用商业产品Checkmarx,更具体地说是它的数据依赖关系图,来提取这两种切片。基本思想如下:

  • 对于前向库/API函数调用中的每个参数,将生成一个或多个前向切片,后者对应于与参数相关的切片在库/API功能调用处或之后分支的情况。
  • 对于后向库/API函数调用中的每个参数,都会生成一个或多个后向切片,后一个切片对应于在库/API功能调用时或之前合并与该参数相关的多个切片的情况。

请注意,程序切片由多个语句组成,这些语句可能属于多个用户定义函数。也就是说,切片可以超出所讨论的用户定义函数的边界。

图3显示了一个包含库函数调用strcpy的示例程序,它有两个参数buf和str。由于strcpy是一个向后函数调用,因此对于它的每个参数,我们将生成一个向后切片。对于参数buf,切片由三条语句组成,即程序的第4、5和9行,它们属于用户定义的函数测试。对于参数str,切片由六条语句组成,即程序的第13、15、18、19、2和9行,其中前4行属于用户定义函数main,后2行属于用户自定义函数测试。这两个切片是链(即线性结构),因为Checkmarx使用链来表示切片,同时注意到切片也可以用树来表示。由于线性结构只能表示一个单独的切片,因此库/API函数调用通常对应于多个切片。

D. 第二步:提取代码小工具并标记其基本真实标签

1)步骤II.1:将程序切片组装成代码小工具:上一步生成的程序切片可以组装成代码小工具,如下所示。

首先,给定一个库/API函数调用和相应的程序切片,我们根据语句在用户定义函数中的出现顺序,将属于同一用户定义函数的语句(即代码段)组合成一个片段。如果有重复的语句,则会消除重复。

在图3所示的示例中,属于用户定义函数测试的三条语句(即第4、5和9行)组成了与参数buf对应的程序切片,属于用户自定义函数测试的两条语句(如第2和9行)都是与参数str对应的程序片。因此,我们需要将它们组装成一个整体,因为它们与相同的功能测试相关。根据这些语句在功能测试中出现的行号,这将导致2→ 4 → 5 → 9→ 9。由于第9行对应的语句是重复的,因此我们消除了重复,以派生出一段组合语句2→ 4 → 5 → 9,对应功能测试。

其次,将属于不同用户定义函数的语句组装到单个代码小工具中。如果属于这些用户定义函数的两条语句之间已经存在顺序,则保留此顺序;否则,使用随机顺序。

在图3所示的示例中,当组装属于用户定义函数main(即第13、15、18和19行)的语句片段和属于用户定义功能测试的语句片段(即第2、4、5和9行)时,我们得到13→ 15→ 18→ 19→ 2 → 4 → 5 → 9,它是与库函数调用strcpy相对应的代码小工具。此代码小工具保留了与参数str对应的程序切片中包含的用户定义函数的顺序。

2)步骤II.2:标记基本事实:每个代码小工具都需要标记为“1”(即易受攻击)和“0”(即不易受攻击的)。如果代码小工具对应于训练数据集中已知的漏洞,则标记为“1”;否则,标记为“0”。在第IV-C节中,我们将详细讨论在处理与特定漏洞数据源相关的程序时,如何标记基本事实。

E. 第三步:将代码小工具转换为向量

1)步骤III.1:将代码小工具转换为符号表示:这一步旨在启发性地在训练神经网络的程序中捕获一些语义信息。首先,删除非ASCII字符和注释,因为它们与漏洞无关。其次,以一对一的方式将用户定义的变量映射到符号名称(例如,“VAR1”、“VAR2”),同时注意当多个变量出现在不同的代码小工具中时,它们可能映射到相同的符号名称。第三,以一对一的方式将用户定义的函数映射到符号名称(例如,“FUN1”、“FUN2”),同时注意当多个函数出现在不同的代码小工具中时,它们可能映射到相同的符号名称。

图4.步骤III.1的说明:将代码小工具转换为符号表示

图4通过使用步骤II生成的代码片段突出显示了上述过程。如图3所示。

2)步骤III.2:将符号表示编码为向量:每个代码小工具需要通过其符号表示编码成向量。为此,我们通过词法分析将符号表示中的代码小工具划分为一系列标记,包括标识符、关键字、运算符和符号。例如,符号表示中的代码小工具,
“strcpy(VAR5,VAR2);”“strcpy(VAR5, VAR2); ” “strcpy(VAR5,VAR2);”
由7个标记序列表示:
“strcpy”,“(”,“VAR5”,“,”,“VAR2”,“)”,and“;”.“strcpy”, “(”, “VAR5”, “,”, “VAR2”, “)”, and “;”. “strcpy”,“(”,“VAR5”,“,”,“VAR2”,“)”,and“;”.
这导致了大量的语料库的标记。为了将这些标记转换为向量,我们使用了word2vec工具,之所以选择它,是因为它广泛用于文本挖掘。该工具基于分布式表示的思想,将令牌映射为整数,然后将其转换为固定长度向量。

由于代码小工具可能具有不同数量的标记,因此相应的向量可能具有不同的长度。由于BLSTM采用等长向量作为输入,我们需要进行调整。为此,我们引入一个参数τττ作为与代码小工具相对应的向量的固定长度。

  • 当向量小于τττ时,有两种情况:如果代码小工具是从后向切片生成的,或者是通过组合多个后向切片而生成的,我们在向量的开头填充零;否则,我们将零填充到向量的末尾。
  • 当一个向量大于τττ时,也有两种情况:如果代码小工具是由一个反向切片生成的,或由多个反向切片组合生成的,我们删除向量的开始部分;否则,删除向量的结束部分。

这确保了从向后切片生成的每个代码小工具的最后一条语句是库/API函数调用,而从向前切片生成的所有代码小工具中的第一条语句是一个库/API功能调用。因此,每个代码小工具都表示为τττ位向量。向量的长度与BLSTM每层的隐藏节点数有关,这是一个可以调整的参数,以提高漏洞检测的准确性(见第IV-C节)。

IV. 实验和结果

我们的实验集中在回答以下三个研究问题(RQ):

  • RQ1:VulDeePecker能否同时处理多种类型的漏洞?

    漏洞检测系统应该能够同时检测多种类型的漏洞,因为需要维护多种检测系统。为了回答这个问题,我们将进行涉及一种或多种类型漏洞的实验。

  • RQ2:人类专业知识(除定义功能外)能否提高VulDeePecker的效率?

    为了回答这个问题,我们将研究使用一些手动选择的库/API函数调用的有效性对比使用所有库/API功能调用的效果。

  • RQ3:与其他漏洞检测方法相比,VulDeePecker的有效性如何?

    为了回答这个问题,我们将VulDeePecker与其他方法进行比较,包括一些静态分析工具和基于代码相似性的漏洞检测系统。

A. 评估漏洞检测系统的指标

我们使用广泛使用的指标假阳性率(FPRFPRFPR)、假阴性率(FNRFNRFNR)、真阳性率或召回率(TPRTPRTPR)、精度(PPP)和F1F1F1度量(F1F1F1)来评估漏洞检测系统。设TPTPTP为正确检测到漏洞的样本数,FPFPFP为检测到虚假漏洞的样本数量,FNFNFN为未检测到真实漏洞的样本数目,TNTNTN为未检测出漏洞的样本数目。假阳性率指标FPR=FPFP+TNF P R=\frac{\mathrm{FP}}{\mathrm{FP}+\mathrm{TN}}FPR=FP+TNFP​衡量了假阳性漏洞与非漏洞样本总体的比率。假阴性率指标FNR=FNTP+FNF N R=\frac{\mathrm{FN}}{\mathrm{TP}+\mathrm{FN}}FNR=TP+FNFN​衡量了假阴性漏洞与漏洞样本总体的比率。真阳性率或召回指标TPR=TPTP+FNTPR=\frac{\mathrm{TP}}{\mathrm{TP}+\mathrm{FN}}TPR=TP+FNTP​衡量了真阳性漏洞与漏洞样本总体的比率, 同时注意TPR=1−FNRT P R=1− F N RTPR=1−FNR。精度度量P=TPTP+FPP=\frac{\mathrm{TP}}{\mathrm{TP}+\mathrm{FP}}P=TP+FPTP​测量检测到的漏洞的正确性。F1F1F1度量指标F1=2⋅P⋅TPRP+TPRF 1=\frac{2 \cdot P \cdot T P R}{P+T P R}F1=P+TPR2⋅P⋅TPR​考虑了精度和真阳性率。

理想的情况是,漏洞检测系统既不会遗漏漏洞(即FNR≈0F N R≈ 0FNR≈0和TPR≈1T P R≈ 1TPR≈1) 也不会触发错误报警(即FPR≈0F P R≈ 0FPR≈0和P≈1P≈ 1P≈1) ,即F1≈1F 1≈ 1F1≈1。然而,这在实践中很难实现,常常迫使一方以一个指标的有效性换取另一个指标中的有效性。在本研究中,我们倾向于实现低FNRFNRFNR和低FPRFPRFPR。

B. 准备VulDeePecker的输入

收集程序。NIST维护的漏洞数据有两个广泛使用的来源:NVD(包含生产软件中的漏洞)和SARD项目(包含生产、合成和学术安全缺陷和漏洞)。在NVD中,每个漏洞都有一个唯一的常见的漏洞和曝光标识符(CVE ID)和一个 常见的弱点枚举标识符(CWE ID),用于指示相关漏洞的类型。我们收集包含一个或多个漏洞的程序。在SARD中,每个程序(即测试用例)对应一个或多个CWE ID,因为一个程序可能有多种类型的漏洞。因此,将收集具有一个或多个CWE ID的程序。

在本文中,我们重点关注两种类型的漏洞:缓冲区错误(即CWE-119)和资源管理错误(即,CWE-399),每种漏洞都有多个子类型。这些漏洞非常常见,这意味着我们可以收集足够的数据来进行深入学习。我们选择了19种流行的C/C++开源产品,包括Linux内核、Firefox、Thunderbird、Seamonkey、Firefox-esr、Thunder bird esr、Wireshark、FFmpeg、Apache Http Server、Xen、OpenSSL、Qemu、Libav、Asterisk、Cups、Freetype、Gnutls、Libvirt和VLC媒体播放器,根据NVD,这些产品包含这两种类型的漏洞。我们还收集了SARD中包含这两类漏洞的C/C++程序。我们总共收集了NVD 520个与缓冲区错误漏洞相关的开源软件程序和320个与资源管理错误漏洞有关的开源软件软件程序;我们还收集了SARD 8122个与缓冲区错误漏洞相关的程序(即测试用例)和1729个与资源管理错误漏洞有关的程序。请注意,包含漏洞的程序实际上可能包含多个程序文件。

训练程序对比目标程序。我们随机选择80%的程序作为训练程序,剩下的20%作为目标程序。在处理一种或两种类型的漏洞时,此比率同样适用。

C. 训练BLSTM神经网络

这对应于VulDeePecker的训练阶段。我们使用Theano和Keras在Python中实现BLSTM神经网络。我们在NVIDIA GeForce GTX 1080 GPU和Intel Xeon E5-1620 CPU以3.50GHz工作的机器上运行实验。

第一步:提取库/API函数调用和相应的程序切片。 我们从程序中提取C/C++库/API函数调用。有6045个C/C++库/API函数调用,涉及标准库函数调用、基本Windows API和Linux内核API函数调用。总共,我们从程序中提取了56902个库/API函数调用,包括7255个向前函数调用和49647个向后函数调用。

为了回答RQs,我们还手动选择了124个与缓冲区错误漏洞(CWE-119)相关的C/C++库/API函数调用(包括带通配符的函数调用)和16个与资源管理错误漏洞相关的C/C++库/API功能调用(CWE-399)。之所以选择这些函数调用,是因为前面提到的商业工具Checkmarx使用人类专家编写的规则声称它们与这两种类型的漏洞有关。这些函数调用的列表参见附录B中的表VII。相应地,我们从训练计划中提取了40351个库/API函数调用,包括4012个向前函数调用和36339个向后函数调用。对于库/API函数调用的每个参数,提取一个或多个程序切片。

第二步。1: 生成代码小工具。代码小工具是从程序切片生成的。我们获得了一个包含61638个代码小工具的代码小工具数据库(CGD),其中48744个代码小工具是从训练程序的程序片生成的,12894个代码小工具是从目标程序的程序段生成的。生成小工具的时间复杂度主要取决于数据流分析工具。例如,从SARD随机选择的100个程序(99232行)中生成2494个代码小工具需要883秒,这意味着每个代码小工具平均需要354毫秒。为了回答上述RQs,我们使用CGD得出以下6个数据集。

  • BE-ALL:对应于缓冲区错误漏洞(CWE-119)和所有库/API函数调用(即,在没有人工专家的情况下提取)的CGD子集。
  • RM-ALL:对应于资源管理错误漏洞(CWE-399)和所有库/API函数调用的CGD子集。
  • HY-ALL:与缓冲区错误漏洞(CWE-119)和资源管理错误漏洞(GWE-399)以及ALL库/API函数调用的混合(即两者)相对应的CGD子集。也就是说,它与CGD相同。
  • BE-SEL:对应于缓冲区错误漏洞(CWE-119)和手动选择函数调用(而不是所有函数调用)的CGD子集。
  • RM-SEL:对应于资源管理错误漏洞(CWE-399)和手动选择函数调用的CGD子集。
  • HY-SEL:与缓冲区错误漏洞(CWE-119)和资源管理错误漏洞(GWE-399)以及手动选择的函数调用的HYbrid相对应的CGD子集。

表I总结了这些数据集中代码小工具的数量。

表I. 回答RQS的数据集

第二步。2: 标记代码小工具。代码小工具的标签如下。 对于从NVD的程序中提取的代码小工具,我们重点关注补丁涉及行删除或修改的漏洞。这个过程有两个步骤。在第一步中,如果代码小工具至少包含一条根据修补程序删除或修改的语句,则会自动标记为“1”(即易受攻击),否则会标记为“0”(即不易受到攻击)。然而,这个自动过程可能会将一些不易受攻击的代码小工具错误标记为“1”。为了删除这些错误标签,第二步是手动检查标记为“1”的代码小工具,以便更正错误标签(如果有)。

回想一下,SARD中的每个程序都已经用相应的CWE ID标记为好(即没有安全缺陷)、坏(即包含安全缺陷)或混合(即包含有安全缺陷的函数及其修补版本)。对于从与SARD相关的程序中提取的代码小工具,从好程序中提取出来的代码小工具标记为“0”(即不易受攻击),如果从坏程序或混合程序中提取出的代码小工具包含至少一个易受攻击语句,则标记为“1”(即易受攻击的),否则标记为“零”。由于我们在SARD程序的标记过程中使用了启发式方法,我们查看了1000个随机代码小工具的标签,发现其中只有6个(即0.6%)贴错标签。这些标记错误的示例是由于这样一个事实造成的,即一段不易受攻击的代码中的语句与一段易受攻击代码中的语句相同。由于标记错误的代码小工具很少,神经网络对一小部分标记错误的样本具有鲁棒性,因此没有必要手动检查为SARD程序提取的代码小工具的所有标签。

可能会遇到这样的情况,即同一代码小工具标记为“1”和“0”(即标签冲突)。造成这种现象的原因之一是数据流分析工具的不完善。在这种情况下,我们只需删除这些代码小工具。因此,17725个代码小工具标记为“1”,43913个代码小工具标记为“0”。在17725个标记为“1”的代码小工具中,10440个代码小工具对应缓冲区错误漏洞,7285个代码小工具对应资源管理错误漏洞。表I显示了易受攻击的代码小工具的数量(第3列),以及每个数据集中不易受攻击代码小工具(第4列)的数量。

第三步:将代码小工具转换为向量。CGD总共包含6166401个令牌,其中23464个不同。在将用户定义的变量名和函数名映射到一些符号名之后,不同符号的数量进一步减少到10480。这些符号表示被编码到向量中,作为训练BLSTM神经网络的输入。

第四步:训练BLSTM神经网络。对于表I中描述的每个数据集,我们采用10倍交叉验证来训练BLSTM神经网络,并选择与漏洞检测有效性相对应的最佳参数值。例如,我们改变每个BLSTM神经网络的隐藏层数量,并观察对结果F1F1F1测量的影响。当我们调整隐藏层的数量和这些默认值可用时,我们将参数设置为其默认值,并将参数设置成深度学习社区广泛使用的值。代码小工具矢量表示中的令牌数设置为50,dropout设置为0.5,批量大小设置为64,周期数设置为4,使用小批量随机梯度下降和ADAMAX进行训练,默认学习率为1.0,并选择300个隐藏节点。

图5. 具有不同隐藏层数的6个数据集的VulDeePecker的F1度量

图5绘制了VulDeePecker的F1F1F1测量值,涉及6个具有不同隐藏层数量的数据集,每个数据集都会导致不同的神经网络。我们观察到,6个BLSTM神经网络的F1F1F1测量值在2或3层达到最大值,并且当层数大于6时,大多数BLSTM网络的F1F1F1测量值都会下降。请注意,BLSTM神经网络的其他参数可以以类似的方式调整。

D. 实验结果与启示

1)回答RQ1的实验:为了测试VulDeePecker是否可以应用于多种类型的漏洞,我们在三个数据集上进行了实验:BE-ALL、RM-ALL和HY-ALL。这分别生成三个神经网络,其有效性见表II。

表II. 回答RQ1的结果表明,VULDEEPECKER可以检测多种类型的漏洞。

我们观察到,从所有五个指标来看,从RMALL数据集训练的神经网络优于从BE-ALL数据集训练出来的神经网络。这可以通过以下事实来解释:与资源管理错误漏洞相关的库/API函数调用的数量(即16个)远远小于与缓冲区错误漏洞相关联的库/AAPI函数调用的数目(即124个)。我们还观察到,就FPRFPRFPR和PPP度量而言,从HY-ALL数据集训练的神经网络不如从BE-ALL或RM-ALL数据集训练出的神经网络好。我们进一步观察到,从HY-ALL数据集训练的神经网络的TPRTPRTPR和FNRFNRFNR介于从RM-ALL数据集训练出的神经网络和从BE-ALL数据集中训练出来的神经网络之间。从HY-ALL数据集训练的神经网络的F1F1F1测量值比从BE-ALL数据集训练出的神经网络低1.2%,比从RM-ALL数据集中训练出的网络低9.6%。这可以通过以下事实来解释:与混合数据集漏洞相关的库/API函数调用的数量(即140)大于与单一类型漏洞相关的库/API函数的调用数量。我们推测这是由以下原因造成的:为大量与漏洞相关的库/API函数调用提取漏洞模式比为少量与漏洞相关联的库/API函数调用提取漏洞模式更困难。

表III总结了与HY-ALL数据集相对应的训练时间和检测时间,其中第二列表示用于训练的代码小工具数量(即从训练程序中提取的),第三列表示用于检测的代码小工具数量(即从目标程序中提取)。我们观察到VulDeePecker的训练时间,正如深度学习技术的一般情况那样大,但检测时间很短。

表III:训练和检测的时间复杂度

总之,我们肯定地回答了RQ1,如下所示:

见解1:VulDeePecker可以同时检测多种类型的漏洞,但其有效性对与漏洞相关的库/API函数调用数量敏感(即越少越好)。

2) 回答RQ2的实验:为了回答VulDeePecker是否可以通过结合人类专业知识进行改进,我们使用自动提取的所有库/API函数调用进行实验对比使用Checkmarx人类专家编写的漏洞规则指导下手动选择的一些库/API功能调用。

表IV. 回答RQ2的结果表明,使用手动选择的库/API函数调用可以提高Vuldepecker的效率。

如IV所示,HY-SEL数据集训练的BLSTM网络比从HY-ALL数据集训练的BLSTM网络更有效。虽然FPRFPRFPR的改进很小(0.2%),但其他每个指标的改进都是实质性的:FNRFNRFNR和TPRTPRTPR为10%,PPP为5%,F1F1F1测量值为7.5%。此外,表III显示,使用手动选择的库/API函数调用的训练时间可能小于使用所有库/API功能调用的训练,因为需要处理的代码小工具数量较少。这导致了以下关于人类专业知识在提高基于深度学习的漏洞检测有效性方面的有用性的初步理解:

见解2:可以使用人类专业知识来选择库/API函数调用,以提高VulDeePecker的有效性,尤其是F1F1F1度量值的整体有效性。

3)回答RQ3的实验:为了回答RQ3,我们将VulDeePecker与其他基于模式和基于代码相似性的漏洞检测系统的有效性进行了比较。我们在此报告了它们在检测缓冲区错误漏洞(即BE-SEL数据集)方面的有效性比较,同时注意到,在比较它们在检测资源管理错误漏洞(如RM-SEL数据集中)方面的效率时,也观察到了类似的现象——由于空间不足,省略了细节。

为了与其他使用人类专家定义的规则的基于模式的漏洞检测系统进行比较,我们考虑了一个名为Checkmarx的商业产品和两个名为Flawfinder和RATS的开源工具。之所以选择这些系统,是因为我们可以使用它们,而且据我们所知,它们已经被广泛使用。为了与基于代码相似性的漏洞检测系统(主要针对克隆导致的漏洞)进行比较,我们考虑了两个最先进的系统,称为VUDDY和VulPecker。我们使用VUDDY的开放服务,并使用其作者提供给我们的VulPecker的原始实现。为了公平比较,我们需要解决一些微妙的问题。我们观察到VulPecker使用diff作为输入,其中diff描述了易受攻击的代码段与其修补版本之间的差异,我们将目标程序的BE-SEL数据集分为两个子集,即BE-SEL-NVD(266个样本来自NVD)和BE-SEL-SARD(其余样本来自SARD)。我们使用BE-SEL-NVD进行比较研究,因为VUDDY和VulPecker设计用于检测具有CVE ID的漏洞或具有差异的漏洞,但无法检测BE-SEL-SARD中的漏洞。

表V. 回答RQ3的结果:VULDEEPECKER获得了非常小的总体FNR,7.0%,对应于整个BE-SEL数据集(较大的FNR为16.9%,对应于从NVD导出的较小子数据集,较小的FNR为5.1%,对应于从SARD导出的子数据集),同时注意到,5.7%的总体FPR相当小。“N/C”表示系统无法检测相应数据集中的漏洞。

表五总结了比较结果。我们提出以下意见。首先,VulDeePecker大大优于其他基于模式的漏洞检测系统,因为VulDee Pecker的FPRFPRFPR为5.7%,FNRFNRFNR为7.0%,分别比其他检测系统中的对应系统小得多。通过查看其他系统,我们发现Flawfinder和RATS不使用数据流分析,因此漏掉了许多漏洞。尽管Checkmarx确实使用了数据流分析,但其识别漏洞的规则是由人类专家定义的,还远远不够完善。这进一步强调了将人类专家从繁琐的任务中解脱出来的重要性(类似于手动定义特征的任务)。这一观察结果导致:

见解3:利用数据流分析,基于深度学习的漏洞检测系统可以更加有效。(这暗示我们可以推测,通过利用控制流分析,系统可以更加有效。验证或推翻这种推测是一项有趣的未来工作。)

其次,对于BE-SEL-NVD子数据集,VUDDY和VulPecker以高FNR(分别为95.1%和89.8%)换取低FPR(分别为0%和1.9%),这导致F1F1F1测量值非常低(分别为9.3%和18.2%)。大型FNRsFNRsFNRs可以用以下事实来解释:VUDDY只能检测与功能相关的漏洞,这些漏洞与训练计划中的漏洞函数几乎相同(即i类和II类代码克隆造成的漏洞);VulPecker只能检测由类型I、类型II和某些类型III代码克隆(例如,语句的删除、插入和重新排列)引起的漏洞,这解释了为什么VulPeccer的FNRFNRFNR低于VUDDY。然而,这些系统无法检测不是由代码克隆引起的漏洞,这解释了为什么它们会导致高FNRFNRFNR。

VulDeePecker相对于BE-SEL-NVD子数据集的高FPRFPRFPR和FNRFNRFNR不应用作针对VulDee Pecker的证据,因为对于BE-SEL-SARD子数据集,VulDee-Pecker产生的FPRFPRFPR更小,为3.4%,FNRFNRFNR为5.1%,同时注意到VUDDY和VulPecker不适用(即无法检测此子数据集中的漏洞)。此外,VulDeePecker在整个BE-SEL数据集中的FPRFPRFPR为5.7%,FNRFNRFNR为7.0%,这是更实际的情况,因为我们将使用实践中可用的所有数据。

因此,可以公平地说,VulDeePecker大大优于两个最先进的基于代码相似性的漏洞检测系统,简单地因为VulDeePecker在整个数据集上的FPRFPRFPR为5.7%,FNRFNRFNR为7.0%。然而,需要注意的是,基于深度学习的漏洞检测在很大程度上依赖于数据量。这将导致:

见解4:VulDeePecker比基于代码相似性的漏洞检测系统更有效,后者无法检测非代码克隆引起的漏洞,因此通常会导致较高的误报率。然而,VulDeePecker的有效性对数据量很敏感,这似乎是深度学习的本质所固有的。

在实践中使用VulDeePecker。为了进一步展示VulDeePecker的有用性,我们收集了3种软件产品的20个版本:Xen、Seamonkey和Libav。这些产品与上述目标计划不同。我们使用VulDeePecker和其他漏洞检测系统来检测这些软件产品中的漏洞。如表VI所示,VulDeePecker检测到4个尚未在NVD中发布的漏洞。我们手动检查并确认了这些漏洞,发现它们已针对其他产品发布,并且产品供应商已在后续版本中“悄悄”修补。相比之下,上述几乎所有其他漏洞检测系统都没有检测到这些漏洞,除了Flawfinder检测到与CVE-2015-4517相对应的漏洞,而没有检测到其他三个漏洞。

表VI. VULDEEPECKER在3种产品中检测到4种漏洞,这些产品未在NVD中发布,但在这些产品的最新版本中,供应商已“悄悄”修补。除了FLAWFINDER只检测到一个漏洞而没有检测到其他三个漏洞之外,其他漏洞检测系统完全没有检测到这些漏洞。

V. 局限性

VulDeePecker的当前设计、实现和评估有几个局限性,这为未来的研究提出了有趣的开放问题。

首先,VulDeePecker的当前设计仅限于通过假设程序源代码可用来处理漏洞检测。检测可执行文件中的漏洞是一个不同且更具挑战性的问题。

其次,目前的VulDeePecker设计只处理C/C++程序。需要进行进一步的研究,以使其适应其他类型的编程语言。

第三,目前的VulDeePecker设计仅处理与库/API函数调用相关的漏洞。我们将研究如何利用上述其他类型的关键点来检测其他类型的漏洞。

第四,VulDeePecker的当前设计仅适用于数据流分析(即数据依赖),而不适用于控制流分析(如控制依赖),尽管代码小工具的概念可以适用于数据依赖和控制依赖。未来的一项重要工作是改进数据流分析的杠杆作用,并适应控制流分析,以增强漏洞检测能力。

第五,VulDeePecker目前的设计在标记代码小工具的基本真相方面使用了一些启发式方法,将代码小工具转换为其符号表示,将代码小工具的可变长度矢量表示转换为固定长度矢量。虽然直观,但需要进行进一步的研究,以确定这些启发式方法对VulDeePecker有效性的影响。

第六,目前VulDeePecker的实现仅限于BLSTM神经网络。我们计划用其他类型的神经网络进行系统实验,这些神经网络可以用于漏洞检测。

第七,目前对VulDeePecker的评估是有限的,因为数据集仅包含缓冲区错误漏洞和资源管理错误漏洞。我们将对所有可用类型的漏洞进行实验。尽管我们针对3种软件产品(即Xen、Seamonkey和Libav)进一步测试了VulDeePecker,发现了4个漏洞,这些漏洞在NVD中没有报告,并且在发布这些产品的更高版本时由供应商“无声”修补,但这些漏洞是已知的,而不是0天的漏洞。需要对更多软件产品进行大量实验,以检查VulDeePecker是否有能力检测0天漏洞。原则上,这是可能的,因为VulDeePecker使用基于模式的方法。

VI. 相关工作

我们将相关的前期工作分为两类:漏洞检测(与本文目的相关)和程序分析(与漏洞检测方法相关)。

A. 漏洞检测方面的前期工作

基于模式的方法。这种方法可以进一步分为三类。在第一类中,模式是由人类专家手动生成的(例如,开源工具Flawfinder、RATS和ITS4、商业工具Checkmarx、Fortify和Coverity)。这些工具往往有较高的假阳性率或假阴性率。在第二类中,模式是根据预先分类的漏洞半自动生成的(例如,缺失检查漏洞、污点式漏洞、 和信息泄露漏洞)并且模式则是特定于一种类型的漏洞。在第三类中,模式是由类型不可知的漏洞半自动生成的(即无需将其预先分类为不同类型)。这些方法使用机器学习技术,这些技术依赖于人类专家定义特征来描述漏洞。此外,这些方法无法确定漏洞的精确位置,因为程序以粗粒度表示(例如,程序、包、组件、文件和函数)。

VulDeePecker属于基于模式的漏洞检测方法。与上述研究相比,VulDeePecker有两个优点。首先,它不需要人类专家来定义区分漏洞代码和非漏洞代码的特征。其次,它使用细粒度粒度表示程序,因此可以确定漏洞的精确位置。

基于代码相似性的方法。这种方法有三个步骤。第一步是将程序划分为一些代码片段。第二步是以抽象的方式表示每个代码片段,包括标记、树和图。第三步是通过在第二步中获得的抽象表示来计算代码片段之间的相似性。

与任何基于模式的漏洞检测方法(包括VulDeePacker)相比,基于代码相似性的方法的优点是,一个易受攻击的代码实例足以检测目标程序中的相同漏洞。但它只能检测I型和II型代码克隆(即相同或完全相同的代码克隆)以及一些III型代码克隆(如删除、插入和重新排列语句)中的漏洞。为了实现更高的漏洞检测效率,人类专家需要定义特征,以便为不同类型的漏洞自动选择正确的代码相似性算法。然而,即使是具有专家定义功能的增强方法也无法检测到不是由代码克隆引起的漏洞。相比之下,VulDeePecker可以自动检测可能或不可能由代码克隆引起的漏洞(即不需要人工专家定义功能)。

B. 与使用深度学习进行程序分析相关的前期工作

据我们所知,我们是第一个使用深度学习来检测软件漏洞的公司,这是受到深度学习在图像处理、语音识别和自然语言处理方面的成功启发。为了使用深度学习来检测软件漏洞,程序需要用向量表示。为此,有两种方法。一种是将从程序中提取的标记(如数据类型、变量名、函数名和关键字)映射到向量;另一种是将从程序中提取的抽象语法树的节点(例如函数定义、函数调用、标识符声明和控制流节点)映射到向量。VulDeePecker将从代码小工具提取的标记映射到向量,同时考虑到代码小工具中的代码行不一定是连续的。

一些相关的工作是使用深度学习进行软件缺陷预测。然而,软件缺陷与软件漏洞不同(即检测缺陷的方法通常不能用于检测漏洞)[54]中程序的文件级表示过于粗糙,无法确定漏洞的位置。此外,[63]中提出的缺陷预测方法面向代码更改,而不是整个目标程序。远程相关工作是将深度学习用于软件语言建模、代码克隆检测、API学习、二进制函数边界识别、恶意URLs、文件路径检测和注册表项检测等目的。

VII. 结论

我们介绍了VulDeePecker,这是第一个基于深度学习的漏洞检测系统,旨在将人类专家从手动定义特征的繁琐和主观工作中解脱出来,并减少其他漏洞检测系统产生的误报。由于深度学习是为与漏洞检测截然不同的应用程序而发明的,因此我们提出了一些初步原则,用于指导将深度学习应用于漏洞检测的实践。这些原则应该进一步完善,因为深度学习在解决漏洞检测问题方面具有巨大潜力。我们已经收集并公开了一个有用的数据集,用于评估VulDeePecker和其他将在未来开发的基于深度学习的漏洞检测系统的有效性。系统实验表明,VulDeePecker可以实现比其他漏洞检测系统低得多的漏报率,同时减轻了人类专家手工定义特征的繁琐工作。对于我们试验的3种软件产品(即Xen、Seamonkey和Libav),VulDeePecker检测到4个漏洞,这些漏洞未在NVD中报告,并且在供应商发布这些产品的更高版本时,它们“无声”地进行了修补。相比之下,其他检测系统几乎漏掉了所有这些漏洞,只有一个系统检测到其中一个漏洞,漏掉了其他三个漏洞。

未来研究的开放问题很多,包括第五节讨论的当前研究的局限性。特别是,准确描述基于深度学习的漏洞检测的能力和局限性是一个令人兴奋的研究问题。

致谢

我们感谢匿名评论员的评论,他们的评论帮助我们改进了这篇文章,感谢马库斯·彭德尔顿校对了这篇论文。本论文得到了国家基础研究计划(973计划)(批准号2014CB340600)、国家科学基金(批准号61672249)、深圳市基础研究项目(批准号JCYJ20170413114215614)和河北省自然科学基金(授予号F2015201089)的资助。徐寿怀的部分支持来自NSF拨款1111925号和ARO拨款W911NF-17-10566号。本材料中表达的任何意见、调查结果、结论或建议均为作者的意见,并不反映资助机构的意见。

附录

A. LSTM核

BLSTM神经网络中的BLSTM层包含一个称为LSTM核的复杂结构,下面简要介绍这些结构,更多详细信息请参阅[22]。

设⊙\odot⊙表示以元素方式相乘,tanhtanhtanh表示双曲正切函数exp⁡(x)−exp⁡(−x)exp⁡(x)+exp⁡(−x)\frac{\exp (x)-\exp (-x)}{\exp (x)+\exp (-x)}exp(x)+exp(−x)exp(x)−exp(−x)​,σσσ表示sigmoidsigmoidsigmoid函数11+exp⁡(−x)\frac{1}{1+\exp (-x)}1+exp(−x)1​。

每个LSTM核(用ccc表示)使用输入门iii(即输入数据)、遗忘门fff(即单元的状态流)和输出门ooo(即模块的输出)来控制通过神经网络的数据流。lll层在ttt时刻的输出htlh_{t}^{l}htl​为:
htl=otl⊙tanh⁡(ctl),h_{t}^{l}=o_{t}^{l} \odot \tanh \left(c_{t}^{l}\right), htl​=otl​⊙tanh(ctl​),
   其中,时间ttt时层lll的输出门otlo_{t}^{l}otl​为:
otl=σ(Wxolxtl+Wholht−1l+Wcolctl+bol)o_{t}^{l}=\sigma\left(\boldsymbol{W}_{x o}^{l} x_{t}^{l}+\boldsymbol{W}_{h o}^{l} h_{t-1}^{l}+\boldsymbol{W}_{c o}^{l} c_{t}^{l}+b_{o}^{l}\right) otl​=σ(Wxol​xtl​+Whol​ht−1l​+Wcol​ctl​+bol​)
   时间ttt时层lll的LSTM核ctlc_{t}^{l}ctl​的状态为:
ctl=ftl⊙ct−1l+itl⊙tanh⁡(Wxclxtl+Whclht−1l+bcl).c_{t}^{l}=f_{t}^{l} \odot c_{t-1}^{l}+i_{t}^{l} \odot \tanh \left(\boldsymbol{W}_{\boldsymbol{x c}}^{l} \boldsymbol{x}_{t}^{l}+\boldsymbol{W}_{\boldsymbol{h c}}^{l} \boldsymbol{h}_{t-1}^{l}+\boldsymbol{b}_{c}^{l}\right). ctl​=ftl​⊙ct−1l​+itl​⊙tanh(Wxcl​xtl​+Whcl​ht−1l​+bcl​).
   时间ttt时层lll的遗忘门ftlf_{t}^{l}ftl​和输入门itli_{t}^{l}itl​计算如下:
ftl=σ(Wxflxtl+Whflht−1l+Wcflct−1l+bfl),itl=σ(Wxilxtl+Whilht−1l+Wcilct−1l+bil),\begin{aligned}f_{t}^{l} &=\sigma\left(\boldsymbol{W}_{x f}^{l} x_{t}^{l}+W_{h f}^{l} h_{t-1}^{l}+W_{c f}^{l} c_{t-1}^{l}+b_{f}^{l}\right), \\i_{t}^{l} &=\sigma\left(W_{x i}^{l} x_{t}^{l}+W_{h i}^{l} h_{t-1}^{l}+W_{c i}^{l} c_{t-1}^{l}+b_{i}^{l}\right),\end{aligned} ftl​itl​​=σ(Wxfl​xtl​+Whfl​ht−1l​+Wcfl​ct−1l​+bfl​),=σ(Wxil​xtl​+Whil​ht−1l​+Wcil​ct−1l​+bil​),​
   其中xtlx_{t}^{l}xtl​是l−1l− 1l−1层(l>1)(l>1)(l>1)的输入或网络输入(l=1)(l=1)(l=1),WxilW_{x i}^{l}Wxil​, WxflW_{x f}^{l}Wxfl​, WxolW_{x o}^{l}Wxol​, WxclW_{x c}^{l}Wxcl​是连接xtlx_{t}^{l}xtl​与输入门、遗忘门、输出门和LSTM核输入的权重矩阵,WhilW_{h i}^{l}Whil​, WhflW_{h f}^{l}Whfl​, WholW_{h o}^{l}Whol​, WhclW_{h c}^{l}Whcl​是连接ht−1lh_{t-1}^{l}ht−1l​的带有输入门、遗忘门、输出门和LSTM核输入的权重矩阵,bilb_{i}^{l}bil​, bflb_{f}^{l}bfl​, bolb_{o}^{l}bol​, bclb_{c}^{l}bcl​是输入门、遗忘门、输出门和LSTM核输入的偏置项。

B. Checkmarx选择的库/API函数调用

表VII总结了与两类漏洞(缓冲区错误(CWE119)和资源管理错误(CWE-399))相关的C/C++库/API函数调用,其中“∗*∗”表示通配符。这些库/API函数调用由商业产品Checkmarx生成。

表VII. 与两类漏洞相关的库/API函数调用


总结

到此为止,关于本论文的中文翻译就告一段落了。其中论文的参考文献部分并没有翻译,因为这个翻译的价值不大,其余别的内容都原封不动的翻译为了中文。通过这篇论文的翻译,不仅学习到了专业知识,更重要的是提升了自身阅读英文文献的能力,共勉!

论文中文翻译——VulDeePecker: A Deep Learning-Based System for Vulnerability Detection相关推荐

  1. 论文阅读笔记——VulDeePecker: A Deep Learning-Based System for Vulnerability Detection

    本论文相关内容 论文下载地址--Engineering Village 论文中文翻译--VulDeePecker: A Deep Learning-Based System for Vulnerabi ...

  2. 论文详读:LEMNA: Explaining Deep Learning based Security Applications

    我以我ppt的内容顺序介绍一下这篇论文,希望有错误的地方大家可以帮我指出嘻嘻 1.论文出处 论文名:LEMNA: Explaining Deep Learning based Security App ...

  3. 论文中文翻译——SySeVR A Framework for Using Deep Learning to Detect Software Vulnerabilities

    本论文相关内容 论文下载地址--Web Of Science 论文中文翻译--SySeVR A Framework for Using Deep Learning to Detect Software ...

  4. 论文翻译七:Adversarial Transfer Learning for Deep Learning Based Automatic Modulation Classification

    30天挑战翻译100篇论文 坚持不懈,努力改变,在翻译中学习,在学习中改变,在改变中成长- Adversarial Transfer Learning for Deep Learning Based ...

  5. 论文中文翻译——Automated Vulnerability Detection in Source Code Using Deep Representation Learning

    本论文相关内容 论文下载地址--Web Of Science 论文中文翻译--Automated Vulnerability Detection in Source Code Using Deep R ...

  6. 论文翻译:2021_语音增强模型压缩_Towards model compression for deep learning based speech enhancement...

    论文地址:面向基于深度学习的语音增强模型压缩 论文代码:没开源,鼓励大家去向作者要呀,作者是中国人,在语音增强领域 深耕多年 引用格式:Tan K, Wang D L. Towards model c ...

  7. 【论文学习笔记】《A Review of Deep Learning Based Speech Synthesis》

    基于深度学习的语音合成综述论文学习 文章目录 基于深度学习的语音合成综述论文学习 1 简介 2 语音合成概述 2.1 语音合成概念 2.2 语音合成发展历史 2.3 传统语音合成技术 2.3.1 拼接 ...

  8. 论文中文翻译——A deep tree-based model for software defect prediction

    本论文相关内容 论文下载地址--Web Of Science 论文中文翻译--A deep tree-based model for software defect prediction 论文阅读笔记 ...

  9. 【论文笔记】Multi-task deep learning based CT imaging analysis for COVID-19 pneumonia: Classification and

    声明 不定期更新自己精度论文,通俗易懂,初级小白也可以理解 涉及范围:深度学习方向,包括 CV.NLP.Data Fusion.Digital Twin 论文标题:Multi-task deep le ...

最新文章

  1. php图形图像,php图形图像处理
  2. 网络安全-NTFS权限和445文件共享
  3. DNN结构演进History—CNN( 优化,LeNet, AlexNet )
  4. how is Java Bean object created
  5. 学习使用Whally GraalVM!
  6. Java JNI初探
  7. spring注解工具类AnnotatedElementUtils和AnnotationUtils
  8. java ocr linux_linux系统如何使用tess4j(java)进行ocr图片文字识别
  9. CDH-5.13.1离线安装教程
  10. Java 数组转字符串
  11. Docker系列(一)安装
  12. 10大黑客专用的 Linux 操作系统...
  13. access百科 pc_Access是什么
  14. snownlp 原理_情感分析snownlp包部分核心代码理解
  15. 微信公众平台开发实战Java版之如何网页授权获取用户基本信息
  16. U盘拷贝大文件提示文件过大无法拷贝解决方案
  17. python库numpy使用技巧(一)——提取数组中非零元素
  18. 频数直方图的步骤_《频数直方图》PPT课件
  19. 堆与栈区别,以及分配内存的快慢
  20. mbed TLS 概述

热门文章

  1. python生成带背景的字符图片(crnn数据集制作)
  2. NoteExpress 报错该属性无法用于那个对象 (已解决)
  3. 串口的认识(COM接口)
  4. 2023最新爱蜗影视优码双端影视源码+支持代理/在线支付
  5. JAVA开发(JAVA架构师成长之路)
  6. C语言——gotoxy()函数
  7. turtle库使用教程
  8. android 通过手机号码查询联系人,android获取手机通讯录联系人
  9. PS批量导入图片进行后续处理
  10. 机器学习算法 03 —— 逻辑回归算法(精确率和召回率、ROC曲线和AUC指标、过采样和欠采样)