本博客内容为VulDeePecker: A Deep Learning-Based System for Vulnerability Detection论文的精读阅读笔记,对于其中的概念以及方法,都给出了自己的理解,并针对一些不清楚或者没接触过的知识点,都做出了详细注解。此论文为第一篇使用深度学习用于漏洞检测的论文,提出了一些关于使用深度学习应用于漏洞检测的一些指导原则,并给出了基于深度学习的漏洞检测系统的开发过程以及用于评测漏洞检测系统有效性的数据集。这对后面关于漏洞检测的学习有极强的指导意义。
本文在摘要部分首先介绍了现如今对于软件漏洞的自动检测的问题。现在往往是通过人类专家来定义漏洞的特征,然后在去检测软件是否有这些漏洞的特征去判断是否有漏洞。这样的方法不仅仅对人的依赖程度较大,从而导致工作量非常大,而且由于人类专家的主观性等还会遗漏很多漏洞的特征。而本文介绍的方法就是将人类专家从这样繁琐和主观的任务中解脱出来,使用深度学习去代替人类专家从而实现低误报率的漏洞检测系统。在摘要中,还简单介绍了本文所描述方法的原理和过程,最终给出了和其他漏洞检测系统的对比实验结果,发现本文介绍的VulDeePecker都成功的识别了这些漏洞,并且保证了低误报率和低漏报率。
在引言部分,首先介绍了目前的网络攻击现状,指出了许多的网络攻击都源于软件的漏洞,那么也就意味着,我们需要如何检测到这些软件漏洞是当前的重要课题。当然,现在也有很多的漏洞检测方案,但是本文也对这些漏洞检测方案的不足进行了介绍,这些不足主要包括两个主要缺点:
在介绍这两个缺点之前,我对漏洞检测方案的一些评测概念进行了学习和整理。首先定义两个概念,阳性(正)和阴性(负),我们将阳性样例定义为 P P P(Positive),阴性样例定义为 N N N(Negative)。那么我们再进行漏洞检测时,我们做以下几个定义:
所以,显然有:
P = T P + F N N = F P + T N \begin{array}{l} P=T P+F N \\ N=F P+T N \end{array} P=TP+FNN=FP+TN
那么根据这几个基础概念,我们给出对于本文漏洞检测方案的一些评价公式,整理如下:
准确率(Accuracy)
对于准确率我们又可称为正确率。这个最好理解,也就是字面意思,也就是我们的漏洞检测系统对于整体样本判断正确的能力。即将 阳性(正)样本判定为Positive和阴性(负)样本判定为Negative的正确分类能力 。准确率的值越大,说明此漏洞检测系统的性能越好。准确率的评测公式如下所示:
A c c u r a c y = T P + T N T P + T N + F P + F N Accuracy=\frac{T P+T N}{T P+T N+F P+F N} Accuracy=TP+TN+FP+FNTP+TN
精确率(Precision)
精确率容易和准确率搞混,但是这是两个概念。精确率针对的是漏洞检测系统正确检测正样本的能力,即检测的正样本中有多少是真实的正样本。可见准确率是针对全部检测,精确率只是针对正样本检测。精确率的值越大,说明漏洞检测系统的性能越好。精确率的评测公式如下所示:
P r e c i s i o n = T P T P + F P Precision=\frac{T P}{T P+F P} Precision=TP+FPTP
误报率(FalseAlarm)
误报率又可以称为假阳率、虚警率、误检率。通过名字就能知道,误报率描述的是漏洞检测系统错误预测漏洞的评价指标。即负样本被预测为正样本占总的负样本的比例。所以显然,误报率越小,说明漏洞检测系统的检测能力越强。误报率的评测公式如下所示:
F a l s e A l a r m = F P F P + T N = T P N FalseAlarm=\frac{F P}{F P+T N}=\frac{T P}{N} FalseAlarm=FP+TNFP=NTP
漏报率(MissRate)
漏报率也可以称为漏警率、漏检率。漏报率即漏洞检测系统将正样本检测为负样本的所占总的正样本的比例。那么很明显,漏报率的值越小,说明漏洞检测系统的检测能力越强。漏报率的评测公式如下所示:
M i s s R a t e = F N T P + F N = F N P MissRate=\frac{F N}{T P+F N}=\frac{F N}{P} MissRate=TP+FNFN=PFN
当我们对这几个基本概念有所了解后,我们来看本文对于目前的漏洞检测方案的一些看法。首先本文认为,现有的漏洞检测解决方案主要依赖于人类专家来定义特征,所以受人类专家主观倾向的制约,并且工作十分繁琐;其次,本文对于目前的漏洞检测系统的主要缺点做了简要概述,本论文认为现在的漏洞检测系统的误报率以及漏报率很高,或者只兼顾了其一,而不能同时达到低误报率和低漏报率。
那么本文的研究方向也基于这两点,首先要考虑的就是将人类专家从繁重的工作中解脱出来,并且到达低误报率和低漏报率。所以就引出了本文所着重介绍的方法:基于深度学习漏洞检测系统的设计和实现,此漏洞检测系统又称为Vulnerability Deep Pecker(VulDeePecker)。
然后本文作者又针对本方法详细的论述了针对此问题做出的三项贡献。
首先作者对于如何使用深度学习方法用于漏洞检测给出了一些论断,对于深度学习方法,可以使漏洞检测自动化,并不需要人类专家手动定义特征。但是,深度学习方法并不是为漏洞检测应用而生的,所以要确定一些基本原则以便可以将深度学习方法应用于漏洞检测:其中最重要的就是选择可以应用于漏洞检测的特定神经网络。并且使用代码小工具表示程序,使其在语义上相互关联,还可以作为深度学习的输入从而进行向量化。
这里给出向量化的含义:因为在深度学习中,往往需要处理很多数据并且进行很多轮的迭代,那么为了提高迭代速度,那么自然就使用到了矩阵进行运算,这也是数据向量化的由来。
其次,作者对于VulDeePecker的有效性进行了评估。主要从以下三个方面进行了有效性的评估
针对以上问题,作者对VulDeePecker的有效性进行了实验,发现VulDeePecker的效率非常高,可以检测到尚未识别的漏洞,还包括0天漏洞,这足以证明VulDeePecker的有效性。
这里给出0天漏洞的含义: 0day漏洞,又称“零日漏洞”(zero-day),是已经被发现(有可能未被公开),而官方还没有相关补丁的漏洞。通俗地讲就是,除了漏洞发现者,没有其他的人知道这个漏洞的存在,并且可以有效地加以利用,发起的攻击往往具有很大的突发性与破坏性。
最后,因为现在没有现成的数据集来对VulDeePecker进行测试,所以作者评估VulDeePecker和其他未来将开发的基于深度学习的漏洞检测系统的数据集。此数据集已经提供在以下位置了:https://github.com/CGCL-codes/VulDeePecker。
在引言的最后,本文给出了论文其余部分的组织结构,如下所示:
在本部分,本文主要给出了使用深度学习应用到漏洞检测系统的一些指导原则,因为深度学习并不是为漏洞检测而生的,所以确定这些指导原则至关重要。本文主要确定了以下三项指导原则:
其中,指导原则1和指导原则2主要确定了我们待检测漏洞程序的一些特征,比如保留程序元素之间的语义关系以及将程序以更细粒度表示。这些都是为了提高漏洞检测的效率和准确性。而其中最重要的就是指导原则3。因为我们该如何使用深度学习去进行漏洞检测才是我们要确定的问题,因为现在的深度学习有很多框架,我们应该选择哪种才最适合我们呢?本文的指导原则3指出:由于一行代码是否包含漏洞可能取决于上下文,因此可以处理上下文的神经网络可能适合于漏洞检测。 所以说我们可以使用自然语言处理的神经网络应用于漏洞检测。
但是某些应用与自然语言处理的神经网络由于各种问题也不适合与漏洞检测,比如本文提到的Vanishing Gradient(梯度消失)问题。那么应该选择不受Vanishing Gradient(VG)问题影响的神经网络。
这里给出Vanishing Gradient(梯度消失)问题的含义: 在反向传播过程中需要对激活函数进行求导,如果导数小于1,那么随着网络层数的增加梯度更新信息会朝着指数衰减的方式减少这就是梯度消失。
我们可以借助图片来理解梯度消失问题,比如我们在神经网络中常用的 S i g m o i d Sigmoid Sigmoid 函数:
在神经网络的训练或预测中,因为反向传播的过程,所以要对 S i g m o i d Sigmoid Sigmoid 函数求导,那么 S i g m o i d Sigmoid Sigmoid 函数的导数的图像图下图所示:
我们可以看到当 x x x 趋近于无穷大的时候,导数趋近于0。这样经过链式求导之后很容易造成梯度消失问题。 这样会使训练的模型无效。
为了避免这种情况发生,本文经过比较后,选择了长短期记忆网络(LSTM)来进行漏洞检测 ( 注:因为转换转移中使用的是加法,而不是乘法。因为求导后,如果两个数比较小,相乘后会更小。但是加法不会剧烈改变数据返回的大小,适合用来传递状态。这也是因为能够保存状态,缓解梯度消失的原因。) 。但是单向的(LSTM)也不足以胜任现实中的漏洞检测,因为程序函数调用的参数可能会受到程序中前面语句的影响,也可能会受到后面语句的影响。所以基于这个问题,本文最终采用双向长短期记忆网络(BLSTM)来进行漏洞检测,下图为(BLSTM)的示意图:
双向长短期记忆网络(BLSTM)其中最重要的特点就是,(BLSTM)层有两个方向,向前和向后。这样就可以处理上下文信息,便于更准确的识别漏洞。当然(BLSTM)层中包含了很多复杂的(LSTM)核,在本文中被视为黑盒。输入的向量首先经过(BLSTM)层,然后使用密集层减少接收到的矢量维数,最终softmax层接收密集层的低维数据,最后进行格式化分类和表示结果。