Interpreting Deep Learning-based Vulnerability Detector Predictions Based on Heuristic Searching
一.背景
有许多静态代码分析方法需要专家编写规则来检测代码中是否出现问题,而DL(deep learning)方法会比规则匹配更有效。尽管有效,但DL方法只能分类(0:non-vulnerable,1:vulnerable),而不能告诉你为什么,说不出DL模型学到了什么特征。所以在为cause, detection, fix等工作提供deep insights的时候解释工作就显得非常重要。
现在主要有3种解释方法解释其它领域的DL方法
-
hidden neuron analysis
通过 hidden layer outputs 和 gradient values 来分析重要的特征,但这些方法对模型有依赖(model-dependent, relies on the model structure),所以只对特定类型的模型有效。 -
model simulation
这种方法采用代理模型(比如决策树)来近似一个复杂的target模型。代理模型本身具备可解释性,但这类方法很难衡量代理模型和target模型之间的 behavioral gap。 -
local interpretation
这种方式主要在寻找特定的example的一些决策边界。这种方式需要假设样本的特征之间是相互独立的。
这里作者提出了一个解释方法,这种方法针对特定的样本,提取一些重要的token来描述为什么该样本被分类为1或0。
- 这个方法是模型无关(model-agnostic),意味着这个方法可以应用到其它DLVD任务中。
- 这个方法不假设模型决策边界是线性的,也不假设特征之间彼此相互独立。
- 它通过扰动样本的方式寻找重要token,扰动的时候会考虑特征之间的相关性。
作者主要解释VulDeepecker和SySeVR,这2个方法是token序列层面的分类方法,详细可以参考基于Slice-level程序表示的漏洞检测。
二.Deep Learning-Based Vulnerability Detection(DLVD)
对于DLVD任务,作者总结了以下4步:
-
Generating code fragments
一个code fragment为一些statement(语句)的集合,针对1个文件分类目标太大,所以通常会进行更细粒度的检测,通常一个code fragment是一个function或者是一个program slice(可以跨function也可以不跨)。通常数据集的标记也是基于code fragment的。 -
Transforming code fragments into vectors
这一步就是将上面的code fragment向量化,向量化方式有很多种,可以将code fragment直接表示成token序列,来生成序列向量,做序列分类。也可以生成一个程序图(比如CPG),生成图向量,做图分类。这里主要讨论基于token序列的。 -
Training a deep learning model
如果是基于token序列的表示,那么需要训练一个RNN或者CNN模型来做分类任务,比如BGRU, BLSTM等模型。 -
Detecting vulnerabilities
将code fragment分类为vulnerable或者not vulnerable。
作者这篇文章里用到了以下概念
Notation(概念) | Description(描述) |
---|---|
x i x_i xi | x i = ( x i , 1 , . . . , x i , n ) x_i = (x_{i,1},...,x_{i,n}) xi=(xi,1,...,xi,n) 是数据集第 i i i 个样本的程序表示(原文是feature representation),即一个长度为 n n n 的token序列。 x i , j x_{i,j} xi,j 为1分token。 |
x i ′ x_i^{'} xi′ | 通过扰动 x i x_i xi 获得的第 i i i 个样本的程序表示。 |
x i , − j x_{i,−j} xi,−j, x i , − J x_{i, -J} xi,−J | x i , − j = ( x i , 1 , . . . , x i , j − 1 , x i , j + 1 , . . . , x i , n ) x_{i,−j} = (x_{i,1},...,x_{i,j−1},x_{i,j+1},...,x_{i,n}) xi,−j=(xi,1,...,xi,j−1,xi,j+1,...,xi,n) 是通过删除 x i x_i xi 中第 j j j 个token x i , j x_{i,j} xi,j 获得的程序表示。 x i , − J x_{i, -J} xi,−J 通过删除 token序列 J J J 中所有token获得的样本。 |
x i , + j x_{i,+j} xi,+j, x i , + J x_{i, +J} xi,+J | x i , + j = ( x i , 1 , . . . , x i , j − 1 , x i , j + δ i , j , x i , j + 1 , . . . , x i , n ) x_{i,+j} = (x_{i,1},...,x_{i,j−1},x_{i,j} +\delta_{i,j},x_{i,j+1},...,x_{i,n}) xi,+j=(xi,1,...,xi,j−1,xi,j+δi,j,xi,j+1,...,xi,n) 是通过对第 j j j 个token添加噪声 δ i , j \delta_{i,j} δi,j 获得的程序表示,而 x i , + J x_{i, +J} xi,+J 为通过对token序列 J J J 中所有token添加噪声获得的程序表示。 |
M M M | DLVD模型,需要解释的模型。 |
M ( x i ) M(x_i) M(xi), M y ( x i ) M_y (x_i ) My(xi) | M ( x i ) M(x_i) M(xi) 是 M M M 对 x i x_i xi 预测的类别, M y ( x i ) M_y (x_i ) My(xi) 为预测的类别 y y y 的概率,比如 M 1 ( x i ) M_1(x_i) M1(xi) 表示 x i x_i xi 包含漏洞的概率。 |
φ i \varphi_i φi | φ i = ( x i , α 1 , . . . , x i , α γ ) \varphi_i = (x_{i,\alpha_1} ,...,x_{i,\alpha_\gamma}) φi=(xi,α1,...,xi,αγ) 是一个解释方法选出的 γ \gamma γ 个 x i x_i xi 中重要的token,并降序排序。 |
ϕ i \phi_i ϕi | ϕ i = ( x i , α 1 ′ , . . . , x i , α γ ′ ) \phi_i = (x_{i,\alpha_1^{'}} ,...,x_{i,\alpha_\gamma^{'}}) ϕi=(xi,α1′,...,xi,αγ′) 是一个分类模型 M M M 选出的 γ \gamma γ 个 x i x_i xi 中重要的token,并降序排序。 |
τ \tau τ | 关于模型 M M M, τ \tau τ是一个绝对2个token是否彼此关联的阈值。 |
G p G_p Gp | G p = ( C p , 1 , . . . , C p , ξ p ) G_p = (C_{p,1},...,C_{p,\xi_p}) Gp=(Cp,1,...,Cp,ξp) 是一个token combination序列,token combination C p , j = ( x i , t 1 , . . . , x i , t κ ) C_{p,j} = (x_{i,t_1} ,...,x_{i,t_κ}) Cp,j=(xi,t1,...,xi,tκ) 是一个token序列 |
I p , x i , α j ′ I^{′}_{p,x_i,\alpha_j} Ip,xi,αj′, I x i , α j I_{x_i,\alpha_j} Ixi,αj | I p , x i , α j ′ I^{′}_{p,x_i,\alpha_j} Ip,xi,αj′ 是token x i , α j x_{i,\alpha_j} xi,αj 在 G P G_P GP 中的重要指数。而 I x i , α j I_{x_i,\alpha_j} Ixi,αj 是 x i , α j x_{i,\alpha_j} xi,αj 在 x i x_i xi 中的重要指数。 |
下面则是在一个代码中的重要token,它被分类为1
下面是关于为何如此分类的解释
三.解释框架
解释方法输入是模型
M
M
M 和分类样本
x
i
x_i
xi,解释框架包括3步
3.1 Heuristic searching
这一步的目的是获取 γ \gamma γ 个重要的token φ i = ( x i , α 1 , . . . , x i , α γ ) \varphi_i = (x_{i,\alpha_1} ,...,x_{i,\alpha_\gamma}) φi=(xi,α1,...,xi,αγ)。获取的token序列会根据重要指数来排序。
这里用到的扰动方法主要是删除token。作者定义了如下公式来衡量token x i , h x_{i,h} xi,h 和token序列 x i , J x_{i,J} xi,J 的相关程度。
∣ M 1 ( x i , − J ) − M 1 ( x i , − J − h ) ∣ − ∣ M 1 ( x i ) − M 1 ( x i , − h ) ∣ |M_1(x_{i,−J}) − M_1(x_{i,−J−h})| − |M_1(x_i ) − M_1(x_{i,−h})| ∣M1(xi,−J)−M1(xi,−J−h)∣−∣M1(xi)−M1(xi,−h)∣
主要是捕获删除一个特定的token和删除一个token和一个token序列对分类结果造成的damage的对比。
在搜索 γ \gamma γ 个重要的token时,如果采用暴力方式搜索,那么时间复杂度为 n × ( n − 1 ) × ⋅ ⋅ ⋅ × ( n − γ + 1 ) n \times (n −1) \times···\times (n − \gamma +1) n×(n−1)×⋅⋅⋅×(n−γ+1),只能适用于 γ \gamma γ 值很小的时候。所以在这里,作者用了一个启发式的搜索策略。一个好的搜索算法会考虑到token之间的相关系,每个token可能都不是独立存在的,这就引出了token combinations的概念, token combination C = ( x i , t 1 , . . . , x i , t κ ) C = (x_{i,t_1} ,...,x_{i,t_κ}) C=(xi,t1,...,xi,tκ),其中, x i , t h x_{i,t_h} xi,th 会和 C C C 中其它token相关联。
作者提出了如下算法来搜索 φ i \varphi_i φi,其中。
- 将 x i x_i xi 扰动为 x i ′ x_i^{'} xi′ 时, ∣ ∣ x i ′ − x i ∣ ∣ ≤ Θ ||x_i^{'} − x_i || \leq \Theta ∣∣xi′−xi∣∣≤Θ。 ∣ ∣ . ∣ ∣ ||.|| ∣∣.∣∣ 表示L1正则化, Θ \Theta Θ 为一个限定值(这里应该是指删除的token数量)。
- 搜索算法涉及到 N N N 个token combinations,表示为 G 1 , . . . , G N G_1,...,G_N G1,...,GN, G p = ( C p , 1 , . . . , C p , ξ p ) G_p = (C_{p,1},...,C_{p,\xi_p}) Gp=(Cp,1,...,Cp,ξp)。每个token combinations的第一个combination不同,即 C p , 1 ≠ C q , 1 C_{p,1} \neq C_{q,1} Cp,1=Cq,1。
I
p
,
x
i
,
α
j
′
I^{′}_{p,x_i,\alpha_j}
Ip,xi,αj′ 和
I
x
i
,
α
j
I_{x_i,\alpha_j}
Ixi,αj 的计算方式如下:
I p , x i , α j ′ = { λ I C s i f x i , α j i n G p a n d i n d e x o f C i s o d d − λ I C s i f x i , α j i n G p a n d i n d e x o f C i s e v e n 0 i f x i , α j n o t i n G p I^{′}_{p,x_i,\alpha_j}=\left\{ \begin{array}{rcl} \lambda \frac{I_C}{s} & & if \; x_{i,\alpha_j} \; in \; G_p \; and \; index \; of \; C \; is \; odd \\ \\ -\lambda \frac{I_C}{s} & & if \; x_{i,\alpha_j} \; in \; G_p \; and \; index \; of \; C \; is \; even\\ \\ 0 & & if \; x_{i,\alpha_j} \; not \; in \; G_p \end{array} \right. Ip,xi,αj′=⎩⎪⎪⎪⎪⎨⎪⎪⎪⎪⎧λsIC−λsIC0ifxi,αjinGpandindexofCisoddifxi,αjinGpandindexofCisevenifxi,αjnotinGp
s s s 为序列 C C C 的长度。
I x i , α j = s i g n ( ∑ p = 1 N ∣ I p , x i , α j ′ ∣ ) I_{x_i,\alpha_j} = sign(\sum\limits_{p=1}^N |I^{′}_{p,x_i,\alpha_j}|) Ixi,αj=sign(p=1∑N∣Ip,xi,αj′∣)
这里面用到了一个searchTokenCombination
函数,定义如下,其中:
- 这里的目标是获取一个token序列 C C C,以删除最少的token可以翻转(flip)预测结果,比如分类结果从1到0。
- 如果反转不了结果,那就尽可能改变概率值( M 1 ( x i ) M_1(x_i) M1(xi))。
下图展现了一个token combinations G 1 G_1 G1 的计算过程。
下图展现了一个token的重要指数
I
x
i
,
98
I_{x_i,98}
Ixi,98 的计算过程。
3.2 Fidelity evaluation
这一步的目标是评估解释方法的保真度(fidelity)。通过比较解释方法选出的token序列 φ i \varphi_i φi 和模型 M M M 自己选出的token序列 ϕ i \phi_i ϕi 对比。
- φ i = ( x i , α 1 , . . . , x i , α γ ) \varphi_i = (x_{i,\alpha_1} ,...,x_{i,\alpha_\gamma}) φi=(xi,α1,...,xi,αγ)
- ϕ i = ( x i , α 1 ′ , . . . , x i , α γ ′ ) \phi_i = (x_{i,\alpha_1^{'}} ,...,x_{i,\alpha_\gamma^{'}}) ϕi=(xi,α1′,...,xi,αγ′)
这2个序列都根据重要指数降序排序过了。这2个序列的相似度越高,fidelity越高。而由于模型的黑盒特性, ϕ i \phi_i ϕi 通常很难获取。这里用如下方式衡量fidelity。
3.2.1 指标1
这里
- 给定一个样本集合 D D D(训练集),这里是从数据集中随机抽取的一部分。
- M M M 是一个已经训练好的分类模型。
- f i n e − t u n i n g fine-tuning fine−tuning 指用新的样本再训练模型。
- M ′ M^{'} M′ 是用 D D D 中的样本中除去解释器识别出来的重要token后构成的样本集合来对 M M M 进行 f i n e − t u n i n g fine-tuning fine−tuning 得到的模型。
- M + M^+ M+ 是用 D D D 中的样本直接对 M M M 进行 f i n e − t u n i n g fine-tuning fine−tuning 得到的模型。
然后
- 再给定一个样本集合 U = { x 1 , x 2 , . . . , x T } U = \{x_1, x_2, ..., x_T\} U={x1,x2,...,xT}(测试集)
- Class Change(CC)定义为 M ′ M^{'} M′ 和 M + M^+ M+ 在 U U U 上分类结果的差异,差异越大,fidelity越大。
作者定义如下概念
M ′ M^{'} M′(下), M + M^+ M+(右) | 0 | 1 |
---|---|---|
0 | T N ′ TN^{'} TN′ | F N ′ FN^{'} FN′ |
1 | F P ′ FP^{′} FP′ | T P ′ TP^{'} TP′ |
并用机器学习常用的 accuracy, FNR, FPR, F1 4个指标衡量CC。
3.2.2 指标2
作者还定义了一个 V P C VPC VPC(Vulnerable Probability Change)来衡量解释器识别出的token的重要性。
V P C = 1 T ∑ u = 1 T ( M 1 ′ ( x u ) − M 1 + ( x u ) ) 2 VPC = \sqrt{\frac{1}{T} \sum\limits_{u = 1}^T (M_1^{'}(x_u) - M_1^+(x_u))^2} VPC=T1u=1∑T(M1′(xu)−M1+(xu))2
M ′ M^{'} M′ 和 M + M^+ M+ 是在同一个训练集 D D D 下 f i n e − t u n i n g fine-tuning fine−tuning 的,标签都一样。但是 f i n e − t u n i n g fine-tuning fine−tuning M ′ M^{'} M′ 时,样本一些重要的token没了,所以它会学习其它token的特征。这就会导致 M ′ M^{'} M′ 和 M + M^+ M+ 分类结果的不同。 V P C VPC VPC 越大,获取的重要token越好。
3.2.3 指标3
这个指标叫end-to-end impact of fidelity
对于一个给定的测试集,针对 x i x_i xi 识别出的重要token集合为 φ i r \varphi_i^r φir,包含 r r r 个token。用 M ( x i , − φ i r ) M(x_{i,-\varphi_i^r}) M(xi,−φir) 和 M ( x i ) M(x_i) M(xi) 的结果来衡量Positive Classification Rate( P C R PCR PCR), P C R PCR PCR 越低越好。
3.3 Rules extraction
目标在于从解释方法中提取人类可以理解的规则。用决策树模型从抽取的重要token中学习模型推导过程。过程可分3步
3.3.1 Adding meaningful noise
对一个样本 x i x_i xi, x i , j x_{i,j} xi,j 是解释模型抽取的重要token之一,作者用以下策略构造 x i , + j x_{i, +j} xi,+j, 这里添加噪声 δ i , j \delta^{i,j} δi,j 时需要保留源代码的语法结构信息。
- 对于拥有连续值的常量,比如
float
,double
类型。用随机值替代。 - 对于非常量离散值(API调用,keywords,operators,分隔符),用同样类型的一些值替代。比如,
>
可以用<
,!=
,==
替代。数字10
可用5
,9
,11
,20
替代。
3.3.2 Constructing data for regression model
决策树的训练数据需要有training inputs(样本)和expected outputs(标签)。
- training input是之前扰动过的样本,而样本特征每一个维度表示一个重要token的一个change。
- expected output是 M M M 对扰动样本预测为vulnerable的一个概率值
用 x i , j ′ x_{i,j}^{'} xi,j′ 表示对token x i , j x_{i,j} xi,j 扰动过后的token,特征向量表示为
- 对于constant类型的token,直接用 x i , j ′ x_{i,j}^{'} xi,j′ 表示。
- 对于其它,用0表示扰动过,1表示没扰动过。
比如:
作者对上述代码进行了如下扰动, &&
替换为||
,100
替换为5
。5
属于constant,所以特征向量相应维度为5
,而||
不属于constant并且扰动过,所以相应维度为0
。
3.3.3 Training a regression model
对于一个样本
x
i
x_i
xi,作者训练一个决策树模型
T
r
e
e
i
Tree_i
Treei,每个非叶子结点表示一个重要token值得影响。决策树模型是可以理解的模型,一个if-then-else
路径对应一个规则。这可以帮助专家总结详细得规则。
一个示例如下:
代码:
Tree:
PDG的一个子图:
四.实验
作者提出了3个研究问题:
- 这个解释框架是否可以提取重要的token,有效性如何?
- 这个框架在end-to-end impact of fidelity的有效性如何?
- 是否能够抽取相应的规则来解释为什么一些样本会被分类为1(vulnerable)?
在解释方法中,作者选取了LEMNA和Kernel SHAP作为对比。
解释的对象是VulDeepecker + BiLSTM分类模型和SySeVR + CNN分类模型。
实验结果,对比的太多,只粘贴部分
4.1 Experiments for Answering RQ1
这里贴上与LEMNA和Kernel SHAP的对比结果。
VulDeepecker + BiLSTM
SySeVR + CNN
4.2 Experiments for Answering RQ2
不同方法PCR的值如下,这里PCR越低越好
VulDeepecker + BiLSTM
SySeVR + CNN
4.3 Experiments for Answering RQ3
作者采用如下方法从 T r e e i Tree_i Treei 提取 x i x_i xi 的规则,并和cherkmarx的规则作对比
五.Discussion
作者对自己的工作给出了以下局限性:
- 还不能解释为什么模型会认为这个token比另一个重要,这需要对神经网络模型"open the box",这是个大挑战。选出的token在安全层面也并不具备很好的解释性。
- 生成的规则都是主观的,生成规则的过程是用自动生成的决策树模型辅助专家编写规则,如何全自动编写规则是一大挑战。
- 对解释方法的评估是评估选取token的fidelity,如何评估规则的fidelity是一大问题。
- 这是一个 local interpretation 方法,即针对一个样本生成一个解释。一个解释结果也只对应样本而不是漏洞类型。所以,针对一个样本生成的规则不一定适用于其它样本。探寻 global interpretation 方法也是一个研究方向。
其它方面
- 这篇paper对VulDeePecker和SySeVR进行解释,而其它DLVD模型同样需要解释。
- 这里对样本的扰动是基于一个token,如何基于其它unit进行扰动(program statements 和 statement block 等)。
- 扰动的方法是删除token和添加噪声,其它方式也值得探寻。
六.参考文献
Zou, D. , Y Zhu, Jin, H. , H Y e, & Li, Z. . (2020). Interpreting deep learning-based vulnerability detector predictions based on heuristic searching. ACM Transactions on Software Engineering and Methodology, 30(2).