论文中文翻译——VulCNN An Image-inspired Scalable Vulnerability Detection System

本论文相关内容

  1. 论文下载地址——Web Of Science
  2. 论文中文翻译——VulCNN An Image-inspired Scalable Vulnerability Detection System


前言

  此博客为VulCNN An Image-inspired Scalable Vulnerability Detection System论文的中文翻译,本篇论文将漏洞检测与图分类联系到一起,并结合神经网络进行漏洞检测,思路比较新奇,效果看来也还不错,是一篇值得一读的论文!


VulCNN:一种基于图像的可扩展漏洞检测系统

作者信息

Yueming Wu, Huazhong University of Science and Technology, China, [email protected]
Deqing Zou, Huazhong University of Science and Technology, China, [email protected]
Shihan Dou, Fudan University, China, [email protected]
Wei Yang, University of Texas at Dallas, United States, [email protected]
Duo Xu, Huazhong University of Science and Technology, China, [email protected]
Hai Jin, Huazhong University of Science and Technology, China, [email protected]

摘要

  由于深度学习(DL)可以自动从源代码中学习特征,因此它已被广泛用于检测源代码漏洞。为了实现可扩展的漏洞扫描,一些先前的研究打算将源代码直接处理为文本。为了实现准确的漏洞检测,其他方法考虑将程序语义提取为图表示,并使用它们来检测漏洞。在实践中,基于文本的技术是可扩展的,但由于缺乏程序语义而不准确。基于图的方法是准确的,但不可扩展,因为图分析通常耗时。

  在本文中,我们的目标是在扫描大规模源代码漏洞时实现可伸缩性和准确性。受现有基于DL的图像分类的启发,我们倾向于使用这些技术来实现我们的目的,该分类能够准确分析数百万张图像。具体来说,我们提出了一种新的想法,它可以有效地将函数的源代码转换为图像,同时保留程序细节。我们实现了VulCNN,并在13687个易受攻击的函数和26970个非易受攻击函数的数据集上对其进行了评估。实验结果表明,VulCNN可以比八个最先进的漏洞检测器(即Checkmarx、FlawFinder、RATS、TokenCNN、VulDeePecker、SySeVR、VulDeeLocator和Devign)获得更好的准确性。就可扩展性而言,VulCNN比VulDeePecker和SySeVR快约4倍,比VulDeeLocator快约15倍,比Devign快约6倍。此外,我们对2500多万行代码进行了案例研究,结果表明VulCNN可以检测大规模漏洞。通过扫描报告,我们最终发现了NVD中未报告的73个漏洞。

CCS概念

  安全和隐私→ 漏洞扫描器。

关键词

  漏洞检测,CNN,大规模,图像

ACM参考格式

  吴粤明、邹德清、窦世汉、魏阳、徐铎和海金。2022.VulCNN:一种基于图像的可扩展漏洞检测系统。2022年5月21日至29日,第44届国际软件工程会议(ICSE’22),美国宾夕法尼亚州匹兹堡。ACM,纽约,美国,12页。https://doi.org/10.1145/3510003.3510229

1 引言

  最近,黑客勒索、僵尸网络攻击和用户信息泄露等各种网络空间安全事件频频发生。作为网络空间的重要组成部分,软件系统中的漏洞给网络空间带来了严重的安全威胁。2020年,Synopsys开源安全和风险分析(OSSRA)检查了1250+个商业代码库的审计数据,发现这些代码库中70%的代码是开源的。此外,75%的开源代码库包含开源安全漏洞,近一半包含高风险漏洞。因此,迫切需要开展大规模、智能化的软件漏洞检测方法,以更好地保护软件安全。

  通常,源代码漏洞检测方法可分为两大类,即基于代码相似性的方法和基于模式的方法。基于代码相似性的漏洞检测方法主要用于检测代码克隆导致的漏洞。当用于检测非代码克隆导致的漏洞时,它将导致较高的误报率。传统的基于模式的漏洞检测方法依赖于专家手动定义漏洞规则或特征来描述漏洞。这些方法不仅主观,而且难以同时实现低假阳性率和低假阴性率。

  近年来,由于深度学习(DL)的自动特征提取,它被广泛用于检测源代码漏洞。这些基于DL的技术属于第二类方法(即,基于模式的方法)。它们不需要专家手动定义特征,并且可以自动生成漏洞模式。例如,一些先前的研究将程序源代码视为文本,并应用自然语言处理领域的技术来检测漏洞。这些基于文本的方法的检测性能并不理想,因为它们忽略了源代码的程序语义。为了解决这个问题,研究人员进行程序分析,将源代码的程序语义提取为图表示,并进行图分析(例如,图神经网络)以检测漏洞。这些基于图的技术可以在检测漏洞方面获得更高的效率,然而,它们的可扩展性比基于文本的方法差得多。此外,几乎所有这些方法都只关注于将函数标记为易受攻击或不易受攻击,并且无法准确指出哪些代码行可能更易受攻击。

  在本文中,我们的目标是在检测大规模源代码中的漏洞时同时实现准确性和可扩展性。我们的关键思想源自基于DL的图像分类,它可以处理数百万张图像,同时保持高精度,并且可以通过可视化技术解释分类结果。具体来说,我们在论文中主要解决了一个主要挑战。

  • 如何有效地将函数的源代码转换为图像,同时保留程序细节?

  为了应对这一挑战,我们首先进行程序分析,将函数的程序语义提取到程序依赖图(PDG)中,该图包含源代码的控制流和数据流细节。在获得函数的PDG后,我们将其视为一个社交网络,并对网络应用中心性分析,以将图结构信息附加到每行代码。在社交网络分析中,提出了中心性分析来衡量网络中节点的重要性。具体而言,我们利用三种不同的中心性(即,度中心性、katz中心度和紧密中心性)来开始我们的图像转换。使用三个中心性有两个主要原因。首先,不同的中心性可以从不同的方面保持图属性。第二,图像通常有三个通道(即,红色、绿色和蓝色),它们一起工作以生成完整的图像。中心性分析的输出是一幅图像,同时从三个方面保留了图细节。给定生成的图像,我们然后训练卷积神经网络(CNN)模型,并使用它来检测漏洞。为了查明函数中的漏洞代码行,我们在图像上使用深度可视化技术(即类激活图)来获得相应的热图,这些热图可以帮助安全分析人员理解为什么该函数被标记为易受攻击的。

  我们实现了VulCNN,并在40657个函数的数据集上对其进行了评估,该数据集由13687个易受攻击的函数和26970个非易受攻击的函数组成。评估结果表明,VulCNN可以实现比八个相当的漏洞检测器(即Checkmarx、FlawFinder、RATS、TokenCNN、VulDeePecker、SySeVR、VulDeeLocator和Devign)更好的有效性。此外,VulCNN比另一种最先进的基于图的漏洞检测工具(即Devign)快六倍多。为了验证VulCNN在大规模漏洞扫描方面的能力,我们对2500多万行代码进行了案例研究。通过扫描报告,我们最终发现了NVD中未报告的73个漏洞。其中,17个漏洞已被供应商在最新版本的相应产品中“默默”修补,4个漏洞已删除,其他52个漏洞仍存在于产品中。我们已向其供应商报告了这些漏洞,并希望能够尽快修补。

  总之,本文做出了以下贡献:

  • 我们提出了一种新颖的想法,可以有效地将函数的源代码转换为图像,同时保留程序细节。
  • 我们设计并实现了一个原型系统VulCNN,这是一个可扩展的基于图的漏洞检测系统。
  • 我们对13687个漏洞函数和26970个非漏洞函数的数据集进行了评估。实验结果表明,VulCNN优于八种最先进的漏洞检测器(即Checkmarx、FlawFinder、RATS、TokenCNN、VulDeePecker、SySeVR、VulDeeLocator和Devign)。
  • 我们对2500多万行代码进行了案例研究,以验证VulCNN在大规模漏洞扫描方面的能力。通过扫描结果,我们发现了NVD中未报告的73个漏洞。

  论文组织。论文的其余部分组织如下。第2节介绍了本文的动机。第3节介绍了我们的系统。第4节报告了实验结果。第5节讨论了未来的工作。第6节描述了相关工作。第7节总结了本论文。

2 动机

  我们都知道,一个函数由多行代码组成,这些代码一起实现了该函数的程序语义(即功能性)。然而,不同代码行的语义贡献是不同的。例如,有些代码只是一个简单的变量定义,而有些代码实现了函数的核心算法。显然,后者提供了更多的语义。因此,我们提出了一个问题:“如何找出函数中不同代码行对程序语义的贡献?”

  为了回答这个问题,我们选择了一个缓冲区溢出漏洞函数作为示例。为了维护程序语义,我们考虑通过静态分析提取控制流和数据流细节。具体来说,我们利用Joern获得图1中漏洞的程序依赖图(PDG)。PDG中的每个节点对应于漏洞中的一行代码。红线和蓝线分别显示函数中不同代码行之间的数据流和控制流。为了简单地显示漏洞的PDG,我们用编号的圆形节点替换每行代码。函数中的八行代码对应于八个圆形节点,如图1所示。在图论中,邻接矩阵是用于表示有限图的方阵。因此,为了表示漏洞的PDG,我们计算相应的邻接矩阵,并在图1中对其进行描述。矩阵的元素表示图中节点对是否相邻。因为我们的PDG是一个有向图,所以元素表示两个不同节点之间的有向边的数量。例如,节点3具有指向节点4的两条边,而节点4没有指向节点3的边。因此,矩阵中节点3和节点4之间的对应值分别为2和0。

请添加图片描述

图1:漏洞的程序依赖图(PDG)和相应的邻接矩阵

  在获得PDG的邻接矩阵之后,我们发现当我们对矩阵中的一行求和时,获得的值对应于节点的出度。此外,当我们对列求和时,获得的值是节点的入度。例如,节点4的行和是3(即,1+1+1=3),这表明节点4的出度是3。为了更好地说明我们的观点,我们在图2中显示了漏洞的所有代码行的入度、出度和度。通过图2中的结果,我们发现不同代码行的度基本不同。这是合理的,因为不同代码行之间存在不同的关系(即控制流和数据流),并且漏洞是基于这些关系触发的。如果我们将这些代码作为文本直接处理,则所有代码行的度都是1,这可能会降低漏洞检测的准确性。

请添加图片描述

图2:图1中所有代码行的入度、出度和度

  总之,一个图可以用它的邻接矩阵来表示,矩阵可以用所有节点的度来描述。因此,计算函数中代码的度可能是保留图细节的最佳候选。实际上,图中节点的度最初用于量化其重要性。它已广泛应用于社交网络分析。学位越高,人就越重要。同时,不同的代码行具有不同的度。如果我们将每一行代码视为一个人,将控制流和数据流关系视为人与人之间的通信,那么相应的PDG可以视为一个社交网络。一个人的度越高,与他交流的其他人就越多,他在PDG社交网络中的重要性就越大。因此,我们可以利用一行代码的重要性作为程序语义贡献的一种形式。换句话说,一行代码越重要,它对实现函数的程序语义(即功能性)的贡献就越大。基于观察结果,我们通过分析所有代码行的重要性来设计VulCNN。

3 方法

  在本节中,我们将介绍一种新颖高效的源代码漏洞检测系统VulCNN。

3.1 概述

  如图3所示,VulCNN由四个主要阶段组成:图提取、句子嵌入、图像生成和分类。

请添加图片描述

图3:VulCNN的系统概述
  • 图提取:给定函数的源代码,我们首先将它们规范化,然后执行静态分析以提取函数的程序依赖图。

  • 句子嵌入:程序依赖关系图中的每个节点对应于函数中的一行代码。我们将一行代码视为一个句子,并将它们嵌入一个向量中。

  • 图像生成:在句子嵌入之后,我们应用中心性分析来获得所有代码行的重要性,并将它们逐一乘以向量。此阶段的输出是图像。

  • 分类:我们的最后阶段侧重于分类。给定生成的图像,我们首先训练CNN模型,然后使用它来检测漏洞。

3.2 图提取与句子嵌入

  VulCNN旨在在检测漏洞时同时实现准确性和可扩展性,因此,我们首先应用静态分析将源代码的程序语义提取为图表示。由于文件级漏洞检测的粒度较粗,我们专注于在更细粒度级别(即函数级别)检测漏洞,因为函数也可以实现特定任务。在提取函数的图表示之前,我们首先抽象并规范化源代码。特别是,我们使用了三个级别的标准化,这使得VulCNN在保持程序语义的同时,对常见的代码修改具有弹性。

  图4显示了函数在不同规格化级别下的详细转换。

请添加图片描述

图4:VulCNN中源代码规范化的步骤
  • 步骤1:删除源代码中的注释,因为它们与程序语义无关。
  • 步骤2:以一对一的方式将用户定义的变量映射到符号名称(例如,VAR1)。
  • 步骤3:以一对一的方式将用户定义的函数映射到符号名称(例如FUN1)。

  在抽象了源代码之后,我们利用C/C++的开放源代码分析平台Joern来提取函数的程序依赖图(PDG)。PDG是包含源代码的数据流和控制流细节的图表示。PDG中的每个节点对应于函数中的一行代码。我们将一行代码视为一个句子,并应用句子嵌入将其转换为固定长度的向量。具体来说,我们使用了一种广泛使用的方法(即sent2vec)来完成句子嵌入。它采用一个简单但有效的无监督目标来训练句子的分布式表示。在本文中,使用sent2vec模型,我们可以将一行代码转换为其相应的向量表示,其维数为128。

  为了更好地说明我们提出的方法所涉及的详细步骤,我们在图5中提供了一个示例。图5中的红线和蓝线分别表示函数中不同代码行之间的数据流和控制流。

请添加图片描述

图5:说明如何将函数的源代码转换为图像的示例

3.3 图像生成

  在图提取和句子嵌入之后,我们可以获得一个新的PDG,其中每个节点都是一个向量表示。在这个阶段,我们的目标是在考虑不同代码行对程序语义的贡献的同时,有效地将新PDG转换为图像。为了完成我们的目的,我们将新的PDG视为一个社交网络,并应用社交网络中心性分析来获得所有代码行的重要性。中心性概念最初是在社交网络分析中发展起来的,其最初目的是衡量网络中节点的重要性。集中分析已在许多不同领域(例如,生物网络和交通网络)使用,这些成功的应用验证了网络分析的有效性。事实上,已经提出了许多不同类型的中心性来从不同方面量化网络中节点的重要性,例如:

  • 节点的度中心性是它所连接的节点的分数。度中心度值通过除以图中的最大可能度来归一化 N − 1 N-1 N1,其中 N N N是图中的节点数。

    x i = deg ⁡ ( i ) N − 1 x_{i}=\frac{\operatorname{deg}(i)}{N-1} xi=N1deg(i)
    请注意 d e g ( i ) deg(i) deg(i)是节点 i i i的度数。

  • Katz中心性基于节点邻居的中心性计算节点的中心性。节点 i i i的Katz中心性是
    x i = α ∑ j A i j x j + β x_{i}=\alpha \sum_{j} A_{i j} x_{j}+\beta xi=αjAijxj+β
    请注意 A A A是具有特征值 λ \lambda λ的图 G G G的邻接矩阵。参数 β \beta β控制初始中心性和

    α < 1 λ max ⁡ \alpha<\frac{1}{\lambda_{\max }} α<λmax1
    Katz中心性通过测量直接邻居(一级节点)的数量以及通过这些直接邻居连接到所考虑节点的图中所有其他节点的数量来计算图中节点的相对影响。

  • 紧密中心性表示节点与网络中所有其他节点的接近程度。它被计算为从节点到图中每个其他节点的最短路径长度的平均值。节点的平均最短距离越小,节点的紧密中心性越大。
    x i = N − 1 ∑ i ≠ j d ( i , j ) x_{i}=\frac{N-1}{\sum_{i \neq j} d(i, j)} xi=i=jd(i,j)N1
    请注意 d ( i , j ) d(i,j) d(i,j)是节点 i i i j j j之间的距离, N N N是图中的节点数。

  因为图像通常有三个通道(即,红色、绿色和蓝色),它们一起工作以生成完整的图像。我们选择了三种不同的中心性(即,度中心性、katz中心性和紧密中心性)来对应于三个通道。这三个中心性可以从三个不同的方面计算函数中所有代码行的重要性。通过这一点,我们可以完全考虑不同代码行对函数程序语义的贡献。算法1显示了VulCNN如何将函数转换为图像的整个过程。如图5和算法1所示,我们首先对新的PDG中的所有节点执行度中心性分析,以收集所有节点(即向量)的度中心性。然后,在乘以相应的度中心性之后,根据代码行数逐个排列所有向量。我们将这些排列的新向量称为“度通道”。类似地,在对新的PDG应用katz中心性和紧密中心性分析后,我们可以获得另外两个“通道”,即“katz通道”和“紧密通道”。最后,这三个通道用于生成图像。

请添加图片描述

  简言之,图像生成阶段的输入是一个新的PDG,其中每个节点都是一个嵌入向量,输出是一个具有所有代码行重要性的图像。

3.4 分类

  深度学习是一种复杂的机器学习算法,在许多领域(例如,语音和图像识别)取得了远远超过先前相关技术的成果。深度学习的优点是使用无监督或半监督的特征学习和高效的分层特征提取算法来代替手动特征获取。在图像处理领域,卷积神经网络(CNN)一直是焦点,因为它不仅不需要手动图像预处理,而且可以使用其独特的细粒度特征提取达到接近人类的水平。

  在图像生成阶段之后,函数的源代码被转换为图像。给定一幅图像,我们打算首先训练一个CNN模型,然后使用它来检测漏洞。由于CNN采用相同大小的图像作为输入,而不同函数中的代码行数不同,因此我们需要进行调整。为了找到更适合生成固定大小图像的阈值,我们选择第4节中的实验数据集(即40657个函数)作为测试对象,并记录所有这些函数的代码行数。图6显示了这些函数中代码行数的累积分布函数(CDF)。从图6的结果可以看出,99%以上的函数的代码少于200行。事实上,我们在检测漏洞时使用了不同的阈值(即50-200行代码)。考虑到检测精度和相应的运行时间开销,我们最终选择100行代码作为生成输入图像的阈值。当函数中的代码行数小于100时,我们将零填充到向量的末尾。当一个函数有超过100行代码时,我们会删除向量的结尾部分。我们输入的图像大小为3∗100∗128,其中3对应于三个通道(即“度通道”、“katz通道”和“紧密通道”),100对应于代码行的阈值,128代表句子向量的维度。

请添加图片描述

图6:函数中代码行总数的累积分布函数(CDF)

  生成固定大小的图像后,我们使用这些图像训练CNN模型。如图7所示,我们使用形状为 m ∗ 128 m∗128 m128的不同卷积过滤器,使得每个过滤器可以跨越句子嵌入的整个空间。过滤器尺寸 m m m确定一起考虑的连续句子的数量。在VulCNN中,我们选择了10种过滤器尺寸(即1到10),每个尺寸都有32个特征图来提取图像不同部分的特征。在最大池化之后,我们的全连接层的长度为320。VulCNN中使用的参数描述如表1所示。整个模型使用校正的线性单元(即ReLU)作为非线性激活函数。此外,我们的CNN中用于惩罚错误分类的损失函数是交叉熵损失。我们使用Adam以0.001的学习率训练CNN。在获得训练后的CNN模型后,我们使用它来标记新函数是否易受攻击。

请添加图片描述

图7:VulCNN的CNN分类
表1:VulCNN中的参数设置

请添加图片描述

  为了解释检测结果,我们利用梯度加权类激活映射++(Grad CAM++)作为我们的可视化技术来精确定位易受攻击的代码行。Grad CAM++是一种类别区分定位技术,它在不改变架构或重新训练的情况下为任何基于CNN的网络生成视觉解释。根据热图中颜色的强度,我们可以知道哪些代码行更容易受到攻击。

4 实验

  在本节中,我们旨在回答以下研究问题:

  • RQ1:VulCNN在检测源代码漏洞时的检测性能如何?
  • RQ2:VulCNN在检测源代码漏洞时的运行时间开销是多少?
  • RQ3:VulCNN能否实现大规模漏洞扫描?

4.1 实验设置

  我们首先从软件保障参考数据集(SARD)收集数据集,该数据集是美国国家标准与技术研究院(NIST)维护的项目。SARD包含大量生产、合成和学术安全缺陷或漏洞(即坏函数)和许多好函数。在本文中,我们专注于检测C/C++中的漏洞,因此,我们只选择SARD中用C/C++编写的函数。从SARD获得的数据包括12303个易受攻击函数和21057个非易受攻击函数。此外,由于SARD中的合成程序可能不现实,我们从真实世界软件中收集了另一个数据集。对于真实世界的漏洞,我们将国家漏洞数据库(NVD)作为我们的收集源。我们最终获得了1384个易受攻击的函数,它们属于用C/C++编写的不同开源软件。对于真实世界中的非易受攻击函数,我们随机选择了[42]中数据集的一部分,其中包含来自几个开源项目的非易受攻击函数。我们的最终数据集由13687个易受攻击的函数和26970个非易受攻击函数组成。

  VulCNN中的四个阶段(即,图提取、句子嵌入、图像生成和分类)分别通过使用Joern、sent2vec、networkx和pytorch实现。我们在具有16个CPU核和GTX 1080Ti GPU的服务器上运行所有实验。对于数据集,我们首先将其随机分成十个子集,然后使用这七个子集来训练CNN模型,其他两个子集用于验证,最后一个子集用于测试。用于衡量VulCNN有效性的指标与其他指标相同。例如,真阳性(TP)报告正确分类为易受攻击的函数的数量,真阴性(TN)报告正确检测为非易受攻击函数的数量。

4.2 检测性能

  我们首先介绍了VulCNN在不同阈值(即生成图像的代码行数)下的检测性能。因为图6中99%以上的函数的代码少于200行,所以我们将重点放在200行以下的阈值上。具体来说,我们选择了总共10个阈值(即50、60、70、80、90、100、120、150、170、200行)来开始评估。实验结果如图8所示,通过结果,我们看到阈值与检测精度呈正相关,阈值越大,精度越高。然而,当阈值达到100行时,精度的增长变得很小。一方面,由于100行代码的VulCNN的检测精度几乎是最高的。另一方面,阈值越大,图像越大,所需的内存也越多。因此,我们选择100行代码作为生成输入图像的最终阈值。

请添加图片描述

图8:VulCNN在不同阈值下构建图像的检测性能

  然后,我们将VulCNN与几种漏洞检测工具进行了比较,包括一种商业静态漏洞检测工具(即Checkmarx)、两种开源静态分析工具(即FlawFinder和RATS),以及五种基于深度学习的漏洞检测方法(即TokenCNN、VulDeePecker、SySeVR、VulDeeLocator和Devign)。

  至于商业工具(即Checkmarx)和两个开源静态分析工具(即FlawFinder和RATS),图9中的检测性能表明其真阳性率(TPRs)和真阴性率(TNRs)并不理想。例如,Checkmarx的TPR仅为 31.9 % 31.9\% 31.9%,这意味着Checkmarx只能检测到标记数据集中 31.9 % 31.9\% 31.9%的漏洞。这样的结果是合理的,因为这些工具依赖于人类专家定义的规则或模式。在实践中,存在不同类型的漏洞,每种类型的模式都不同。换句话说,专家无法定义所有漏洞的所有模式,导致检测性能不佳。

  对于TokenCNN,它首先进行词法分析,将源代码转换为标记序列,然后将它们嵌入到固定长度的向量表示中。最后,将这些向量输入卷积神经网络(CNN)模型以训练漏洞检测器。由于它不考虑任何程序语义,因此性能比VulCNN更差。对于VulDeePecker和SySeVR,他们都通过切片程序收集代码小工具,然后将其转换为相应的向量表示。最后,这些向量用于训练双向递归神经网络(BRNN)模型以检测漏洞。这两个系统之间的区别在于,VulDeePecker只对程序切片进行数据流分析,而SySeVR同时考虑控制流和数据流以获得程序切片。显然,SySeVR比VulDeePecker性能更好,因为它包含更多的程序语义。然而,他们不考虑不同代码行对程序语义的不同贡献,而是将切片中的所有代码行视为文本,并直接应用BRNN来训练漏洞检测器。这就是为什么他们检测到的漏洞比VulCNN少的原因。对于VulDeeLocator,它首先将程序编译为LLVM位代码文件,然后提取中间表示(IR)切片以保留程序语义。最后,通过训练BRNN模型,使用这些IR切片来检测漏洞。由于IR包含比源代码更多的程序细节,因此VulDeeLocator比VulDeePecker和SySeVR更能识别漏洞。然而,与VulDeePecker和SySeVR类似,VulDeeLocator也将切片视为文本,因此性能低于VulCNN。对于Devign来说,它首先应用复杂程序分析来提取包含全面程序语义的图表示,然后使用通用图神经网络来检测漏洞。Devign的检测性能与VulCNN几乎相同。然而,由于生成图的复杂性,它不能扩展到大规模的漏洞扫描。但VulCNN可以,因为它使用中心性分析将耗时的图分析转换为高效的图扫描。

  为了检查中心性分析的使用是否有助于VulCNN检测漏洞,我们构建了另一个实验。更具体地说,在句子嵌入之后,我们直接将句子向量输入到CNN模型中,以训练分类器,而不必乘以中心性。我们将该方法称为VulCNN-wc(即无中心性的VulCNN),并将实验结果显示在图9中。通过此图,我们可以看到VulCNN优于VulCNN-wc,这表明考虑函数中不同代码行的中心性可以提高漏洞检测的检测精度。

请添加图片描述

图9:Checkmarx、FlawFinder、RATS、TokenCNN、VulDeePecker、SySeVR、VulDeeLocator、Devign和VulCNN在检测漏洞方面的真阳性率(TPR)、真阴性率(TNR)和准确性

  此外,由于VulCNN是一个基于图像的漏洞检测系统,我们可以使用CNN可视化技术解释检测结果。在本文中,我们以梯度加权类激活映射++(Grad CAM++)为例来可视化我们的检测结果。图10显示了检测到的缓冲区溢出漏洞的可视化。当“data”大于“sizeof(dest)-strlen(dest)”时,可能会触发此漏洞。在这种情况下,终端null将被写入缓冲区之外。通过图10,我们可以看到代码“strncat(dest,data,strlen(data));”的颜色是最红的,这意味着这行代码更可能是易受攻击的代码。这一结果符合预期。

请添加图片描述

图10:检测到的缓冲区溢出漏洞的可视化

4.3 运行时间开销

  在本节中,我们使用40657个函数(即13687个易受攻击的函数和26970个非易受攻击函数)对VulCNN的运行时间开销进行了全面评估。给定一个新功能,VulCNN包括四个主要步骤来完成分类:图提取、句子嵌入、图像生成和分类。

4.3.1 图提取

  给定函数的源代码,VulCNN的第一步是提取其PDG。图11显示了数据集上图提取的运行时间开销,其中95%以上的函数可以在三秒内获得图。平均而言,构造函数的PDG需要1.71秒。

4.3.2 句子嵌入

  VulCNN的第二步是将所有代码行嵌入到相应的固定长度向量中。如图11所示,这个阶段非常快,只需要大约0.000489秒就可以完成PDG的句子嵌入。

4.3.3 图像生成

  在将所有代码行嵌入向量表示之后,VulCNN的第三步是应用中心性分析将新PDG转换为图像。图11显示了此步骤中VulCNN的运行时间开销。超过98%的PDGs能够在一秒内转换为图像,该阶段的平均运行时间开销为0.26秒。这样的结果表明,VulCNN可以有效地将PDG转换成图像。

4.3.4 分类

  VulCNN的最后一步是使用经过训练的CNN模型检测漏洞。CNN分类是VulCNN中所有阶段中最快的,完成图像分类只需要大约41微秒。

请添加图片描述

图11:VulCNN在不同阶段(秒)运行时开销的累积分布函数(CDF)

  此外,我们还将VulCNN的可扩展性与其他相当的系统进行了比较。我们排除了与Checkmarx、FlawFinder和RATS的比较,因为它们不是基于深度学习的方法,并且表现比其他五种基于深度学习方法更差。图12显示了TokenCNN、VulDeePecker、SySeVR、VulDeeLocator、Devign和VulCNN的平均运行时开销。至于TokenCNN,因为它只应用简单的词法分析来获取源代码标记,并使用CNN模型来检测漏洞,所以它是最快的。平均而言,完成数据集中函数的分析只需0.25秒。对于VulDeePecker和SySeVR,其切片生成阶段需要提取控制流图(CFG)、程序依赖图(PDG)和函数调用图(FCG),这导致了比VulCNN更低的可扩展性。对于VulDeeLocator,由于它是一个基于LLVM-IR的漏洞检测系统,因此需要首先编译源代码。编译阶段消耗大量时间,因此难以大规模检测漏洞。至于Devign,它结合了不同的代码表示(即抽象语法树(AST)、控制流图(CFG)、数据流图(DFG)和自然代码序列(NSC)),以实现准确的漏洞分析。由于这些代码表示的大量提取,Devign比VulCNN消耗更多的运行时间。

请添加图片描述

图12:TokenCNN、VulDeePecker、SySeVR、VulDeeLocator、Devign和VulCNN的运行时间开销比较

  总之,尽管VulCNN的可扩展性不如TokenCNN,但它比VulDeePecker和SySeVR快约4倍,比VulDeeLocator快约15倍,比Devign快约6倍。

4.4 实例研究

  本文的最初目标是在检测大规模源代码中的漏洞时同时实现准确性和可扩展性。因此,在本小节中,我们进行了一项案例研究,以检查VulCNN在现实世界大规模漏洞检测方面的能力。我们选择了三种广泛使用的开源产品作为测试对象:Libav、Xen和Seamonkey。这些产品的版本包括几个旧版本和最新版本。由此,我们可以报告旧版本中的漏洞是否已在最新版本中“默默”修补。

  表2是我们收集到的产品的汇总,这些产品中Joern能够成功分析的函数总数为600233个。换句话说,VulCNN总共分析了600233个函数,总共超过2500万行代码。

  由于这些代码量很大,我们采用并行处理来分析它们。具体来说,我们一次处理十个函数。总的处理运行时开销如图13所示,可以观察到最耗时的阶段是提取函数的PDG,该阶段占总处理运行时间的87%以上。在生成这60万个函数的PDGs之后,我们可以在大约253分钟内将它们转换为相应的图像。如此高的效率表明,VulCNN有能力扫描大规模源代码以发现新的漏洞。

请添加图片描述

图13:VulCNN处理超过2500万行代码的总运行时间开销

  实际上,我们的扫描结果也令人鼓舞,因为我们发现了73个漏洞。具体来说,我们首先使用我们收集的标记为40657个函数来训练CNN模型,其中包括13687个易受攻击的函数和26970个非易受攻击函数。然后,从表2中的2500多万行代码中生成的600233个图像被输入到训练好的CNN模型中。收集完VulCNN报告的所有警告后,我们进行手动分析,逐一将其与收集到的真实漏洞进行比较。如果发现两者属于同一模式,将被判定为真正的漏洞。分析结果显示,73个警告对应于NVD中已知漏洞的模式。在这些检测到的漏洞中,有17个漏洞已由供应商在相应产品的最新版本中“默默”修补,4个漏洞的代码已被删除,另外52个仍然存在于产品中。我们已经向他们的供应商报告了这些漏洞,并希望他们能够尽快发布修补版本。

表2:我们测试的开源软件概要

请添加图片描述

  由于页面有限,我们在网站中显示了旧版本产品的检测结果,并仅在本小节中显示了三个最新版本的检测结果(即表3)。我们发现的漏洞的详细信息包括NVD中对应的CVE ID、NVD中报告的易受攻击产品、NVD的发布数据以及目标产品中的易受攻击文件。从我们所选产品的六个旧版本中,我们检测到47个漏洞。从这些产品的三个最新版本中,VulCNN发现了26个漏洞。

表3:通过VulCNN从我们所选产品的最新版本中发现的漏洞

请添加图片描述

5 论述

5.1 对有效性的威胁

  SARD中标记的函数来自合成程序。这些合成函数可能不能代表整个程序。为了减轻威胁,我们将NVD中的一些真实漏洞和开源产品中的非易受攻击函数添加到数据集中。选择函数的最大行数以生成相等大小的图像可能会导致一些不准确。我们通过研究40000多个函数的代码行数以找到更好的阈值来减轻威胁。此外,检测开源产品(即Libav、Xen和Seamonkey)漏洞的不准确是不可避免的,因为VulCNN可能会导致一些误报。通过将检测到的漏洞模式与NVD中真实世界的漏洞模式进行深入比较,可以减轻威胁。

5.2 论述

5.2.1 比较工具的选择

  我们首先根据工具是否开源来选择候选项,然后根据工具使用的技术类型进行筛选。最后,我们选择了一个基于标记的工具(即TokenCNN)、一个基于切片的工具(例如VulDeePecker)、一种基于位码的工具(如VulDeeLocator)和一个基于图形的工具(比如Devign)。注意,由于SySeVR是VulDeePecker的改进版本,因此我们也选择它作为比较工具之一。此外,为了实现更全面的比较,我们还选择了三种传统的基于规则的工具(即Checkmarx、FlawFinder和RATS)。

5.2.2 中心性度量与图像通道颜色之间的关系

  构建图像的目的是为了便于使用基于图像的模型(即CNN)进行漏洞检测,同时保留程序细节。因此,我们的函数图像有三层(与常规图像的格式相同),但常规图像中的三种颜色和函数图像中的3种中心性度量之间没有严格的对应关系。

5.2.3 未来的工作

  从图13中的结果可以看出,VulCNN最耗时的阶段是提取函数的PDG,这一阶段占据了总处理运行时间的87%以上。在我们未来的工作中,我们计划设计一种新的静态分析工具或尝试其他静态分析工具(例如,Frama-C),以实现更高效的PDG生成。在VulCNN中,我们选择了度中心性、katz中心性和紧密中心性来开始我们的图像转换。在实践中,也可以采用其他不同的中心性来保留图形细节。我们计划使用不同中心性的不同组合来找到合适的组合,以在VulCNN中实现更有效的图像转换。此外,由于大多数漏洞检测系统都是封闭源代码,我们只将VulCNN与八种工具(即Checkmarx、FlawFinder、RATS、TokenCNN、VulDeePecker、SySeVR、VulDeeLocator和Devign)进行比较。我们将在今后的工作中对更多系统进行详细的比较分析。尽管VulCNN可以保持比相当工具更好的效率,但其TNR并不理想。换句话说,我们检测到的一些漏洞可能是误报。在我们未来的工作中,我们计划在检测到的漏洞上利用定向模糊来缓解这种情况。

6 相关工作

  已经提出了许多不同的漏洞检测方法,可分为两大类:基于代码相似性的和基于模式的。

  对于基于相似性的方法,可以从不同方面测量相似性,例如基于字符串的、基于树的、基于标记的、基于图的以及基于它们混合的。然而,它们只能检测克隆的漏洞,无法检测新的漏洞。为了应对这一挑战,设计了基于模式的技术。

  根据自动化程度,基于模式的工作可以分为三个子类别。1) 手动方法:人类专家手动生成漏洞模式,并使用它们来检测新的漏洞。在实践中,这些工具(如Checkmarx、FlawFinder和RATS)的检测效率很差,因为专家无法生成不同漏洞的所有模式。图9中的结果也显示了这种情况。2) 半自动方法:人类专家首先提取某些特征(例如,子树和API符号、导入和函数调用),然后将其输入传统的机器学习模型(例如,支持向量机和k近邻)以检测漏洞。3) 更自动的方法(即,基于深度学习的方法):由于深度学习可以自动从源代码中提取特征,因此它已用于检测源代码漏洞。例如,VulDeePecker首先通过切片程序收集代码小工具,然后将其转换为相应的向量表示。最后,它使用这些向量来训练双向长短期记忆(BLSTM)模型以检测漏洞。muVulDeePecker使用了VulDeePecker中的程序处理方法,并添加了代码注意力以检测多类漏洞。Devign应用通用图神经网络来检测漏洞。它包含一个新的卷积模块,可以有效地从学习的富节点表示中提取用于图级分类的有用特征。DeepWukong将程序语义提取为程序依赖图,并根据程序的兴趣点将其拆分为多个子图。然后将这些子图输入到图神经网络中,以训练漏洞检测器。

7 结论

  在本文中,我们提出了一种新的思想,该思想可以有效地将函数的源代码转换为图像,同时保留程序语义。据此,我们设计了一个可扩展的基于图的漏洞检测系统(即VulCNN)。对13687个易受攻击函数和26970个非易受攻击函数的数据集的评估结果表明,VulCNN优于八个最先进的漏洞检测器(即Checkmarx、FlawFinder、RATS、TokenCNN、VulDeePecker、SySeVR、VulDeeLocator和Devign)。为了验证VulCNN在大规模漏洞扫描方面的能力,我们对2500多万行代码进行了案例研究。通过扫描结果,我们发现了NVD中未报告的73个漏洞。我们已经向他们的供应商报告了这些问题,并希望他们能够尽快得到修补。

致谢

  我们要感谢匿名审稿人对提高论文质量的富有洞察力的评论。这项工作得到了国家科学基金重点项目U1936211的支持,以及国家科学基金会CCF-2146443的部分支持。我们也感谢西门子和支付宝对研究的支持。


总结

  以上就是本篇论文翻译的全部内容了,后续如果有时间,我会分享这篇论文的阅读笔记!

猜你喜欢

转载自blog.csdn.net/IronmanJay/article/details/130739876