Empirical Studies
这篇blog里我分享2篇code embedding领域与漏洞检测有关的empirical study
一.Learning Program Semantics with Code Representations: An Empirical Study
1.1.简介
这篇发表在IEEE International Conference on Software Analysis, Evolution and Reengineering (SANER 2022)上,主要做的是评估不同的代码表示在不同任务上的性能。
在这篇paper里,作者对比了Feature-based, Sequence-
based, Tree-based 和 Graph-based 代码表示在代码分类,漏洞分类和克隆检测3个任务上的性能。
作者提出了3个RQ:
-
RQ1:针对不同的任务是否有1个最优代码表示?具体来说,比较Feature-based, Sequence-based,
Tree-based 和 Graph-based 表示的性能。 -
RQ2:Tree-based 和 Graph-based 方法中生成node vector时可用的信息包括语句文本和结点类型,它们是否都适用于代码智能任务?这里作者比较了不同的node embedding策略。
-
RQ3:Graph-based方法包括CFG,CDG,DDG等图,它们对模型学习代码语义的贡献是否相等?作者这里比较了不同图结构的性能。
作者得出的结论包括:
-
在这3个任务上,Graph-based表示比其它表示性能更好。
-
在生成node向量时,node的文本信息比类型信息对学习代码语义更重要。
-
不同的任务需要特定的语义表示来获取模型最佳性能,但是结合诸如控制依赖、数据依赖多种语义依旧能取得较好的结果。
(paper artifact的github地址)
1.2.Overview
1.2.1.任务
-
代码分类(code classification):意在根据代码的功能对代码进行分类,具体来说,作者收集了OJ 数据集(TNCNN中的数据集),其中包含了104类的代码,总共52000个样本,每一类代码对应1种操作(翻转整数、查找最大/最小值)。
-
代码克隆(Code Clone):决定2个代码片段是否互为克隆,作者从OJ数据集中生成克隆对,同1类中的样本互为克隆,不同类的为非克隆对,作者随机生成了25000个样本并为它们选取1个克隆和非克隆样本组对,这个数据集被称为OJClone。
-
漏洞检测(Vulnerability Detection):作者用到了Devign中的数据集。
实验中作者用到了Joern工具,作者过滤了不能被正确解析的样本,数据集train,eval, test按照8:1:1的比例划分。
1.2.2.代码表示
-
Feature-based:使用TF-IDF向量化代码样本,并分别结合SVM,Naive-Bayes和XGBoost来分类代码。
-
Sequence-based:首先将代码解析为sub-token序列,比如token
get_int
会被拆分为get
和int
,分别结合LSTM,Bi-LSTM和Transformer来学习代码语义。 -
Tree-based:将代码解析为AST后采用Tree-LSTM直接处理AST或者采用Code2Vec生成Path集合。
-Graph-based:将代码解析为AST、CFG、CDG、DDG后根据不同策略结合它们分别结合GCN、GAT、GGNN来生成代码向量。
Joern生成的AST和图示例如下:
1.2.3.结点向量的生成
图/树中的每个结点包括类型信息和文本信息,生成初始结点向量时作者考虑了3种策略:
-
type embedding:用类型的one-hot向量
-
text embedding:将node text解析为sub-token序列并用BiLSTM来生成node向量
-
hybrid embedding:使用了1个全连接层来结合text embedding和type embedding
1.3.实验
作者采用acc和F1作为评估指标
1.3.1.RQ1
在这一部分,作者使用hybrid embedding来为Tree/Graph-based方法生成初始向量。
实验结果如下
可以看到, Graph-based方法是所有方法种表现最好的,而还可以看到Code2Vec在代码分类和漏洞检测上表现尚可,但是在克隆检测上不行,这可能是path-based方法并不适合这个任务,Code2Vec最初提出是用在方法名预测等任务上的。
1.3.2.RQ2
这部分作者对比了text embedding, type embedding和hybrid embedding应用在Tree/Graph-based方法上的性能,实验结果如下:
单独来看text embedding比type embedding用来表示代码效果更好,而结合2者更能提高模型的检测效果。当然,作者这里同个1个全连接层结合2种embedding向量,之后可以探索其它方式结合。
而这里hybrid embedding在漏洞检测上性能次于text embedding,除了embedding结合方式之外漏洞检测本身任务比其它任务复杂很多。尽管如此依旧可以认为hybrid是最好的embedding方式。
1.3.3.RQ3
探寻不同图结构对模型检测效果的影响,作者这里只用了GGNN,因为GGNN的效果最好,实验结果如下
可以看到,几乎所有任务中,CPG(AST + CFG + CDG + DDG)取得了最好的效果,而单独来看,代码分类中CFG取得最好的效果,漏洞检测中DDG取得最好的效果,克隆检测中CFG取得最好的效果。
1.4.Discussion
1.4.1.代码语义向量空间
作者这里用t-SNE对代码分类中,BiLSTM、Tree-LSTM和GGNN针对7类样本生成的代码向量进行降维后进行了可视化,结果如下:
可以看到边界的清晰度:GGNN > Tree-LSTM > BiLSTM
1.4.2.语义等价变换
作者随机挑选了2个漏洞代码,GGNN、Tree-LSTM和BiLSTM均能预测它有漏洞,而作者进行了语义变换,包括:
-
函数重命名
-
交换没有依赖关系的语句顺序
-
变量重命名为
变换后,BiLSTM预测错误,GGNN和Tree-LSTM预测正确,作者认为BiLSTM对代码token的顺序进行建模,不能很好地抗干扰,而Tree-LSTM和GGNN对代码对代码结构进行了建模,因而更加鲁棒。
1.4.3.分类结果的分析
作者分析了OJ数据集中GGNN分类准确率高的类别(Class 29, Class 66, Class 83)和相对较低的类别(Class 25, Class 52, Class 61),总结了程序中可能存在的5种复杂语义: Nested Loops, Multiple Loops, Pointer Operation, Do-While 和 Others/Basic。这些复杂语义不容易被神经网络学到,因而对准确率有一定影响。
二.Can Deep Learning Models Learn the Vulnerable Patterns for Vulnerability Detection?
2.1.简介
这篇paper发表在IEEE Annual International Computer Software and Applications Conference (COMPSAC 2022)
这篇文章主要探索深度学习模型是否能有效进行漏洞检测以及这些模型是否捕捉到了漏洞的关键pattern。
作者研究了4种结合attention机制的模型的漏洞检测能力,BLSTM-att、, Hierarchical Attention Network (HAN) 、Single Attention Network (SAN)、RGCN-att,其中前3种是Sequence-based模型,最后一种是Graph-based模型。
可用的漏洞数据集包括真实、半合成、合成3类,真实数据集有1个很大的问题是没有标注漏洞行(source点和sink点等等没有标注,现有的大部分根据diff标注只能标注fix位置),作者选择了合成数据集Juliet(SARD,Java数据集而不是C语言版本)来进行研究,Juliet中已经标注了sink点,作者进一步进行了手动标注,创建了Juliet+数据集。
在实验结果上,4种模型都取得了高于95%的F1分数,作者进一步分析了模型的attention分数,发现RGCN-att比其它3种模型更能捕捉到漏洞pattern,同时数据集更大、正负样本更平衡时模型效果更好。
(附上paper artifact的github地址)
2.2.漏洞检测方法
paper的工作架构如下,其中每个Java程序会被转化成跨函数DDG来作为代码表示,这也是这篇paper与其它工作的不同,首先分类的unit不是一个function而是1个program。
-
样本收集,在Juliet(SARD)中无漏洞方法的命名一般是
goodXXX
(一整个调用链都是goodXXX
加上别的,不会有badXXX
),有漏洞方法的方法名是badXXX
(整个调用链不会有goodXXX
),一个样本 c i = { f i , c o r e , f i , 1 , . . . , f i , n } c_i = \{f_{i,core}, f_{i,1}, ...,f_{i,n}\} ci={fi,core,fi,1,...,fi,n}, f i , c o r e f_{i,core} fi,core 是这个样本的核心方法,其它的是直接或间接被 f i , c o r e f_{i,core} fi,core 调用的方法。因此,在标注样本时, f i , c o r e f_{i,core} fi,core 包含字段bad
,那么这个样本就是漏洞样本,反之,正常样本。一般而言,Juiet中每个testcase包含1个漏洞样本,2个正常样本。
-
代码预处理,作者基于JavaParser实现了解析器,首先提取一个样本的调用链后,解析器构造每个方法的CFG,之后构造跨函数DDG,作为该样本的代码表示。
-
向量化:对于代码中的token作者用SySeVR中的符号化操作对变量名和函数名进行归一化,并用Word2Vec转化为50维向量。Graph中每个结点相当于一个token sequence,并附有类型信息,每个结点向量为text和type的concat,记为 [ s e _ s i , j ; t y _ s i , j ] [se\_s_{i,j}; ty\_s_{i,j}] [se_si,j;ty_si,j], s e _ s i , j se\_s_{i,j} se_si,j 为text向量, t y _ s i , j ty\_s_{i,j} ty_si,j 为类型one-hot向量。作者设计了下面2种方式获取 s e _ s i , j se\_s_{i,j} se_si,j。
- M1,序列卷积: s e _ s i , j = C o n v ( { w i , j , k } k = 1 T ) se\_s_{i,j} = Conv(\{w_{i,j,k}\}_{k=1}^T) se_si,j=Conv({wi,j,k}k=1T) ( w i , j , k w_{i,j,k} wi,j,k 为token向量, T T T 为node中token数量)
- M2,BGRU + attention
用到的深度学习模型:
-
HAN,层次attention:首先将DDG中的node按拓扑序排成node序列,对每个node先用M2(BGRU+att)的方式获取node向量,然后用一个 sentence attention 层结合每个node向量计算代码向量。
-
SAN,单层attention:与HAN类似,先将node排序好,然后对每个node用M1(序列卷积)的方式计算node向量,再用 sentence attention 层计算代码向量。
-
BLSTM-att:与HAN类似,先将node排序好,然后对每个node用M2(BGRU+att)的方式计算node向量,然后用BLSTM-att计算代码向量。
-
R-GCN-att:用RGCN + node attention层计算代码向量。
2.3.实验
评估指标:
-
二分类: accuracy (A)、precision §、recall ®、 F1-score(F1)、false positive rate (FPR), false negative rate (FNR)
-
attention:Hit@k, Hit@k%,这个paper中解释的并不是很清楚,我猜测是top k(%)中覆盖的标注的漏洞结点的百分比,对于漏洞结点类型,黑样本中作者标注了
bad_source
和bad_sink
,白样本中作者标注了fix
,而作者进一步设计了2种hit指标bad_either
表示bad_source
或者bad_sink
和bad_avg
表示 average rank。
数据集中漏洞类型作者选择以下几个类型的漏洞
实验设计的RQ包括:
-
RQ1:4种模型的漏洞检测能力如何?(二分类)
-
RQ2:模型是否学习到漏洞pattern?(attention分数评估)
-
RQ3:在不同CWE漏洞类型上RGCN-att的attention评分如何?
2.3.1.RQ1
可以看到HAN模型取得的效果最好,不过总体来看这4个模型的F1分数都超过95%。
2.3.2.RQ2
attention分数中,RGCN-att表现的最好,之前F1最高的HAN反而attention分数低于RGCN-att,同时BSLTM-att的attention分数是最低的,表面它不能很好的学习到漏洞pattern。
2.3.3.RQ3
首先可以观察到在所有CWE上RGCN-att的 bad_source
hit远大于 bad_sink
,这可能是由于修复时数据集中更多是在 bad_source
中修复而不是 bad_sink
。同时,CWE190和CWE191中 bad_either
不如其它3种漏洞高可能是由于漏洞样本数量小于非漏洞样本。
因此,可以认为模型的attention受到样本数量,类别分布,正负样本特征不同点等等影响,所有,训练样本应当尽量满足:类别平衡,正负样本区别鲜明,样本数量足够。