查看原文
其他

【源头活水】Devign: 基于GNN的源代码漏洞检测



“问渠那得清如许,为有源头活水来”,通过前沿领域知识的学习,从其他研究领域得到启发,对研究问题的本质有更清晰的认识和理解,是自我提高的不竭源泉。为此,我们特别精选论文阅读笔记,开辟“源头活水”专栏,帮助你广泛而深入的阅读科研文献,敬请关注。

来源:知乎—Hero
地址:https://zhuanlan.zhihu.com/p/433608077

Paper

Devign: Effective Vulnerability Identification by Learning Comprehensive Program Semantics via Graph Neural Networks:NIPS(A) 2019,Yaqin Zhou et al.


01

Abstract
本文提出了Devign模型,一个基于GNN的源代码漏洞检测模型,使用GNN学习丰富的代码语义信息。该模型包括一个Conv模块,其功能是提取有用的特征来进行graph-level的分类。该模型在4个大型开源C项目上进行训练和测试,结果表明Devign明显优于现有技术,平均提高了10.51%的准确率和8.68%的F1值。


02

Introduction
本文提出了一种基于复合代码表示的图神经网络模型Devign,可以对程序语义信息进行完整的提取,用以各种捕捉漏洞特征。在复合代码表示中,以AST为中心,将不同级别的数据依赖和控制依赖编码为联合图,其中不同类型的边代表不同的依赖特征。这种复合代码表征综合了各种信息,尽可能广泛的捕捉漏洞类型和漏洞模式,使得GNN能够更好的学习节点表征。
提取复合代码表征后,经过门控GNN模块,通过对邻接节点信息的聚合和传递来得到各个节点的表征。最后,经过Conv模块选择与当前任务相关的节点和特征集合,应用一维卷积和dense层来对节点特征进行提取从而实现图级别的分类。
另外,为了验证复合程序编码表征的作用,以及使用GNN进行漏洞检测的效果,本文从4个流行的C库中收集人工标记数据集来进行实验。实验结果表明,Devign比现有方法平均提高了10.51%的准确率和8.68%的F1值,而Conv模块带来了4.66%的精度和6.37%的F1值,将Devign应用到从4个项目中收集到的40个最新的CVE中,得到了74.11%的准确率,在发现新漏洞方面体现了该模型的可用性。

03

Method
上图是Devign的整体架构,包含三个顺序的部分,首先是复合代码语义embedding层,该层将源代码编码为具有多种代码语义的联合图结构;第二部分是GNN层,该层通过聚集和传递图中相邻节点的信息来学习节点的特征;第三部分是Conv模块,提取有意义的节点表征用于图级别的分类预测。
  • 复合代码表征
程序分析中的各种程序表示被用来显示程序的内在信息,比如AST,CFG,DFG(数据流图)等等捕捉了源代码的语法和语义关系。很多漏洞不考虑复合代码语义就无法发现,比如有研究表明,仅仅使用AST可以查找不安全参数的漏洞,而将AST与CFG结合则可以查找资源泄露和释放后使用漏洞。进一步,将AST,CFG,DFG联合使用,则可以检测多种类型的漏洞。
除了以上的三种经典的代码结构,Devign还考虑了源代码序列本身,因为它的flatten结构能以一种“人类可读”的方式捕获代码token之间的联系。接下来分别介绍各种类型的代码表示,以及如何将个各种子图表示为一个联合图。下图(a)是整数溢出代码示例,(b)是图表示。
AST是一种源代码的树形结构表示,它是代码解析器用来理解程序的基本结构和检查语法错误的第一步表示,因此,它是生成许多其他代码表示的基础。AST的节点集包括本文使用的其余三种代码表示的所有节点,从根节点开始,代码被分解为代码块、语句、声明、表达式等等,最后分解为形成叶节点的token。如图2所示,第一行是代码级别,越往下越细致,蓝色框是叶子节点,紫色箭头表示父节点和子节点的关系。
CFG描述了程序在执行过程中可能要遍历的所有路径。路径选择是由条件语句决定的,例如if, for, switch语句。节点表示语句和条件,节点之间通过有向边连接,表示控制的传递。如图2所示,绿色箭头表示的是CFG图的边。
DFG跟踪了CFG中变量的使用情况。数据流是面向变量的,任何数据流都涉及对某些变量的访问或修改,DFG中的边表示对相同变量的后续访问或修改。如图2所示,橙色双箭头表示DFG图的边,并在边上标注了涉及的变量。
NCS(自然代码序列)体现了源代码的自然顺序,反映了源代码序列所体现的编程逻辑。如图2所示,红色箭头表示NCS的边,连接了AST所有的叶子节点。
以上,Devign将一个C函数表示成一个联合图形式(包含4个子图),所有的节点就是AST的节点集合,使用预训练的word2vec模型和构建在整个项目源代码文件上的代码语料库,分别对节点的code和type编码,将两部分编码concat作为节点的初始表征。
  • GNN层
图神经网络的核心思想是通过对相邻节点的信息进行聚合来embedding节点表征,本文使用门控递归图网络来学习节点表征。和正常的GNN一样,通过邻接矩阵来对邻接节点的信息进行聚合,将聚合节点和当前节点一起经过GRU网络得到下一时刻的当前节点。以此类推,经过T时刻,生成所有节点的最终的节点表征。
  • Conv层
图分类的标准方法是将所有的节点特征线性的输入到MLP中然后通过softmax分类,这种方法没有注重重点。Conv模块用来选择与当前任务相关的节点和特征集合,应用一维卷积和dense层来对节点特征进行提取从而实现图级别的分类。

04

Evaluation
  • Q1:Devign相比其他源代码漏洞检测方法,效果如何?
  • Q2:Conv模块与普通的flatten的节点融合相比,有什么优势?
  • Q3:复合图特征学习相比单一图有哪些优势?
  • Q4:在真实场景中,相比于静态分析器,Devign是否有更好的性能?
  • Q5:在CVE公开报告的最新漏洞上,Devign的表现如何?
上图是本文使用的数据集示例,本文评估了从4个大型C语言开源项目中收集的手工标记的函数,这些项目在开发人员中很流行,并且功能多样,例如Linux Kernel, QEMU, Wireshark和FFmpeg。
本文利用基于代码属性图的C/C++开源代码分析平台Joern来提取数据集中所有函数的AST和CFG,上图中的Ggrn意思是普通的flatten的节点融合。将DFG图分为3个子图,DFG_C表示变量的定义,DFG_R表示变量的最近一次读,DFG_W表示变量的最后一次写。下图展示了Devign模型与BiLSTM,BiLSTM-Attention,CNN,以及两种静态方法进行比较的实验结果。
下面回答之前提出的5个问题:
  • Q1:可见Devign相比其他的模型,准确率和F1值都有明显的提高
  • Q2:Devign模型与Ggrn模型相比,准确率平均提高3.23%,F1值平均提高3.92%,说明Conv模块提取了更多相关节点和特征用于图级分类
  • Q3:对于Ggrn模型,复合图和单一图的区别不大,而对于Devign模型,复合图的效果优于单一图
  • Q4:本文创建了一个具有10%漏洞的不平衡数据集,将Devign与著名的开源静态分析工具Cppcheck、Flawfinder和商业工具CXXX进行比较,Devign的F1平均值显著提高,提升幅度达到了27.99%
  • Q5:本文分别提取了各个项目的最近的10个CVE漏洞来检查Devign是否可以识别0-day漏洞。通过对40个CVE漏洞的提交修复提取得到112个漏洞函数,将这些函数输入到经过训练的Devign模型中,平均准确率达到了74.11%,显示了Devign在实际应用中发现新漏洞的潜力。


05

Conclusion
本文提出了一种基于复合代码表示的图神经网络漏洞检测模型Devign, 该模型首先生成联合图提取图节点的复合代码表征,然后通过GNN对邻接节点的信息进行聚合来学习节点特征,最后通过Conv模块选择与当前任务相关的节点和特征集合,通过一维卷积和dense层来进行图级别的分类检测。以函数为检测粒度,针对C代码。

本文目的在于学术交流,并不代表本公众号赞同其观点或对其内容真实性负责,版权归原作者所有,如有侵权请告知删除。


“源头活水”历史文章


更多源头活水专栏文章,

请点击文章底部“阅读原文”查看



分享、在看,给个三连击呗!

您可能也对以下帖子感兴趣

文章有问题?点此查看未经处理的缓存