Page 91 - 《软件学报》2020年第11期
P. 91
段旭 等:基于代码属性图及注意力双向 LSTM 的漏洞挖掘方法 3407
1.1.1 基于规则的源代码漏洞挖掘技术
基于规则的源代码漏洞挖掘方法具有较为悠久的发展历史,在 20 世纪 70 年代,SteveJohnson 就开发了 Lint
[6]
工具 ,其通过规则检查对 C 语言代码中存在的错误进行挖掘.在 2000 年,出现了通过简单的词法分析对代码漏
[2]
[7]
[1]
洞进行挖掘的工具 ITS4 ,但是其准确率较低.随后,Flawfinder 和 RATS 对词法分析方式进行了改进,它们对
每种类漏洞维护内建的特征库,然后通过词法分析算法对其中条目进行匹配,从而挖掘代码中的漏洞,其可以有
[8]
[9]
效地挖掘 API 误用 等问题导致的漏洞.在同期,也先后出现了例如 MOPS ,BLAST [10] 等基于逻辑推理的漏洞
挖掘工具,它们通过使用状态机对程序的结构进行表示,然后利用安全属性对状态机进行遍历,从而挖掘漏洞.
1.1.2 基于学习的源代码漏洞挖掘技术
近年来,机器学习和深度学习技术在计算机视觉、自然语言处理和推荐系统等领域被广泛应用,并且取得
了较好的成效.与此同时,由于机器学习和深度学习模型强大的特征学习和数据拟合能力,也逐渐被应用在漏洞
挖掘中,直接或间接地为漏洞挖掘提供服务 [5,11] .Yamaguchi 等人 [12] 使用从已知漏洞中获取 API 使用模式,然后
使用 TFIDF 和主成分分析等机器学习技术将 API 使用模式映射为向量,从而根据 API 使用模式之间的相似度
来推测漏洞,即与具有漏洞的 API 使用模式相似度高的 API 使用模式很可能也具有漏洞.Feng 等人 [13] 提出
Genius,其对已知漏洞的控制流图进行无监督聚类生成码本,然后根据该码本对程序构造特征向量,通过比较目
标程序和已知漏洞的特征向量的相似度,从而判定目标程序中是否存在漏洞.但是该方法由于涉及图匹配,效率
较低,并且相似性判定依赖聚类生成的码本,难以对新任务进行适应.为此,Xu 等人 [14] 在 Genius 的基础上提出
Gemini,其通过 Structure2vec 算法将控制流图转化为数字向量,然后训练孪生神经网络,判定目标程序与已知漏
洞是否相似,进而挖掘目标程序是否存在漏洞.该方法实现了比 Genius 更高的准确率和效率,并且可以通过迁移
学习快速地适应新任务.Li 等人 [15] 提出了 VulDeePecker,其根据程序中的 API 调用对程序代码进行切片,然后将
切片后的代码视作纯文本,使用词嵌入技术将其映射为向量,最后输入到双向 LSTM 中,判断被测程序是否具有
漏洞.Duan 等人 [16] 提出了 VulSniper,其使用代码属性图对代码进行建模,然后使用基于规则的方法将其编码为
特征张量,最后构建带有注意力机制的全连接网络,判断被测程序是否具有漏洞.该方法虽然能够在一定程度上
检测细粒度漏洞,但是其网络结构较为简单,仅由全连接网络构成,特征学习能力有待提高.同时,由于其没有对
程序进行切片,导致其难以对包含大量与敏感操作无关代码的程序进行处理.Grieco 等人 [17] 提出分别用静态分
析和动态分析的方法对程序进行静态特征和动态特征的提取,然后综合动态特征和静态特征,使用词嵌入技术
将其映射到含有语义信息的固定长度的向量中,并使用多层感知机进行训练和分类.Kim 等人 [18] 使用语法、语
义和控制流对程序源代码进行建模,并使用基于注意力机制的双向 LSTM 推断漏洞代码模式,并将进行漏洞定
位.Russell 等人 [19] 同时利用卷积神经网络和随机森林进行漏洞检测,其首先使用卷积和池化操作对程序源代码
进行表示学习,然后将习得的向量表示输入到随机森林中进行分类.
1.2 程序抽象图结构表示
在程序分析任务中,将程序抽象成图结构是一种常见的处理方式,其通过使用图数据结构对程序的语义属
性进行表示,从而实现更加有效地对程序进行分析.目前已有很多不同的图结构被提出,包括控制流图(control
flow graph,简称 CFG)、数据流图(data flow graph,简称 DFG)、抽象语法树(abstract syntax tree,简称 AST)、程序
依赖图(program dependence graph,简称 PDG)等.不同的图结构可以视为从程序的不同特征视角来描述程序,例
如,AST 描述了代码的语法结构,CFG 描述了程序的执行路径和控制依赖,而 PDG 描述了程序内的控制依赖和
数据依赖关系.
此外,由于程序的抽象图结构中包含充足的语义信息,利用抽象图结构进行程序分析是目前较为流行的趋
[3]
势.例如,TBCNN 将程序源代码建模为抽象语法树,然后根据抽象语法树的结构和节点类型进行基于树的卷积
和池化操作,实现对程序进行分类.Yu 等人 [20] 在抽象语法树的基础上加入细粒度的 Token 信息,并提出基于位置
的 Token 向量嵌入方法,用于代码克隆检测.SecureSync [21] 对程序生成抽象语法树和程序依赖图,并通过子图同
构判定程序代码中是否存在漏洞.针对子图同构时间复杂度较大的问题.Li 等人 [22] 提出了 4 种对搜索范围剪枝
的方法,有效地提高了搜索同构子图的效率.另外,有很多方法在已有图结构的基础上提出新的图结构,以适应