本论文相关内容
- 论文下载地址——IEEE Xplore
- 论文中文翻译——Systematic Analysis of Deep Learning Model for Vulnerable Code Detection
- 论文阅读笔记——Systematic Analysis of Deep Learning Model for Vulnerable Code Detection
前言
这篇文章不难,主要就是总结了当下的一些相关技术以及相关数据集,也算是之前学习的一个总结。下面就是本篇论文的全部阅读笔记!
漏洞代码检测的深度学习模型系统分析
摘要
本文作为一篇综述性文章,主要介绍深度学习模型在检测源代码漏洞方面的进展,主要有两个目的:
- 探索和理解用于源码漏洞检测的深度学习方法的有效性
- 对检测过程和实验特征进行总结
- 针对特定数据集对各类深度学习模型进行评估
I. 引言
随着技术迭代与软件数量/种类的不断增加,网络安全攻击的数量也在不断增加,最终导致软件漏洞的数量随着时间的推移而增加。1999年~2022年检测到的漏洞数量变化如图1所示。
软件漏洞普遍存在的原因主要有以下两点:
- 包含这些缺陷的开源软件和代码重用的广泛使用
- 互联网用户数量的增加
传统的漏洞检测系统包括:
- 基于规则的传统方法:此种方法需要人类专家手工生成规则,主要缺点包括:
- 不精确
- 资源密集型
- 耗时
- 对软件来说是主观的
- 完全依赖于专家的知识和经验
- 使用静态工具:如Checkmarx、Flawfinder等,主要缺点包括:
- 具有高的假阳性率
- 具有高的假阴性率
为了解决以上问题,可以使用深度学习方法来检测软件源代码中存在的漏洞。相较于传统的漏洞检测系统,深度学习方法的主要优点包括:
- 可以自动学习特征
- 泛化能力比人工确定特征更好
因此,漏洞检测模型的成功和有效性取决于深度学习模型中深度神经网络的复杂性,而不是传统机器学习中使用的特征选择。
A. 本次调查的贡献
本次调查的主要贡献如下:
- 扩展软件漏洞检测中的深度学习研究领域,并提供一个不同的视角
- 概述用于训练深度学习模型的数据集的性质,例如:合成代码、半合成代码和真实代码
- 研讨流行的源代码表示,以捕获未标记源代码的语义信息
- 总结漏洞检测中的深度学习模型及其评估指标
II. 研究方法
作为文献综述,肯定需要阅读多篇与本课题相关的文献,本文给出了一个“搜索过程”来检索相关内容的文献。具体的搜索关键字包括:
- 源代码漏洞检测
- 基于深度学习的软件漏洞检测
- 漏洞自动检测或发现
- 深度学习检测软件漏洞
有了搜索关键字后,需要在以下的科学数据库对相关内容的文献进行检索:
- IEEE Xplore
- arXiv e-Print Archive
- ACM数字图书馆
- 谷歌学术搜索
当然,也不是所有的相关文献都可以入选,因为有些文献的内容虽然相关,但是质量不高,所以本文也给出了一些筛选论文的标准,如表I所示:
最后的搜索结果如表II所示,按照初始关键字搜索出了很多的相关文献,但是按照筛选标准排除了一些论文后,最终得到10篇具有代表性的相关内容文献。
A. 相关回顾
在这之前,已经有很多人总结了此领域的相关技术,比如:
- Ghaffarian和Shahriari对用于检测和分析软件漏洞的传统机器学习和数据挖掘技术进行了广泛而详细的回顾
- Malhotra回顾了64项用于软件故障预测的机器学习技术
- Radjenovic等人对软件故障解决方案的软件度量进行了系统的文献综述
- M.Masum等人引入了一种新的基于贝叶斯优化的超参数自动优化框架,以确保最佳的深度神经网络架构。作者还介绍了一个基于特征选择的框架,采用不同的机器学习算法,包括基于神经网络的架构,对用于勒索软件检测和预防的安全级别使用以下分类器进行分类:
- 决策树(DT)
- 随机森林(RF)
- 朴素贝叶斯(NB)
- 逻辑回归(LR)
- 基于神经网络(NN)
- M.J.H. Faruk等人强调了基于人工智能(AI)的检测和预防恶意软件活动的技术
III. 源代码表示
源代码表示是指通过删除不必要的行、注释和空格,从而获取到关键的语法或语义信息。下面几种源代码表示是目前最先进的方法。
A. 抽象语法树(AST)
顾名思义就是使用树形结构来表示源代码中的语法结构和语义信息,具体结构可参照图2。当然,AST也可以是多叉树,可以利用AST解析源码中的上下文关系,并将源码划分为更小的部分方便训练输入。但是由于AST树结构通常十分复杂,所以粒度较大也是此方法的缺点之一。基于此思路提出了一种称为树-LSTM的RNN模型,自底向上计算整棵树所有AST子节点的输出,从而判断此部分源码是否包括漏洞。
此方法的具体实现可见:
-
论文中文翻译——A deep tree-based model for software defect prediction
-
论文阅读笔记——A deep tree-based model for software defect prediction
B. 代码小工具
所谓代码小工具,实际是指具有数据依赖性和控制依赖性的多行程序语句组合而成,关于代码小工具的具体示例可参见图3:
代码小工具的具体体现就是程序切片,其中程序切片又可以分为两种类型的切片:
- 前向切片:从外部输入(如文件o套接字)接收的代码片段
- 后向切片:通过分析程序的数据流和控制流对程序进行分解,重点关注库/API函数调用、数组或指针
此方法的具体实现可见:
-
论文中文翻译——VulDeePecker: A Deep Learning-Based System for Vulnerability Detection
-
论文阅读笔记——VulDeePecker: A Deep Learning-Based System for Vulnerability Detection
C. 代码属性图(CPG)
代码属性图(CPG)将以下几种数据结构合并:
- 抽象语法树
- 控制流图(CFG)
- 程序依赖图(PDG)
其实有点类似于上面讲的抽象语法树(AST),因为树形结构毕竟就是特殊的图,只不过代码属性图(CPG)还结合了其他的数据结构,这样可以获得更多的上下文相关信息,从而更准确的预测漏洞。本方法的具体实现包括:
- REVEAL漏洞预测框架:结合现有CPG添加数据流图(DFG),并利用修改后的CPG捕获代码中语义的附加上下文
- Devign:将AST、CFG、DFG和自然代码序列(NCS)的概念合并到一个联合图中,在源代码表示中采用了类似于CPG的方法
D. 词法表示
词法表示主要是从关键字、运算符、分隔符中抽取一部分标记作为词汇表,并排除不相关的代码,从而得到词法分析器。词法分析器可以将代码转换为以下三种不同类型的标记。最终可以将源代码表示为适合深度学习的输入向量。
- 字符串、字符和浮点值被划分为特定于类型的占位符
- 整数值被逐位数标记
- 来自公共库的类型和函数调用被映射到其泛型版本
此方法的具体实现可见:
-
论文中文翻译——VulDeePecker: A Deep Learning-Based System for Vulnerability Detection
-
论文阅读笔记——VulDeePecker: A Deep Learning-Based System for Vulnerability Detection
E. 基于语义的漏洞候选(SeVC)
本方法的重点在于从源代码中提取基于语法(SyVC)的漏洞语义(SeVC)特征,从而得到具有高度上下文关系的源代码表示。整个过程如下所示:
- 将源代码转换为包含多个连续标记的AST
- 遍历AST以找到与定义的漏洞语法匹配的代码元素,该语法被标记为SyVC
- 使用Joern工具提取每个SyVC的PDGs
- 通过程序切片将SyVCs转换为SeVCs,以捕获基于数据依赖性和控制依赖性的语句的语义关系
- 从程序间正向和反向切片生成程序切片,这些切片被转换为SeVCs
此方法的具体实现可见:
-
论文中文翻译——SySeVR A Framework for Using Deep Learning to Detect Software Vulnerabilities
-
论文阅读笔记——SySeVR A Framework for Using Deep Learning to Detect Software Vulnerabilities
IV. 深度学习模型
深度学习技术在图像分类中已经取得了成功,那么如何利用深度学习技术来减轻漏洞检测的工作量和提高检测准确性就是目前需要研究的内容。其中最重要的就是从文本(源代码)中提取特征,然后训练其模型来理解和检测软件中的漏洞,目前针对漏洞检测的深度学习模型主要包括CNN(卷积神经网络)和RNN(循环神经网络)。当然,这两个深度学习模型都十分复杂,不可能在这里讲清楚,毕竟这只是一个综述论文,关于这两个深度学习模型的学习可以关注我的后续博客,我会进行详细解读。
A. CNN(卷积神经网络)
CNN可以通过学习源代码中的模式和上下文之间的关系来提取特征并理解程序的结构,当模型提取到特征后,就可以对源码进行分类,即存在漏洞或者不存在漏洞。如图4所示就是一个典型的模型结构,以此示例简单总结此模型的应用。
- 使用3层的卷积核在原始输入上进行采样
- 将卷积层输出的特征图补全到原图的形状大小,目的是使特征图中的激活值能与输入原图对应
- 采用全局平均池化层将最后一个卷积层输出的每个特征图的激活值取平均
- 将这些均值的加权和作为 S o f t m a x Softmax Softmax层的输入
- 进行有无漏洞的判断
此模型的具体应用如下:
B. RNN(循环神经网络)
1. RNN(循环神经网络)
经典的RNN(循环神经网络)主要是通过提取比CNN更长的标记依赖性来获得上下文关系。一个RNN网络的简单示意图如下所示:
此网络在
t
t
t时刻接收到输入
x
t
x_t
xt,经过隐藏层
s
s
s后的值为
s
t
s_t
st,最终的输出值为
o
t
o_t
ot。其中最重要的一点在于
s
t
s_t
st的值不仅取决于
x
t
x_t
xt,还取决于
s
t
−
1
s_{t-1}
st−1。这样就可以获得源代码的上下文关系,从而进行源码漏洞分析。RNN的计算方法如下所示:
O
t
=
g
(
V
⋅
S
t
)
S
t
=
f
(
U
⋅
X
t
+
W
⋅
S
t
−
1
)
\begin{array}{l} O_{t}=g\left(V \cdot S_{t}\right) \\ S_{t}=f\left(U \cdot X_{t}+W \cdot S_{t-1}\right) \end{array}
Ot=g(V⋅St)St=f(U⋅Xt+W⋅St−1)
2. LSTM(长短期记忆网络)
LSTM是RNN架构的扩展版本,其又称为长短期记忆网络,LSTM网络包括三个“门”:输入门、输出门、遗忘门。一个LSTM网络中包括很多LSTM核,在介绍LSTM网络之前,先介绍LSTM核,因为LSTM网络是由LSTM核构成的,关于LSTM核的示意图如下所示:
这里首先介绍几个概念。在上面图中,设 ⊙ \odot ⊙表示以元素方式相乘, t a n h tanh tanh表示双曲正切函数 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), σ σ σ表示 s i g m o i d sigmoid sigmoid函数 1 1 + exp ( − x ) \frac{1}{1+\exp (-x)} 1+exp(−x)1。每个LSTM核(用 c c c表示)使用输入门 i i i(即输入数据)、遗忘门 f f f(即单元的状态流)和输出门 o o o(即模块的输出)来控制通过神经网络的数据流。
- 遗忘门 f f f:记忆细胞状态,选择性遗忘记忆细胞中的信息。也就是选择对训练有用的数据留下,对训练没用的数据丢弃。
- 输入门 i i i:将新的信息选择性的记录到新的细胞状态中。
- 输出门 o o o:将运算结果更新到下一个隐层。
在每次运算中,对于如何计算每一次的状态和输入输出结果公式一一列举如下,这个可以结合上面的示意图理解:
-
l l l层在 t t t时刻的输出 h t l h_{t}^{l} htl为:
h t l = o t l ⊙ tanh ( c t l ) , h_{t}^{l}=o_{t}^{l} \odot \tanh \left(c_{t}^{l}\right), htl=otl⊙tanh(ctl), -
时间 t t t时层 l l l的输出门 o t l o_{t}^{l} otl为:
o t l = σ ( W x o l x t l + W h o l h t − 1 l + W c o l c t l + b o l ) 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=σ(Wxolxtl+Wholht−1l+Wcolctl+bol) -
时间 t t t时层 l l l的LSTM核 c t l c_{t}^{l} ctl的状态为:
c t l = f t l ⊙ c t − 1 l + i t l ⊙ tanh ( W x c l x t l + W h c l h t − 1 l + b c l ) . 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(Wxclxtl+Whclht−1l+bcl). -
时间 t t t时层 l l l的遗忘门 f t l f_{t}^{l} ftl和输入门 i t l i_{t}^{l} itl计算如下:
f t l = σ ( 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 ) , i t l = σ ( 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 ) , \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} ftlitl=σ(Wxflxtl+Whflht−1l+Wcflct−1l+bfl),=σ(Wxilxtl+Whilht−1l+Wcilct−1l+bil),
其中 x t l x_{t}^{l} xtl是 l − 1 l− 1 l−1层 ( l > 1 ) (l>1) (l>1)的输入或网络输入 ( l = 1 ) (l=1) (l=1), W x i l W_{x i}^{l} Wxil, W x f l W_{x f}^{l} Wxfl, W x o l W_{x o}^{l} Wxol, W x c l W_{x c}^{l} Wxcl是连接 x t l x_{t}^{l} xtl与输入门、遗忘门、输出门和LSTM核输入的权重矩阵, W h i l W_{h i}^{l} Whil, W h f l W_{h f}^{l} Whfl, W h o l W_{h o}^{l} Whol, W h c l W_{h c}^{l} Whcl是连接 h t − 1 l h_{t-1}^{l} ht−1l的带有输入门、遗忘门、输出门和LSTM核输入的权重矩阵, b i l b_{i}^{l} bil, b f l b_{f}^{l} bfl, b o l b_{o}^{l} bol, b c l b_{c}^{l} bcl是输入门、遗忘门、输出门和LSTM核输入的偏置项。
以上就是一个简单LSTM核的运算过程。通过以上公式,我们就能利用上下文信息进行自然语言处理,以及对于漏洞的检测并解决RNN的梯度消失问题。若干LSTM核就构成了整个LSTM网络,关于LSTM网络的简图如下所示:
3. BLSTM(双向长短期记忆网络)
虽然LSTM可以帮我们完成一部分工作,但是对于我们漏洞检测的实际应用情况,我们不仅需要上文的信息,还需要下文的信息进行辅助分析。所以我们要使用BLSTM进行上下文分析,从而使漏洞检测的有效性更高。如果理解了LSTM,那么对于BLSTM也就好理解了,因为BLSTM也是由若干个LSTM核组成的,只是多了一个反向传播的过程,下面为BLSTM的网络结构,整个网络构成了一个无环图,每次的输出都需要考虑前后的因素,这样更适合利用上下文信息进行漏洞检测,同样使结果更具有鲁棒性。
4. GRU(门控循环单元)
GRU是LSTM的一个替代版本,主要由更新门和重置门这两个门构成,这两个门不仅可以提高效率还可以解决RNN中的梯度消失问题。GRU的结构如下图所示:
- 更新门:决定应该将之前步骤中的多少信息传递给未来的时间步骤
- 重置门:结合新的输入和以前的记忆,并决定过去信息的多少记忆应该被遗忘
此模型的具体应用如下:
-
论文中文翻译——VulDeePecker: A Deep Learning-Based System for Vulnerability Detection
-
论文阅读笔记——VulDeePecker: A Deep Learning-Based System for Vulnerability Detection
V. 数据集
源码漏洞检测数据集主要是C/C++语言的源代码,了解这些数据集对于后续的学习有着很大的帮助。其中各类数据集的分布情况如图2所示:
A. NVD和SARD
此类数据集主要包括两种数据:
- 软件保障参考数据集(SARD):包含生产、合成和学术安全缺陷或漏洞
- 国家漏洞数据库(NVD):包含生产软件中的漏洞
此数据集主要由C/C++程序和软件产品组成,具体的易受攻击和非易受攻击的代码分布可以参见图2,其中具体包括:
- 10440个缓冲区错误漏洞(CWE-119)
- 7285个资源管理错误漏洞(CWE-399)
B. Draper VDISC
Draper VDISC数据集包括127万个函数的源代码,主要由C/C++代码构成,并通过潜在漏洞的静态分析进行标记。此数据集是从各类开源软件中挖掘得到的,具体的易受攻击和非易受攻击的代码分布可以参见图2。主要来源包括:
- Debian Linux Distribution:由精心管理和仔细挑选的代码构成
- GitHub上的公共git存储库:由数量更大、种类更广(通常质量更低)的代码构成
- NIST Samate项目的SATE IV Juliet测试套件:由118个不同的常见漏洞枚举(CWE)漏洞的合成代码示例构成
C. REVEAL
此数据集主要包含C/C++源代码,是一个维护良好的公共项目,具体的易受攻击和非易受攻击的代码分布可以参见图2。其中的漏洞主要来自:
- Linux Debian内核
- Chromium开源项目
D. FFMPeg+Qemu
FFMPeg+Qemu是一个从Github存储库收集的平衡的真实世界数据集,并且该数据集的标记是基于提交消息和领域专家手动完成的。具体的易受攻击和非易受攻击的代码分布可以参见图2。 此漏洞数据集主要由以下4个大型C语言开源项目组成:
- Linux内核
- Qemu
- Wireshark
- FFMPeg
VI. 挑战和未来工作
本综述主要总结了目前一些先进的漏洞检测系统以及可用于漏洞检测的深度学习模拟,以及一些专用于漏洞检测模型训练或评测的数据集。但是目前本方向的研究仍有一些局限性,作者针对数据集以及深度学习模型都提出了一些目前存在的挑战,并针对目前存在的问题指出了未来的研究方向。
A. 数据集
目前存在的局限性:
- 缺乏涵盖大多数CWE漏洞的标准化基准数据集
- 无法为基于深度学习的模型的评估制定统一和标准化的度量
- 易受攻击代码与非易受攻击的代码的比例失衡
未来的研究方向:
- 开发标准化基准数据集解决基本真实数据集问题
- 平衡数据集中易受攻击代码和非易受攻击代码的比例以解决模型过拟合问题
B. 深度学习模型
目前存在的问题:
- 模型是否准确?
- 漏洞预测是否可靠?
- 在特定的源代码中对易受攻击或非易受攻击进行分类的原因是什么?
目前解决以上问题的方法:
- 使用LIME创建神经网络的线性模型以进行简单解释
- 将代码注意力引入源代码表示,并定量测量深度学习模型中所有神经网络中对特定网络的关注程度
VII. 结论
本文作为一篇综述文献,总结了目前深度学习应用于漏洞检测方向的研究内容,主要贡献如下:
- 对最先进的源代码表示进行了详细的总结
- 总结了当前适用于训练和评估基于深度学习的漏洞检测模型的数据集
- 对用于源代码漏洞检测的深度学习模型的形成进行了概述
- 指出了该研究领域的挑战和未来工作的方向
总结
本文作为一篇综述性论文,并没有什么技术上需要总结的,但是有些知识我作为补充内容写到阅读笔记了,肯定写的不是特别详细,这个就要等我以后慢慢总结了,总之这篇文章作为复习和总结还是不错的。下篇博文见!