一种基于Bert模型与BiLSTM的C源代码漏洞检测方法转让专利

申请号 : CN202110770650.4

文献号 : CN113420296B

文献日 :

基本信息:

PDF:

法律信息:

相似专利:

发明人 : 马之力马宏忠李志茹张学军盖继扬杨启帆赵红张驯弥海峰谭任远李玺朱小琴白万荣杨勇魏峰龚波杨凡高丽娜

申请人 : 国网甘肃省电力公司电力科学研究院国网甘肃省电力公司兰州交通大学

摘要 :

一种基于Bert模型与BiLSTM的C源代码漏洞检测方法,通过对软件源代码进行分析,构建控制依赖图与数据依赖图,依据代码间的控制依赖关系和数据依赖关系将代码进行切片,生成切片级代码块,再对生成的代码块进行数据清洗和预处理,并对生成的每个代码块打标签以区分代码块是否包含漏洞信息。其次,将处理过的代码块作为训练集输入Bert预训练模型对标准Bert模型进行微调,得到新的Bert模型。再将代码块输入新的Bert模型以无监督方式学习代码间的语义信息和上下文关系,对代码块进行词嵌入编码,得到具有最大化代码语义信息和上下文关系的词向量。最后,将得到的词向量输入BiLSTM中训练检测模型,得到源代码漏洞检测模型。本发明能提高漏洞检测准确率,降低误报率。

权利要求 :

1.一种基于Bert模型与BiLSTM的C源代码漏洞检测方法,其特征在于:主要包含以下步骤:

步骤A:生成程序切片,基于软件的源代码,利用Joern工具生成源代码对应的程序依赖图PDG和抽象语法树AST,程序依赖图PDG包含代码间的控制依赖图CDG和数据依赖图DDG,抽象语法树AST包含程序语句间的语法信息;基于控制依赖图CDG和数据依赖图DDG中的控制依赖信息和数据依赖信息,基于漏洞规则对代码进行切片,最终得到想要的程序切片;

步骤B:生成代码的符号表征,将步骤A得到的原始程序切片进行数据清洗和格式化处理,即对代码块中出现的除关键字和操作符以外的标识符,用户定义的函数名和变量名,按照自定义命名规则进行重新命名,将处理过的代码块中的每一行代码语句转化为由单个字符组成的有序子集,得到代码符号表征;

步骤C:对标准Bert模型进行微调,基于标准Bert模型,将步骤B得到的代码符号表征作为Bert模型的训练集,再把训练集中的数据逐条转化为Bert模型输入要求的数据格式,并将其输入标准Bert模型进行模型微调,通过微调可得到更适应本地数据集的新的Bert模型;具体为:

C1:所述将训练集转化为Bert模型输入的格式表示为:首先,读取得到的代码块,以分号为界,将多行代码组成单行列表,得到格式为Text, Label的数据集,其中Text表示代码集合,Label表示对应代码集合的标签;其次,采用Bert自带的vocab.txt词表对Text进行词嵌入,将代码块表示成单个字符的集合,生成Text的词嵌入表示,即Tokens数组,其中每条数据对应的Tokens数组以[CLS]作为文本开头标识,以[SEP]作为结尾表示;

C2:定义一个Tokens数组中字符被标记后序列的最大长度max_seq_length,再将得到的Tokens数组中的每个字符映射为对应的id,生成input_ids数组;input_ids中每个字符被唯一的id替换;同时基于Tokens数组得到其对应的长度为max_seq_length的segment_ids数组;最终生成的input_ids、segment_ids将作为Bert模型的输入,用于Bert模型的微调;

步骤D:生成代码表征对应的向量表征,使用步骤C中微调得到的新的Bert模型对步骤B中得到的代码表征集进行预训练,将其转化为具有丰富语义信息及上下文关系的向量表征集,用于后续输入神经网络进行模型训练;具体为:D1:所述向量表征集即为将代码表征集转化为Bert模型输入要求的格式input_ids,segment_ids,再将其输入步骤C得到的微调后的Bert模型,Bert模型对输入信息进行编码,得到原始代码表征对应的词向量数据,作为BiLSTM深度学习网络的输入;

步骤E:训练软件源代码漏洞检测模型,设计双层BiLSTM网络,并将步骤D中由Bert模型预训练得到的词向量作为其训练数据,得到基于软件源代码的漏洞检测模型。

2.根据权利要求1所述的一种基于Bert模型与BiLSTM的C源代码漏洞检测方法,其特征在于,其中步骤A进一步包括:

A1:使用公开的Joern工具构建程序依赖图和抽象语法树,基于漏洞语法规则在抽象语法树中寻找与漏洞语法规则相匹配的代码语句,构建有序的代码语句集合;

A2:基于程序依赖图中的控制依赖信息和数据依赖信息,对有序的代码语句集合进行切片,得到切片级代码块,将代码块与现存的漏洞库中的漏洞代码块进行匹配对比,对包含漏洞特征的代码块,用标签1表示,对不包含漏洞特征的代码块用标签0表示。

3.根据权利要求1所述的一种基于Bert模型与BiLSTM的C源代码漏洞检测方法,其特征在于,其中步骤B进一步包括:

B1:所述代码块清洗过程表示为:得到的带有标签的代码块由有序的多行代码语句组成;针对每行代码语句,删除不存在造成漏洞的无关字符串信息、代码注释和非ASCII字符,同时保留引号和括号这类具有语法信息的符号,保留分号以区分每行代码;

B2:所述代码块格式化过程表示为:代码块中用户自定义的变量名被按顺序重新命名为 VAR1、VAR2,用户自定义的函数名被按顺序重新命名为FUN1、FUN2;其中VAR和FUN用于区分函数和变量,1和2表示该变量或函数在代码块中的次序;这些映射都是以一对一的方式执行的;每个代码块的命名替换完成后,都会对函数和变量索引重新计数,因此当多个变量和函数出现在不同的代码块中时,它们可能被映射为相同的符号名。

4.根据权利要求1所述的一种基于Bert模型与BiLSTM的C源代码漏洞检测方法,其特征在于,其中步骤E进一步包括:取20%的训练数据对所述漏洞检测模型进行测试,以检测准确率和训练损失作为评价指标,评价模型的检测性能。

说明书 :

一种基于Bert模型与BiLSTM的C源代码漏洞检测方法

技术领域

[0001] 本发明涉及一种软件源代码漏洞检测方法,具体为一种基于Bert模型与BiLSTM的C源代码漏洞检测方法。

背景技术

[0002] 当前生活中发生的大多数网络攻击安全事件大都基于设备软件中存在的各种不同的软件漏洞,软件漏洞是指软件开发者在开发阶段由于技术问题、经验不足等因素造成
的软件缺陷,并且该缺陷存在于软件部署与运行的整个阶段。因此,攻击者可在任何时间或
地点使用漏洞利用工具基于此类软件漏洞缺陷对目标系统发起攻击,提取管理员权限,获
取系统数据与命令控制权限以达到扰乱系统的正常运行或获取经济利益的目的。
[0003] 目前存在的比较成熟的漏洞挖掘技术主要包括:二进制漏洞检测方法、基于模式匹配的漏洞检测方法、基于代码相似性的漏洞检测方法。其中基于二进制的漏洞检测方法
是将源代码转化为二进制流,再对二进制流进行分析,因此缺失了大部分语义与逻辑信息,
不利于漏洞的检测。基于模式匹配的漏洞检测方法的原理是首先需要专家人工定义漏洞模
式,再依据定义好的漏洞模式在源代码中搜索是否存在与之匹配的代码段,确定漏洞是否
存在,但这种方法效率较低,主观性较强,误报率较高。基于代码相似性的漏洞检测方法的
检测原理是通过分析并统计代码之间相似度高低,从而判断被测程序中是否存在漏洞,可
以对由代码复制及代码克隆引起的漏洞进行有效检测,但对其他类型漏洞的检测具有一定
的局限性。以上三种方法都是通过具有丰富经验的专家去定义漏洞特征,设定漏洞检测规
则对软件中的代码进行安全性检测。这种方法最大的缺陷就是检测效率低、主观依赖性强、
无法实现批量检测。因此基于自动化的漏洞检测方法已经成为当前发展的新趋势,目前基
于深度学习的漏洞检测方法可通过多层神经网络学习源码中的漏洞特征,无需人工定义漏
洞模式,有效改善了传统方法中无法批处理和模块化的缺陷,提高了漏洞检测效率。Li等人
(Zhen L, D Zou, Xu S  , et al. SySeVR: A Framework for Using Deep Learning to 
Detect Software Vulnerabilities[J]. 2018.)首次提出使用深度学习技术构建基于软
件源代码的漏洞检测模型,该模型利用word2vec词向量转化技术将处理好的漏洞代码块转
化为深度学习可以识别的词向量,再将其放入深度学习网络训练模型,以上方法虽然可以
对漏洞有效分类,但由于word2vec技术在词向量转化过程中不考虑原始文本的上下文语义
关系,因此基于该向量训练得到的检测模型仍然存在检测准确率低的问题。专利
CN201910447971提出使用深度学习技术学习漏洞特征,避免了人工定义漏洞特征,提高了
漏洞检测效率,但上述方法在词向量生成阶段使用了word2vec中的Skip‑Gram模型,该模型
不能对文本中的上下文关系进行编码,且只能对单个词进行编码。因此,在生成词向量的过
程中必然会造成语义信息缺失,导致训练得到的模型检测准确率较低。专利
CN202011046243提出的源代码漏洞检测方法的词向量转化过程和专利CN201910447971一
致,同样是基于word2vec词向量转化技术将包含漏洞的源代码数据转化为其对应的向量表
示。因此,在生成词向量的过程中必然会造成语义信息缺失,从而影响模型的检测准确率。
专利CN201911363149使用半监督学习技术,将有标签数据和无标签数据共同作为训练数
据,直接将代码元素输入ELMo模型中对源代码是否包含漏洞信息进行预测,虽然节省了代
码处理的时间,但是由于ELMo模型在训练下游需要设置每层的参数,因其只能对单个词进
行编码,且无负采样过程,无法保证较高的检测准确率。专利CN202010576421提出了一种基
于图卷积神经网络的源代码漏洞检测方法,该方法通过得到源代码对应的代码属性图,基
于漏洞特征构建代码切片图结构,再使用图卷积网络学习每个图节点的向量表示,训练得
到源代码漏洞检测模型,但当训练代码结构较为复杂时,生成的代码属性图复杂度较高,图
卷积网络不能有效学习复杂的图节点,因此仍然存在检测准确率较低的问题。

发明内容

[0004] 本发明提供一种基于Bert模型与BiLSTM的C源代码漏洞检测方法,提高漏洞检测准确率,降低误报率。
[0005] 本发明采用的技术方案如下:
[0006] 一种基于Bert模型与BiLSTM的C源代码漏洞检测方法,主要包含以下步骤:
[0007] 步骤A:生成程序切片,基于软件的源代码,利用Joern工具生成源代码对应的程序依赖图PDG和抽象语法树AST,程序依赖图PDG包含代码间的控制依赖图CDG和数据依赖图
DDG,抽象语法树AST包含程序语句间的语法信息;基于控制依赖图CDG和数据依赖图DDG中
的控制依赖信息和数据依赖信息,基于漏洞规则对代码进行切片,最终得到想要的程序切
片;
[0008] 步骤B:生成代码的符号表征,将步骤A得到的原始程序切片进行数据清洗和格式化处理,即对代码块中出现的除关键字和操作符以外的标识符,用户定义的函数名和变量
名,按照自定义命名规则进行重新命名,将处理过的代码块中的每一行代码语句转化为由
单个字符组成的有序子集,得到代码符号表征;
[0009] 步骤C:对标准Bert模型进行微调,基于标准Bert模型,将步骤B得到的代码符号表征作为Bert模型的训练集,再把训练集中的数据逐条转化为Bert模型输入要求的数据格
式,并将其输入标准Bert模型进行模型微调,通过微调可得到更适应本地数据集的新的
Bert模型;
[0010] 步骤D:生成代码表征对应的向量表征,使用步骤C中微调得到的新的Bert模型对步骤B中得到的代码表征集进行预训练,将其转化为具有丰富语义信息及上下文关系的向
量表征集,用于后续输入神经网络进行模型训练;
[0011] 步骤E:训练软件源代码漏洞检测模型,设计双层BiLSTM网络,并将步骤D中由Bert模型预训练得到的词向量作为其训练数据,得到基于软件源代码的漏洞检测模型。
[0012] 其中步骤A进一步包括:
[0013] A1:使用公开的Joern工具构建程序依赖图和抽象语法树,基于漏洞语法规则,在抽象语法树中寻找与漏洞语法规则相匹配的代码语句,构建有序的代码语句集合;
[0014] A2:基于程序依赖图中的控制依赖信息和数据依赖信息,对有序的代码语句集合进行切片,得到切片级代码块,将代码块与现存的漏洞库中的漏洞代码块进行匹配对比,对
包含漏洞特征的代码块,用标签1表示,对不包含漏洞特征的代码块用标签0表示。
[0015] 其中步骤B进一步包括:
[0016] B1:所述代码块清洗过程表示为:得到的带有标签的代码块由有序的多行代码语句组成;针对每行代码语句,删除不存在造成漏洞的无关字符串信息、代码注释和非ASCII
字符,同时保留引号和括号这类具有语法信息的符号,保留分号以区分每行代码;
[0017] B2:所述代码块格式化过程表示为:代码块中用户自定义的变量名被按顺序重新命名为 VAR1、VAR2,用户自定义的函数名被按顺序重新命名为FUN1、FUN2;其中VAR和FUN用
于区分函数和变量,1和2表示该变量或函数在代码块中的次序;这些映射都是以一对一的
方式执行的;每个代码块的命名替换完成后,都会对函数和变量索引重新计数,因此当多个
变量和函数出现在不同的代码块中时,它们可能被映射为相同的符号名。
[0018] 其中步骤C进一步包括:
[0019] C1:所述将训练集转化为Bert模型输入的格式表示为:首先,读取得到的代码块,以分号为界,将多行代码组成单行列表,得到格式为Text, Label的数据集,其中Text表示
代码集合,Label表示对应代码集合的标签;其次,采用Bert自带的vocab.txt词表对Text进
行词嵌入,将代码块表示成单个字符的集合,生成Text的词嵌入表示,即Tokens数组,其中
每条数据对应的Tokens数组以[CLS]作为文本开头标识,以[SEP]作为结尾表示;
[0020] C2:定义一个Tokens数组中字符被标记后序列的最大长度max_seq_length,再将得到的Tokens数组中的每个字符映射为对应的id,生成input_ids数组;input_ids中每个
字符被唯一的id替换,如[CLS]被替换为101;同时基于Tokens数组得到其对应的长度为
max_seq_length的segment_ids数组。最终生成的input_ids、segment_ids将作为Bert模型
的输入,用于Bert模型的微调。
[0021] 其中步骤D进一步包括:
[0022] D1:所述向量表征集即为将代码表征集转化为Bert模型输入要求的格式input_ids,segment_ids,再将其输入步骤C得到的微调后的Bert模型,Bert模型对输入信息进行
编码,得到原始代码表征对应的词向量数据,作为BiLSTM深度学习网络的输入。
[0023] 其中步骤E进一步包括:取20%的训练数据对所述漏洞检测模型进行测试,以检测准确率和训练损失作为评价指标,评价模型的检测性能。
[0024] 本发明在得到代码切片之后,首先对切片进行数据清洗和格式化处理,其次使用Bert模型自带的词袋和词嵌入技术对代码切片进行字符编码和字符位置编码,得到字符映
射数组和位置映射数组,再使用微调后的Bert模型以无监督的方式学习代码切片间的上下
文关系、语义关系和位置关系,生成具有语义信息的向量,再将向量作为BiLSTM模型的输
入,进行模型训练。由于本发明在代码切片的词向量转化过程中很好的保留了代码语句的
语义信息和上下文关系,并引入了位置编码,因此,本发明提出的方法有效提高了源代码检
测模型的准确率,降低误报率。

附图说明

[0025] 图1为本发明所提源代码漏洞检测模型的训练流程图;
[0026] 图2为本发明基于深度学习的源代码漏洞检测模型的系统架构图;
[0027] 图3为本发明源代码程序切片提取及处理过程示意图;
[0028] 图4为本发明Bert模型对代码切片的词向量转化过程示意图。

具体实施方式

[0029] 下面结合具体实施方式对本发明进一步说明。
[0030] 一种基于Bert(Bidirectional Encoder Representations from Transformers)模型与双向长短期记忆网络BiLSTM(Bi‑directional Long Short‑Term Memory)的C源代
码漏洞检测方法,主要包含以下步骤:
[0031] 步骤A:生成程序切片,基于软件的源代码,利用Joern工具生成源代码对应的程序依赖图PDG(Program Dependence Graph)和抽象语法树AST(Abstract Syntax Tree),PDG
包含代码间的控制依赖图CDG(Control Dependence Graph)和数据依赖图DDG(Data 
Dependence Graph),AST包含程序语句间的语法信息;基于控制依赖图CDG和数据依赖图
DDG中的控制依赖信息和数据依赖信息,基于漏洞规则对代码进行切片,最终得到想要的程
序切片。
[0032] 步骤B:生成代码的符号表征,将步骤A得到的原始程序切片进行数据清洗和格式化处理,即对代码块中出现的除关键字(如int,char等)和操作符(如+,*,%等)以外的标识
符,用户定义的函数名和变量名,按照自定义命名规则进行重新命名,将处理过的代码块中
的每一行代码语句转化为由单个字符组成的有序子集,得到代码符号表征。
[0033] 步骤C:对标准Bert模型进行微调,基于标准Bert模型,将步骤B得到的代码符号表征作为Bert模型的训练集,再把训练集中的数据逐条转化为Bert模型输入要求的数据格
式,并将其输入标准Bert模型进行模型微调,通过微调可得到更适应本地数据集的新的
Bert模型;
[0034] 步骤D:生成代码表征对应的向量表征,使用步骤C中微调得到的新的Bert模型对步骤B中得到的代码表征集进行预训练,将其转化为具有丰富语义信息及上下文关系的向
量表征集,用于后续输入神经网络进行模型训练;
[0035] 步骤E:训练软件源代码漏洞检测模型,设计双层BiLSTM网络,并将步骤D中由Bert模型预训练得到的词向量作为其训练数据,得到基于软件源代码的漏洞检测模型。
[0036] 下面将基于CWE‑399(资源管理错误漏洞)和CWE‑119(缓冲区溢出漏洞)详细介绍本发明的实现步骤,主要从代码块的生成、代码数据的编码映射及Bert模型的微调、词向量
转化及模型训练这几个方面详细介绍。图1主要介绍了本发明所提的源代码漏洞检测模型
的构建流程,图2主要介绍了本发明所提漏洞检测模型的架构及使用原理。
[0037] 1、得到训练数据集(带有标签的代码块)。
[0038] 步骤1‑1:生成源代码的程序依赖图和抽象语法树。使用Joern工具解析得到软件源代码对应的程序依赖图PDG和抽象语法树AST,其中程序依赖图PDG包含代码语句的数据
依赖图DDG和控制依赖图CDG,抽象语法树AST包含程序语句间的语法信息。
[0039] 步骤1‑2:生成代码块。基于漏洞语法规则(API函数调用,数组、指针、表达式的定义与使用)在抽象语法树中寻找与漏洞语法规则相匹配的代码语句,如图3中(a)和(b)所
示,在源代码中找到与漏洞语法规则匹配的API调用函数strncpy(b,a,n),并基于程序依赖
图中的控制依赖和数据依赖关系,向前向后切取可能具有漏洞语义信息的代码语句,组成
图3中(c)所示的代码块。将代码块与现存漏洞库中的漏洞代码块进行匹配对比,对包含漏
洞特征的代码块,用标签1表示,对不包含漏洞特征的代码块用标签0表示,以用于后续输入
神经网络进行有监督分类,训练漏洞检测模型。
[0040] 2、对得到的代码块进行数据清洗和格式化操作。
[0041] 步骤2‑1:所述代码块清洗过程表示为:得到的带有标签的代码块由有序的多行代码语句组成。针对每行代码语句,删除不存在造成漏洞的无关字符串信息、代码注释和非
ASCII字符等,同时保留引号和括号这类具有语法信息的符号,保留分号以区分每行代码
(C,C++中每行代码均以分号结尾)。
[0042] 步骤2‑2:所述代码块格式化过程表示为:代码块中用户自定义的变量名被按顺序重新命名为 “VAR1”、“VAR2”等。用户自定义的函数名被按顺序重新命名为“FUN1”、“FUN2”
等。其中“VAR”和“FUN”用于区分函数和变量,“1”和“2”表示该变量或函数在代码块中的次
序。如图3中(c)所示,a[10]、b[10]和n被依次重命名为VAR1[10]、VAR2[10]和VAR3,函数调
用strncpy (b, a, n)被重新命名为FUN1(VAR1, VAR2, VAR3),这些映射都是以一对一的
方式执行的。每个代码块的命名替换完成后,都会对函数和变量索引重新计数,因此当多个
变量和函数出现在不同的代码块中时,它们可能被映射为相同的符号名。
[0043] 3、使用Bert模型对训练数据集进行预训练,生成向量表示。
[0044] 步骤3‑1:基于数据集对Bert模型进行微调,以使得模型更适应数据。首先,将训练集转化为Bert模型输入的格式,代码读取得到的代码块,以分号为界,将多行代码组成单行
列表,得到格式为(Text, Label)的数据集,其中Text表示代码集合,Label表示对应代码集
合的标签。其次,采用Bert自带的vocab.txt词表对Text进行词嵌入,将代码块表示成单个
字符的集合,生成Text的词嵌入表示,即Tokens数组。如图4所示,其中每条数据对应的
Tokens数组以[CLS]作为文本开头标识,以[SEP]作为结尾表示。定义一个Tokens数组中字
符被标记后序列的最大长度max_seq_length,再将得到的Tokens数组中的每个字符映射为
对应的id,生成input_ids数组,若序列长度大于max_seq_length,则只保留长度为max_
seq_length大小的序列,否则用max_seq_length‑len (input_ids)个0补齐序列,input_
ids中每个字符被唯一的id替换,如[CLS]被替换为“101”。同时基于Tokens数组得到其对应
的长度为max_seq_length的segment_ids数组,其中segment_ids的作用是使用Embedding
的信息对文本中每句话的位置进行区分,本发明使用segment_ids标记每个字符在每行代
码语句中的位置信息。最终生成的input_ids、segment_ids将作为Bert模型的输入用于
Bert模型的微调,得到新的Bert模型。
[0045] 步骤3‑2:如图4所示,与步骤3‑1同理,先将训练集转化为Bert模型输入需要的格式(input_ids、segment_ids),并将其输入微调后的Bert模型,通过编码得到原始代码表征
对应的词向量数据。Bert模型采用transformer特征提取技术和self attantion 技术学习
文本的上下文关系和语义信息。另外,Bert模型的输入数据segment_ids表示单个语句的位
置信息,一般情况下,同一字符在不同语句中可能表示不同的语义与语法信息,因此对不同
位置出现的同一字符给予不同的向量表示,最大化保留了代码语句的上下文关系和语法信
息,避免了漏洞检测模型训练过程中代码语义信息和代码结构的信息缺失,从而有效提高
了漏洞检测模型的准确率。
[0046] 4、使用改进后的BiLSTM模型实现软件源代码漏洞检测模型。
[0047] 步骤4‑1:将步骤3‑2中由Bert模型预训练得到的词向量作为改进后的BiLSTM深度学习网络的训练数据,训练得到基于软件源代码的漏洞检测模型。由于Bert词向量训练网
络模型已具备一定的分类能力,因此无需后接太过复杂的网络模型。本发明设计了一个由
单个单层BiLSTM模型。其中,损失函数为binary_crossentropy,优化函数为Adamax,学习率
为0.0001,输入神经元个数为128(由于Bert输出向量维度为768,因此在输入前需要对输入
向量进行重塑维度)。模型训练完成之后,取20%的训练数据对漏洞检测模型进行测试,以检
测准确率,训练损失作为指标,评价模型的检测性能。
[0048] 参阅表1,在cwe399和cwe119漏洞数据集上进行实验,结果表明本发明使用Bert模型对得到的函数级别的代码块进行预训练,可以有效学习并保留源代码的语义信息和上下
文关系,相比于使用word2vec词向量转化技术,本发明可以保证训练得到的检测模型具有
较高的检测准确率。
[0049] 表1在CWE‑399和CWE‑119漏洞数据集上的模型分类准确率和模型训练损失
[0050]