这篇文章提出了一种可以同时实现高检测能力和高定位精度的漏洞检测器VulDeeLocator。主要包含两个创新:1)利用中间代码来容纳额外的语义信息。2)使用粒度细化的概念来确定漏洞的位置。当应用于从三个真实世界软件产品中随机选择的200个文件时,VulDeeLocator检测到18个已确认的漏洞,其中16个为已知漏洞,另外两个未在NVD中报告,但已被Libav供应商静默修补。

漏洞是造成网络攻击的主要原因,理想的漏洞检测应同时具备高检测能力和高定位精度(即定位漏洞代码所在的行号)。
目前的静态分析方法主要分为基于代码相似性的检测和基于模式的检测,它们存在以下缺陷:
目前最先进的方法,1)无法捕捉跨程序文件的语义相关语句之间的关系,因为程序通常包含许多用户定义的和系统头文件(如.h),用于指定类型和宏指令,不能通过单独分析每个源代码文件来实现,因为这些类型和宏指令是在程序文件(如.c)中使用,而在头文件中定义的,这就要求进行跨文件的依赖性分析。2)无法容纳准确的控制流和变量定义使用关系,这是由于每个变量没有被精确地分配一次并且基于源代码的表示具有许多构造(例如标识符)。
文章提出一种基于深度学习的漏洞检测器VulDeeLocator,用于C程序源代码漏洞检测。与最先进的探测器相比,VulDeeLocator在F1值、假阳率和假阴率分别平均提高了9.8%,7.9%,和8.2%,以及漏洞定位精度提高了4.2倍。
图1介绍了VulDeeLocator的基本思想。首先给定漏洞语法特征,并从源代码中提取关键tokens,然后从同一源代码的中间代码中挑选出与这些标记有语义关系的语句。这些语句被编码为向量用来训练神经网络,或者输入到训练好的模型中进行漏洞检测,得到的输出为漏洞代码的行号。

(source code- and Syntax-based Vulnerability Candidate, sSyVC)的定义:给定源程序P
(intermediate code- and Semantics-based Vulnerability Candidate, iSeVC)的定义:给定源程序P,其中间代码为P′,sSyVC yi的中间代码表示为y′i。用ei表示yi对应的iSeVC,ei为中间代码P′的一系列语句,这些语句与y′i存在控制或数据依赖关系。也就是说,与yi相对应的iSeVC是程序P的中间代码y′i的一个程序切片。
作为VulDeeLocator输入的C程序源代码需满足两个条件:
VulDeeLocator大致分为5个步骤:1)从源代码提取sSyVCs。2)根据sSyVCs,从中间代码中生成iSeVCs。3)将从训练程序提取到的iSeVCs标记为有漏洞或无漏洞,并标记漏洞位置。4)通过iSeVCs对应的向量表征和标签训练神经网络模型。5)用训练好的神经网络模型去检测和定位漏洞位置。

利用已知漏洞的语法特征,并通过程序源代码的抽象语法树来表示这些特征,从而简化sSyVC的提取。文章共定义了4种漏洞语法特征:库/API函数调用(FC)、数组定义(AD)、指针定义(PD)、算术表达式(AE)。
生成源代码的AST,然后识别其类型和代码与漏洞语法特征相匹配的节点,从中提取sSyVC。图4(a)用红框突出显示了程序中的sSyVC:与FC漏洞语法特征相关的sSyVCs包括"printf"(第6行)、"memset"(第14行和第23行)和"memmove"(第25行);与AD漏洞语法特征相关的sSyVC包括"dataBuffer"(第10行)和"source"(第11行);与PD漏洞语法特征相关的sSyVC包括"data"(第2行);与AE漏洞语法特征相关的sSyVC包括"data=dataBuffer-8"(第19行)。

生成iSeVCs包含下列三个步骤:
如果iSeVC包含已知漏洞,则标记其漏洞的行号,表示为x1,…,xζ,其中xϵ(1≤ϵ≤ζ)对应于该漏洞的行号。否则,标记为"0"(即iSeVC不包含漏洞)。可以通过附带调试信息的文本LLVM将源代码中的漏洞行号映射到中间代码中的行号。
为了在捕获程序语义信息的同时使iSeVC免受用户定义的函数名称的影响,将用户定义的函数名映射到符号名(如"FUN1"、"FUN2")。使用词嵌入方法将iSeVC编码为向量,并统一向量长度(向量长度小于θ时,在其末尾补0。向量长度大于θ时,将向量截断为长度θ)。
BRNN的输出粒度和输入粒度相同,无法实现细化,对于漏洞检测,iSeVC中的漏洞代码应受到神经网络模型更多的关注,BRNN-vdl较好实现了上述要求。
3.5.1 标准BRNN层
图5展示了BRNN-vdl的结构,在标准BRNN结构中新加入了3层结构:乘法层(Multiply layer)、k最大池化层(k-max pooling layer)、平均池化层(Average pooling layer)。模型的输入为标记的iSeVC的向量表征,每个时间步长对应iSeVC中的一个token,每一个token被编码为长度为30的向量,且每一个iSeVC表示为长度为27000的向量,也就是说每个iSeVC中仅考虑前900个向量。在时间步长τ(1≤τ≤λ)中,λ是iSeVC中token的数量,iSeVC的标准BRNN层的输出表示为:
gτ(ei)=ϕ(gτ−1(ei),gτ+1(ei),ei,ω,β)
其中ω是权重向量,β是偏差向量,gτ−1(ei)和gτ+1(ei)分别为BRNN层在时间步τ−1和τ+1的输出。函数ϕ表示BRNN层的输出由其中几个参数表示。
对于iSeVC ei,标准BRNN中激活层的输出向量表示为:
Ai=(g1(ei),…,gλ(ei))

3.5.2 乘法层(Multiply layer)
乘法层实现注意力获取。对于存在漏洞的iSeVCs,挑选出与漏洞代码行对应的 tokens作为输出。对于不存在漏洞的iSeVCs,将iSeVCs中的所有tokens作为输出(这些tokens同等重要)。也就是说,乘法层的作用在于:在训练中除去与漏洞无关的tokens,提升漏洞检测精度,降低加阴率。乘法层将激活层的输出向量Ai与漏洞定位矩阵Li相乘,得到乘法层的输出Mi:
Mi=AiLi
其中Li为对角矩阵:Li=diag(α1,α2,…,αλ)。对于漏洞iSeVCs,如果φ∈{x′ϵ,…,x′ϵ+wϵ−1},设αφ为1,否则,设αφ为0。对于不存在漏洞的iSeVCs,设αφ为1,其中1≤φ≤λ。
3.5.3 池化层(Pooling layer)
两个池化层进一步时间检测粒度细化。对于iSeVC ei,平均池化层的输出定义为oi:
oi=ave(maxk(Mi))
其中函数maxk返回向量中前k个最大的元素,函数ave返回前k个最大的元素的平均值。
图6展示了已训练的BRNN-vdl进行漏洞检测和定位的过程,输入是从目标程序中提取的iSeVCs的向量表征。首先得到iSeVCs中的tokens对应的激活层的输出,并计算每一行中tokens的k个最大输出值的平均值,然后提取输出大于阈值ϑ的代码行,从而得出存在漏洞的iSeVCs和漏洞代码行。最后,将存在漏洞的iSeVCs和其中的漏洞代码行映射到源代码中,作为检测阶段的输出。

文章采用经典二分类指标FPR、FNR、A、P、F1来衡量VulDeeLocator的漏洞检测能力。使用IOU=|U∩V||U∪V|测试VulDeeLocator的定位精度,其中U表示真实漏洞代码行号的集合,V表示检测的漏洞代码行号的集合,IOU越接近1,说明漏洞定位精度越高。
表一展示了VulDeeLocator-BGRU基于两种不同的漏洞表征方式的漏洞检测能力对比。结果显示iSeVCs比sSeVCs(基于源代码表征)的效果更好,FPR提高4.6%,FNR提高7.4%,准确率A提升6.5%,精度P提升5.9%,F1值提高6.7%。这表示基于中间代码表征的iSeVCs与基于源代码表征的sSeVC相比可以捕获更多的语义信息。

为了验证BRNN-vdl对于漏洞定位的有效性,分别基于不同漏洞候选表征和不同模型进行了实验,表4总结了实验结果。BRNN-vdl在IOU值上比BRNN平均提高了21.5%,在输出的漏洞行数上,BRNN-vdl平均为2.6行,而BRNN平均为18.8行。当使用sSeVC作为漏洞候选时,FPR降低5.0%,FNR提高0.5%,F1值提高4.2%;当使用iSeVC作为漏洞候选时,其FPR提高1.8%,FNR提高1.6%,F1值提升3.9%。以上结果说明,与BRNN相比,BRNN-vdl实现了更高的漏洞定位精度和略高的漏洞检测能力。

表5总结了与目前最先进的基于模式的漏洞检测器的比较结果。VulDeeLocator在检测和定位漏洞方面比最先进的基于模式的漏洞检测器更有效。特别是,VulDeeLocator-BGRU的定位精度平均比漏洞检测器SySeVR高4.2倍。

为了测试VulDeeLocator是否能检测并定位真实软件产品中的漏洞,从3个真实软件产品中随机挑选了200个程序,在5个漏洞检测器中,VulDeeLocator-BGRU是最有效的。在其他4个检测器中,SySeVR获得了最高的F1值,但其IoU最低。SySeVR的低定位精度是由于检测到的漏洞代码行的平均数量很大(即平均每个检测到的漏洞有76.2行代码),这与VulDeeLocator检测到的漏洞代码行的平均数量3.8行形成强烈对比。

这篇文章提出了一种基于深度学习的,具有高检测能力和高定位精度的漏洞检测器VulDeeLocator。通过引入粒度细化的理念和利用基于中间代码的表征来捕获程序中的语义信息,如类型和宏的定义及其在文件中的使用之间的关系,以及控制流和变量定义-使用关系。真实软件产品的检测结果显示,VulDeeLocator检测到了NVD中没有报告的四个漏洞。