FVD-DPM: Fine-grained Vulnerability Detection via Conditional Diffusion Probabilistic Models 论文笔记[上]

FVD-DPM: Fine-grained Vulnerability Detection via Conditional Diffusion Probabilistic Models

非常好的文章, 值得一读

1. Abstract

  1. 背景:

漏洞检测的背景就不赘述了

工作的目标就是

  • 细粒度漏洞检测, 具体是指切片粒度
  • 精确定位(到某一行)

这里简单解释一下这里粒度的含义, 文章把漏洞检测方法分为文件粒度, 函数粒度, 切片粒度

  1. 方法:

主要思想就是把生成式模型用在漏洞检测上, 把漏洞检测定义成生成式的问题

  • 首先为了包含代码的语义信息并且有良好的细粒度表示, 工作用一个图表示代码, 和传统的PDG, CPG等不一样, 工作提出了CJG(Code Joint Graph), 然后基于CJG和切片起点(具体哪些起点后面也会讲)生成切片,
  • 接着, 把一个生成式模型——条件扩散概率模型用在切片的图结构上, 利用图结构信息从高斯噪声中生成图节点的标签(大致解释一下标签的意思, 这个工作中一个图的结点是一个语句, 标签就是这个语句有无漏洞也就是图结点标签是1还是0), 具体方法后面会详细介绍

新颖的点

  • 一个是CJG考虑到了语句的自然排列顺序(一定会顺序执行的代码的顺序关系, 也就是代码块), 能保留一定的过程内代码逻辑和语义信息(和CG相对, CG是过程间的控制流关系), 是其他图没有考虑到的

  • 另外, 不同于直接通过掌握的信息预测是否有漏洞, 这个工作把漏洞检测等价成了一个图结构上的node标签的生成式问题, 也就是通过给定的图结构, 期望生成的漏洞的分布与真实漏洞的分布尽可能相似(这是拿生成式模型的目标来解释的)

  1. 实验

​ 在五个数据集上和九个sota漏洞检测方法进行对比, 摘要里没有写具体的效果, 后面再详细介绍

2. Motivation

现有的漏洞检测工具存在一些问题

​ 通过举一个漏洞例子的特点阐述动机, 举了一个典型的漏洞CVE-202338430, [CWE-125]在这里插入图片描述

ksmbd does not validate the SMB request protocol ID, leading to an out-of-bounds read.

1. 要漏洞检测, 肯定要精确的提取程序的语义(semantic)信息,

​ 漏洞和补丁代码语义明显不同, 但传统的方法不能完全捕捉到这种语义的变化

要考虑哪些语义信息? 这个例子可以看出来:

(1). 跨函数:

首先看10和23, 漏洞是跨函数的

​ 这个不多说了, 很多研究都会考虑到这一点, 跨函数的切片很多, 这不是本工作的贡献, 只是提到要考虑这个点, 说比较早的工作没有考虑到这一点

(2). **语句顺序,

看10和17行, 补丁把语句换了个位置

​ 这个补丁, 语义明显有改变, 语句在源代码中的自然排列顺序改变了, 由此看出代码自然顺序的重要性.
​ 所以这个工作结合PDG中的数据依赖, 控制依赖边, 函数调用边, 和这里说的顺序边, 提出了CJG

​ 但是, 我觉得这个例子举的有点牵强, 文章在这里也一笔带过, 这个例子确实有顺序在里面, 但是跟他定义的natrual order不是一个东西, 可能只是为了强调顺序的重要性, 这个例子中的顺序可能有更好的定义方法

2. 检测模型要能辨认CJG中的全局上下文信息

从例子中可以看到有漏洞的语句只有三个, 还被非常多的语句隔开了

可以看出

(1) 细粒度是有必要的

​ 细粒度的模型是有必要的, 漏洞语句在程序中占比很少, 这也是为什么要切片, 很多工作中都提到不赘述

(2) 全局信息是重要的

​ 传统的GNN每个结点只考虑了距离2以内的邻接结点, 但是从例子中可以看出, 两个漏洞语句被很多语句隔开, 很有可能在图中这两个结点(语句)不是距离2以内的邻居,
​ 因此使用GNN的方法无法推断一个图中距离很远的可疑漏洞点的信息是否能影响到另一个点, 从而阻碍了漏洞检测的能力,
​ 而这个工作中由于GAT(应用了注意力机制), 能够自适应的考虑到全局的结点信息

3. Method

1. 概览

在这里插入图片描述

主要分为两个阶段

  • 生成源代码的CJG, 然后使用程序切片技术提取切片, 文中的切片起了个名字叫GrVCs
  • 根据GrVCs的图结构构造一个有监督的条件扩散概率模型来预测GrVCs结点标签的分布

2. 细节: 阶段一: 特征提取

(1) 数据集及其CJG的的构造

上面说过了工作结合数据依赖(表现为DFG), 控制依赖边(表示为CFG), 函数调用边(表示为CG), 语句顺序边(表示为CS: Code Sequence), 和结点组成了CJG

1. CJG的边
  • 首先根据CVE信息在Github上得到相应的源代码,
  • 用Joern——一个自动化程序分析工具生成CFG(控制流图), DFG(数据流图), 然后得到PDG,
  • 将所有生成的图保存到neo4j(一个图数据库)里
  • 在数据库中查询所有函数调用的结点(neo4j中命名为Function Nodes)来构成CG(函数调用图)

文中具体没说CS是怎么构造的, 后来看了代码是查询CFG和CG, 没有跳转和函数调用, 中间能顺序执行的代码就顺着添加代码顺序边

2. CJG的结点

一个结点对应的是源程序中的一条语句

结点的内容有:

  • 源程序中文本形式的语句
  • 语句的类型, 这些类型是Joern中原本就定义了的, Joern定义了很多, 这个工作中就取了23种常用的类型作为CJG结点的类型, 如下:
    在这里插入图片描述
(2) 切片起点的选择和提取

为了更细粒度的表示漏洞程序, 还需要把CJG进行切片

程序切片的定义这里也不赘述了, 切片是需要一个切片起点的

  • SySeVR, VulDeePecker指出对API和库函数的错误使用是大部分漏洞产生的原因
  • 敏感变量(数组和指针)容易引起空指针引用, double free, 缓冲区溢出等漏洞, 对这些变量的检查在CppCheck, Flawfinder等工具中广泛使用
  • 从整数溢出漏洞也可以看出, 算术表达式也容易产生漏洞

因此切片起点选了这三种


具体的选择方法是, 根据结点类型和结点中的语句

结点类型是ExpressionStatement(表达式语句), 语句中包含"=", 就判断这是一个算术表达式结点

(3) 切片

根据提取的切片起点遍历CJG, 和一般的切片方法一摸一样, 不赘述

直接看一个例子

在这里插入图片描述

有这样一个函数, 第五行(把外面包的一层函数声明去掉对应的就是第三行)会导致拒绝服务, 是一个漏洞, 在右边是红色的结点,

图b左边是CJG, 紫色的边就是这个代码顺序边比如345, 中间没有调用, 也没有控制流, 是一个最长的顺序执行的代码块, 用紫色的边连起来了

其他的都比较直观

右边就是切片, 7被切掉了

(4) 初步的结点嵌入(就是代码嵌入)

把结点中的文本形式的语句, 拆成token, 在源代码数据集上训练Word2Vec保证其有特定领域的词汇知识, 然后把token输入到训练后的Word2Vec得到向量表示的Token序列, 然后对Token取均值, 得到语句的向量表示


3. 细节: 阶段二: 基于扩散模型的漏洞检测

在这里插入图片描述

这个方法实际是挪用ICML‘23的一个工作, (Jang et.al Diffusion probabilistic models for structured node classification. ICML’23)到漏洞检测里, 简单介绍一下这个方法是如何将扩散模型和图结构结合来学习漏洞标签的分布的


先简单介绍一下一般的扩散模型来直观理解一下, 扩散模型的训练分为两个过程, 1. 前向加噪过程 2. 条件反向去噪过程, 接下来看加噪和去噪的简介

在这里插入图片描述

加噪过程就是给真实世界分布(要学习的分布)的样本不断添加随机高斯噪声使数据逐渐失真, 通过对加噪过程的精妙设计, 使得样本从原始分布最终被构造成高斯分布的纯噪声.
在这里插入图片描述

而去噪过程是, diffusion model学习加噪的逆过程, 即学习预测加噪过程中每次添加的噪声, 从而具备从任意高斯噪声中预测噪声, 还原出真实世界数据(也就是学习真实数据分布)的能力,

在这里插入图片描述
在这里插入图片描述

本文中的扩散模型不太一样,

  • 上面提到本文的方法是有监督的, 加噪过程不需要标签, 而去噪过程是需要标签的. 具体怎么构造数据集留给后面的实验部分讲.
  • 一般的扩散模型的T是固定的且很大, 然后为了提高效率这里的T是随机的

具体看下面

1. 加噪过程
每一步的加噪

加噪过程的形式化定义如下

在这里插入图片描述

公式解释

先解释一下图中的符号, 若未经说明, q一律指加噪过程中的分布函数, p一律指去噪过程中的分布函数, y(0)是未加噪声的标签或者需要推断的输入, y(大T)是经过加噪得到的最终高斯噪声

T: 大写的T指的是diffusion总共进行T次加噪,

式(1): 加噪过程为了保证最终能够构造高斯分布被设计成了马尔可夫过程也就是(1)式表达的含义,

式(2): (2)式中等式左边指的是第t次添加的随机高斯噪声的分布, 右式是高斯分布的参数其中beta是个超参数, 能够控制最终高斯分布的方差, 之所以设计成(2)式这个模样也是为了保证不断加噪后最终能构造一个标准高斯分布

重参数

提一嘴采样这样一个抽样过程是不可微的, 不能反传梯度, 所以需要进行某些数学构造, 使得在不改变原来采样随机性及其分布的前提下, 把采样用等价但可微的形式表示出来, 这种技术叫重参数(reparameterization)

可以把从期望为miu, 方差为sigma正太分布抽取的样本Z构造成这样的形式

在这里插入图片描述

这样就使得抽样过程是可微的, \odot是是对样本空间数乘

最终总览

任意时刻的 可以由y(0)和beta表示

最终通过一系列的推导, 得到最终的高斯噪声y(T)的分布

在这里插入图片描述

大T次加噪后, 原来真实世界数据分布q(y(0))将变成(3)式中的样子, 当T足够大, 最终的噪声将接近标准高斯分布

2. 去噪过程
过程的形式化定义

去噪过程的形式化定义如下

在这里插入图片描述

去噪过程可以定义为一个条件分布, 如(4)所示, 给定随机高斯噪声y(T)和图结构(注意这和一般的扩散模型有区别), 预测整个加噪过程和原始数据的联合分布, 简单来说就是给定y(T)和图结构, 去噪过程可以预测加噪过程中的任何一步的噪声, 也可以预测真实数据

每一步的去噪经证明p(y(t-1)|y(t))也就是第t步去噪的逆过程也服从正态分布, 如(5)式所示


计算过程中分布的均值和方差

由于diffusion model的工作中已经证明, 加噪去噪过程分布越相似, 最终生成的越符合真实的分布, 为了衡量分布的相似度使用KL散度, 因此我们需要知道正态分布的均值和方差来最小化KL散度

其中(5)式中正态分布的均值, 由贝叶斯理论, 能推导出(8)式

在这里插入图片描述

由于方差表示比较复杂, 并且(Nichol et.al Improved denoising diffusion probabilistic models. In International Conference on Machine Learning, pages 8162–8171. PMLR, 2021.)指出均值能更有效的决定一个分布且前几步加噪更能影响变分下界(或者说模型性能的下限)

因此将方差定义为加噪过程中方差的加权平均, 这里的Kappa也就是权重定义为一个可学习的参数

在这里插入图片描述

在这里插入图片描述

现在问题只剩下(8)式中的Z_{theta}如何定义, 要将图结构映射到数域, 这需要图嵌入方法, 本工作使用的是GAT, 具体下部分再介绍

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值