目标,识别程序中是否有漏洞。如果有,定位漏洞的位置(这个放到今天都算研究的热门话题)。实验用到的数据集地址:VulDeePecker,包括了61,638个code gadget。漏洞类型包括CWE-119和CWE-399。
作者提出了一个code gadgets来作为程序中间表示。code gadgets是由一些代码行(一行一行的代码,VulDeePecker是基于code gadget分类的。一个目标程序可能包含多个code gadget,一个code gadget被分类为有漏洞,那么,该code gadget中所有的代码行都有问题)组成的程序声明,这些代码行之间有语义(数据流,控制流)相关。
code gadget的生成和key point有关,key point某种程度上是一个漏洞的中心点。key point可以但不限于是:
key point和漏洞之间是多对多的关系,作者这里只研究library/API function calls与相关的code gadget。
示例代码:
void
test(char *str)
{
int MAXSIZE=40;
char buf[MAXSIZE];
if(!buf)
return;
strcpy(buf, str); /*string copy*/
}
int main(int argc, char **argv){
char *userstr;
if(argc > 1) {
userstr = argv[1];
test(userstr);
}
return 0;
}
产生code gadget的步骤如下:
这里library/API function calls分为
recv
函数strcpy
forward library/API function calls直接从外部接收输入很容易直接造成漏洞,而backward library/API function calls会受到与其参数有关的传参语句的影响。
program slice最初是表示程序中与一个变量或者程序点相关的语句,这里是与library/API function calls的参数相关的语句。
program slice也分为
以上面的示例代码为例,library/API调用是strcpy(buf, str);
,参数包括 buf
和 str
,buf
又与MAXSIZE
有关。str
是函数test
形参,在main
函数中userstr
作为实参传入test
,userstr又可以追踪到userstr = argv[1];
char *userstr;
2句。
所以program slice包括
test(char *str)
int MAXSIZE=40;
char buf[MAXSIZE];
strcpy(buf, str); /*string copy*/
main(int argc, char **argv)
char *userstr;
userstr = argv[1];
test(userstr);
2个backword slice,可以看到1个slice对应一个函数。而1个库函数调用可能会生成多个slice。
生成code slice的时候用到了checkmarx生成的数据依赖图(data dependency graph)
将上面针对一个库函数调用提取到的每个slice拼接成code gadget
每个code gadget都必须打上标签。如果有漏洞,标1,反之,标0。
该步骤的目的是在训练神经网络的程序中启发式地获取一些语义信息。
采用以下步骤
VAR1, VAR2
这类符号化后的变量名FUNC1, FUNC2
这类符号化后的函数名首先将符号化后的code gadget用词法分析器解析为token序列,token种类包括identifiers, keywords,operators, symbols
。
比如,一个一行code gadget strcpy(VAR5,VAR2);
词法分析后就成了"strcpy" , "(" , "VAR5" , "," , "VAR2" , ")" , ";"
这会带来一个很大的token词库。这里用word2vec
将token向量化。(感觉fasttext
更好,可以利用符号化变量名的信息)
之后用 Bi-LSTM + Dense
解析token序列并分类。
这里作者将token序列的长度固定为 τ \tau τ
SySeVR也是VulDeePecker团队的研究成果,主要针对VulDeePecker存在的以下问题
作者这里提出了2个概念
该框架合称为SySeVR:基于语法,语义和向量的表示。
在这篇paper中,作者用到了比VulDeePecker更大的数据集:SySeVR,包括了126种漏洞,VulDeePecker选择Bi-LSTM作为网络架构,SySeVR选择Bi-GRU。
该部分输入包括
输出包括
定义1:
一个程序 P P P 由一系列的函数 f 1 , . . . , f n f_1, ..., f_n f1,...,fn 组成。而函数 f i , 1 ≤ i ≤ n f_i, 1 \leq i \leq n fi,1≤i≤n 由一系列的 statement s i , 1 , . . . , s i , m i s_{i,1}, ..., s_{i,m_{i}} si,1,...,si,mi 组成。 而statement s i , j , 1 ≤ j ≤ m i s_{i,j}, 1 \leq j \leq m_i si,j,1≤j≤mi 由一系列token t i , j , 1 , . . , t i , j , w i , j t_{i,j,1}, .., t_{i,j,w_{i,j}} ti,j,1,..,ti,j,wi,j 组成。其中token类型包括 identifiers, operators, constants, keywords, 可由词法分析获取。
给定一个函数 f i f_i fi 的AST(可由其它方式生成)。AST每个叶子结点对应一个token t i , j , g t_{i,j,g} ti,j,g, 非叶子结点对应一个statement或者 s i , j s_{i,j} si,j 或者 s i , j s_{i,j} si,j 内部多个连续的token。
直观上,一个SyVC是一个token(对应于一个叶子结点)或者由多个连续的token(对应于一个非叶子结点)组成,如下图红框标出的部分。
定义2:
给定statement s i , j s_{i,j} si,j, 定义
SyVCs转换为SeVCs需要用到program slice技术,这就用到了程序依赖图(PDG),PDG又用到了数据依赖图(data dependency)和控制依赖图(control dependency)。
给定程序源代码 P = { f 1 , . . , f n } P = \{f_1, .., f_n\} P={f1,..,fn}, 对于函数 f i f_i fi。
f i f_i fi 的CFG(控制流图)为图 G i ( V i , E i ) G_i(V_i, E_i) Gi(Vi,Ei)。 V i = { n i , 1 , . . , n i , c i } V_i = \{n_{i,1}, .., n_{i, c_i}\} Vi={ni,1,..,ni,ci} 每个结点 n i , j n_{i,j} ni,j 表示一个statement或者一个control predicate(不太理解这个概念), E i = { ϵ i , 1 , . . . , ϵ i , d i } E_i = \{\epsilon_{i,1},..., \epsilon_{i, d_i}\} Ei={ϵi,1,...,ϵi,di} 中每个边 ϵ i , j \epsilon_{i,j} ϵi,j 表示结点之间的控制流向。
f i f_i fi 的数据依赖:给定 f i f_i fi 的CFG G i G_i Gi。 若其中2个结点 n i , j n_{i,j} ni,j 和 n i , l n_{i,l} ni,l 有下面关系, n i , l n_{i,l} ni,l 计算出的值在 n i , j n_{i,j} ni,j 中用到了。那么 n i , j n_{i,j} ni,j 就数据依赖于 n i , l n_{i,l} ni,l。
f i f_i fi 的控制依赖:这部分有点绕。给定 f i f_i fi 的CFG G i G_i Gi。若其中2个结点 n i , j n_{i,j} ni,j 和 n i , l n_{i,l} ni,l 有下面关系
f i f_i fi 的程序依赖图(PDG): f i f_i fi 的程序依赖图为 G i ′ ( V i , E i ′ ) G_i^{'}(V_i, E_i^{'}) Gi′(Vi,Ei′), V i V_i Vi 和CFG的 V i V_i Vi 一样。 E i ′ E_i^{'} Ei′ 中每条边为一个控制依赖或者数据依赖。
SyVC的程序切片(Program Slice) p s i , j , z ps_{i,j,z} psi,j,z 由 f s i , j , z ′ fs_{i,j,z}^{'} fsi,j,z′ 和 b s i , j , z ′ bs_{i,j,z}^{'} bsi,j,z′ 合并得到。
定义SeVC:
与VulDeePecker一样,采用以下步骤符号化SeVC
V1, V2
这类符号化后的变量名F1, F2
这类符号化后的函数名和VulDeePecker一样,作者先用词法分析器将SeVC解析为token序列,之后用Word2Vec向量化token,之后用了多种神经网络模型(CNN,RNN,Bi-LSTM,Bi-GRU等)向量化序列并分类(分类是针对SeVC而不是Program或者function)
针对VulDeePecker的改进主要是可以识别出code gadget包含的漏洞种类,并改进了code gadget的提取方式,并同时提取一个code attention。这里作者同样只分析库函数调用引起的漏洞(library/API function call)
相关概念
program statement 和 token
一个程序源代码 P = { p 1 , . . . , p ϵ } P = \{p_1, ..., p_\epsilon \} P={p1,...,pϵ}, p i p_i pi 是一个statement
p i = { t i , 1 , t i , 2 , . . . , t i , w } p_i = \{t_{i,1} ,t_{i,2} ,..., t_{i,w}\} pi={ti,1,ti,2,...,ti,w}, t i , j t_{i,j} ti,j 为1个token,token类型包括variable, function, constant, keyword ,operator等等。
数据依赖(data dependency,和SySeVR有点不一样)
给定一个程序源代码 P = { p 1 , . . . , p ϵ } P = \{p_1, ..., p_\epsilon \} P={p1,...,pϵ}, 一个variable token t i , j t_{i,j} ti,j 在statement p i p_i pi 中定义,若 t i , j t_{i,j} ti,j 在 p u p_u pu 被使用, 那 p u p_u pu 数据依赖于 t i , j t_{i,j} ti,j
控制依赖(control dependence)
2个statement p i p j p_i \; p_j pipj。如果 p i p_i pi 的执行结果会影响 p j p_j pj 是否执行, 那么 p j p_j pj 控制依赖于 p i p_i pi
code gadget
给定一个statement p v p_v pv,假设 p v p_v pv 中有 m m m 个函数调用。 f v i f_{v_i} fvi 是 p v p_v pv 中的一个函数调用。 f v i f_{v_i} fvi 的参数token 包括 { t v i , x 1 , . . . , t v i , x η } \{t_{v_i,x_1} , ..., t_{v_i,x_\eta}\} {tvi,x1,...,tvi,xη}。 statement p v p_v pv 中对应 f v i f_{v_i} fvi 的code gadget表示为 s v i s_{v_i} svi, 为statement集合 P P P 的一个子集合,其中每一个statement 要么数据依赖于一个参数token要么控制依赖于 p v p_v pv。
code attention
给定对应statement p v p_v pv 中函数调用 f v i f_{v_i} fvi 的 code gadget s v i s_{v_i} svi。 R = { r k } 1 ≤ k ≤ h R=\{r_k\}_{1 \leq k \leq h} R={rk}1≤k≤h 为描述漏洞语法特征的规则集合。code attention c v i c_{v_i} cvi 为 code gadget s v i s_{v_i} svi 中能够匹配的上 R R R 中一条规则的子集合(元素为statement)。
这里采用的是多分类, l a b e l = { 0 , 1 , 2 , . . . , m } label = \{0,1,2,...,m\} label={0,1,2,...,m}。 type 0 0 0 表示无漏洞, type i i i 表示第 i i i 种漏洞
提取code gadget的过程用到了SDG( System Dependency Graph),这个可由PDG获得
提取code gadget过程如下:
从code gadget 到 code attention
可以看到,code gadget包括了 1,2,3,4,5,6,7,8,9,10,15,16,17
行。而code attention只包括 2,4,5,6,7,8,16,17
行
检测阶段
可以看到针对code gadget的向量表示融合了code gadget和code attention
其它的处理过程和 VulDeePecker 大同小异
[1] Li Z , Zou D , Xu S , et al. VulDeePecker: A Deep Learning-Based System for Vulnerability Detection[J]. 2018.
[2] SySeVR: A Framework for Using Deep Learning to Detect Software Vulnerabilities[J]. IEEE Transactions on Dependable and Secure Computing, 2021, PP(99):1-1.
[3] Zou D , Wang S , Xu S , et al. u \\u uVulDeePecker: A Deep Learning-Based System for Multiclass Vulnerability Detection[J]. arXiv e-prints, 2020.