使用深度神经网络进行漏洞挖掘的方法调研
传统的漏洞挖掘方法
静态方法
- 基于规则/模板的
- 代码相似性检测
- 符号执行
对源代码分析,高假阳性
动态方法
- 模糊测试
- 污点分析
代码覆盖率低
混合方法
结合静态、动态方法,会继承上述的问题,并且实践上难以应用
介绍
机器学习方法的优点
人类智慧(经验)起到重要指导作用(基于规则、基于提取的特征的)
困难:
- 难以将安全专家对漏洞的理解 转换为 可被检测系统学习的特征向量
- 系统从特征集中学到的东西也可能受到各种因素的影响
例如,模型的表现力、数据过度拟合、数据中的噪声等
一些概念:
-
缺口(GAP):机器学习 要 像人类一样 学习和理解 漏洞代码的语义 (如何将漏洞代码表示为机器可学习的信息)
-
semantic gap: 语义缺口、语义空白
-
传统机器学习方法依赖手工制作的特征
-
深度学习、RNN可以自动通过学习揭示代码语义的复杂模式和软件代码的高级表示
安全从业者人工审查漏洞考虑的因素
漏洞语义差距
对软件漏洞一种不同的表达
定义:缺陷的实例,由软件的设计、开发或配置中的错误引起,从而可以利用它来违反某些显式或隐式的安全策略
安全相关的 bug ==》 被攻击者利用 ==》 导致安全失败或者违反安全策略
人类检查和检测系统的语义鸿沟
对代码语义的高级理解需要:
- 足够的经验
- 编程知识
- 对编程语言本身的理解
- 理解代码的语义和语法
- 对代码库有深入认识(一个例子是心脏滴血漏洞中,需要对n2s函数有了解
- 安全编码的实践
自动检测系统
依赖特征集,来自于:
- 人工提取的(传统机器学习算法
- 自动提取的(深度学习
检测系统无法像从业者那样充分理解易受攻击代码模式的潜在语义。 因此,知识渊博、经验丰富的从业者与基于ML的检测系统之间存在语义差距,我们将其定义如下。
语义差距的定义:
语义差距是从业者能够理解的漏洞的抽象语义与ML算法可以学习的语义之间缺乏一致性。
特征的准确性很重要:
- 人类根据经验总结和提取的特征,可能导致信息丢失或者个人偏见
- 机器学习算法提取的特征,可能拟合不足、过拟合、数据噪声
传统机器学习方法
分类
- 基于软件度量的 Metrics
- 基于脆弱代码模式 pattern
- 基于异常的 anomaly
软件度量
McCabe: 软件复杂性指标
使用这些度量的漏洞检测模型建立在一个假设的基础上,即一个复杂的代码对一个从业者来说是很难理解的,因此很难维护和测试
Code Churn: 软件修改频率
CodeChurn度量意味着经常修改的代码往往是错误的,因此考虑到漏洞是软件缺陷的子集,更有可能是有缺陷的,也可能是脆弱的
软件度量可以作为参考,但是不能作为决定性因素
基于源代码提取模式
词袋 =》 N-gram
容易忽略上下文,忽略了代码丰富的语义(完全相同的令牌和每个令牌的相同频率,可以具有不同的代码语义
基于结构化信息
利用代码分析工具,生成的结构化数据
- AST抽象语法树
- CFG控制流图
- DFG数据流图
- PDG程序依赖图
- CPG代码属性图 === 将AST、CFG和PDG组合
代码分析工具和解析器的结果的特征集揭示了更多关于代码的信息,因为程序表示的每一种形式都从不同的方面提供了关于源代码的视图
有助于分析变量如何从源流到汇,并可用于构建变量
基于动态执行的跟踪数据
基于执行异常的
考虑 什么 导致了漏洞,而不是如何产生的漏洞
从异常API使用模式中提取的特征、导入和函数调用,以及API符号缺失检查进行漏洞检测
缺点: 这些特征集通常与一小组漏洞或特定类型的漏洞相连
从导入和函数调用中提取的特征只能训练一个分类器来检测一些脆弱的头文件或库引入的漏洞,
而与缺失检查相关的API符号只能用于发现由于缺乏验证或边界检查而导致的漏洞
- 只适用于特定任务的应哟个
- 假阳性
深度学习技术
优点
相比较传统机器学习,深度学习:
- 能够学习具有更复杂和抽象的高级特征或表示
- 能够自动学习更可概括的潜在特征或表示,从而使从业者免于劳动密集型、主观和易错的特征工程任务
- 提供灵活性,允许针对不同的应用场景定制网络结构。 例如,将长短期记忆(LSTM)网络与密集层结合起来,用于学习函数级表示作为高级特征、实现用于学习特征重要性的注意层,以及添加外部内存“插槽”以捕获远程代码依赖
上述深度学习技术的特点使研究人员能够构建能够捕获代码语义、理解代码上下文依赖关系和自动学习更可推广的高级特征集的检测系统。 有了这些功能,构建的系统可以更好地“理解”代码的语义和上下文,因此,将进一步缩小语义差距
用于弥补语义差距的 特征表示 方法
NLP 自然语言模型对处理源代码也是有效的
神经模型促进表征学习
不同类型的网络结构用于从各种类型的输入中提取抽象特征,我们称之为特征表示,用于识别易受攻击的代码片段的语义特征
FCN全连接网络
MLP多层感知器
将网络视为学习隐藏的和可能复杂的脆弱模式的高度非线性分类器。
传统的ML算法:
- 随机森林
- 支持向量机(SVM)
- C4.5
FCN可以拟合高度非线性和抽象的模式
FCN优点:
- FCN具有学习比传统ML算法更丰富的模型的潜力,在大数据集下。 这种潜力促使研究人员利用它来建模潜在和复杂的脆弱代码模式
- 输入结构无关的”,这意味着网络可以采取多种形式的输入数据(例如图像或序列)也为研究人员提供了手工制作各种类型功能的灵活性,供网络学习。
CNN卷积神经网络
用来学习结构化的空间数据
CNN可以捕捉单词的上下文含义,这促使研究人员应用CNN学习上下文感知的脆弱代码语义
RNN循环神经网络
用于处理顺序数据
RNN的双向形式能够捕获序列的长期依赖关系。 因此,许多研究使用双向LSTM(Bi-LSTM)和门控递归单元(G RU)结构来学习代码上下文依赖关系,这对于理解许多类型的漏洞(例如缓冲区溢出漏洞)的语义至关重要)。
各种各样的
- deep belief network (DBN)
- variational autoencoders (VAEs)
深度学习技术的另一个有前途的特点是可以定制网络结构,以满足不同的应用场景
已有的工作分类
- 基于图的特征表示:包括AST、CFG、PDG和它们的组合
- 基于序列的特征表示:使用DNN从顺序代码实体中提取特征表示,例如执行跟踪、函数调用序列和变量流/序列
- 基于文本的特征表示:从源代码学习
- 混合特征表示
理由:
- 这些研究的贡献在于如何处理软件代码以生成特征表示,从而促进DNN对代码语义的理解,并将模式捕获为潜在易受攻击的代码片段的指标。
- DNN模型作为具有内置表示学习能力的分类器工作。 现有的基于不同类型特征输入的研究允许DNN获得揭示不同语义信息的高级表示。
基于图的特征表示
- 一种检测SQL注入和XSS漏洞的方法:CFG\DFG
- 基于AST的方法,介绍了6个项目,其中有一半是不开放数据集和源代码的(包含手工标注的数据集,使得难以复现)
- 没有研究比较AST与其他形式的基于图形的程序表示,如CFG、PDG或DDG
AST
在从源代码中提取AST时,保留了三种类型的节点:
- 函数调用节点和类实例创建节点
- 声明节点
- 控制流节点
此外,ASTS、CFGS、PDG和DDG是基于图形的程序表示。 然而,上述研究没有使用它们原来的树/图形式进行处理,而是在将它们馈送到深层网络之前“扁平”它们。 图嵌入技术和基于图的神经网络可以作为处理上述基于图的程序表示的漏洞检测的替代方案,也可能是更有效的解决方案。
基于序列的特征表示
系统执行跟踪、函数调用序列、形成数据流的语句序列等
- 静态特征:作者从与标准C库函数相关联的一组调用序列中提取静态特征,这需要作者对二进制文件进行拆卸
- 动态特征:获取动态特性需要在有限的时间内执行程序。 在执行过程中,作者监视程序的事件并收集调用序列。
得到的动态调用序列包含大量的函数调用参数,这些参数是低级的计算值
code gadget: 不仅包含描述数据依赖关系的代码序列,而且还包含揭示控制依赖关系的代码序列
准确地捕捉缓冲区错误(CWE-119)和资源管理错误(CWE-399)漏洞的语义模式和特征
因此,代码序列形成上下文,捕获与可能的漏洞相关的“全局”语义。
code attention: 为了检测特定的漏洞类型,他们还提出了所谓的“代码注意”,以关注语句中的“本地化”信息
基于文本的特征表示
代码文本是指源代码的表面文本、汇编指令和代码lexer处理的源代码。
DBN和FCN的分层结构能够学习高层表示。
CNN和RNN的变体(例如LSTM网络)能够从文本语料库(如源代码或AST序列)中捕获上下文模式或结构
混合的特征表示
从smali文件中提取了两种类型的特征:
- 由显示令牌属性的dalvik指令的频率表示的令牌特征
- 通过遍历smali文件的AST生成的语义特征。 为了提取令牌特性,作者将smali文件的dalvik指令分为八个类别,并构建了一个映射表
应用深度优先搜索(DFS)遍历将AST转换为序列
挑战和未来的方向
大量的ground-truth 数据集
数据集是阻碍这一领域发展的主要障碍。 在目前阶段,所提出的基于神经网络的漏洞检测技术都是在自构数据集上进行评估的
迫切需要一个标准基准数据集,作为评价和比较拟议方法有效性的统一指标。
代码分析和神经学习
应用于漏洞检测的网络模型变得越来越复杂,为了更好地学习代码语义,指示易受攻击的代码片段,网络模型变得越来越具有表现力。
保留语义的神经模型
在应用神经网络进行脆弱性检测的领域中,一个关键点是通过使神经模型能够更好地用编程语言的语义推理来填补语义空白
在NLP领域,序列建模和自然语言理解的最新进展令人鼓舞。 例如,基于自我关注机制的变压器神
代码表示学习
在漏洞检测领域,由于易受攻击的代码模式多种多样,语句形成了一个脆弱的代码上下文,要么在函数边界内(过程内),要么跨越多个函数(过程间),因此定义通用描述所有类型漏洞的特征集几乎是不可行和不可能的。 因此,定义特征集反映某些类型的漏洞的特征可以是一种折衷的选择,但开发针对特定类型漏洞的检测系统取得了有希望的结果
模型的人类可理解性
ML模型,特别是神经网络模型,是黑匣子,这意味着模型如何进行预测/分类的原因对于实践者来说是未知的。 大量的综述研究没有努力解释模型的行为。 在漏洞检测领域,无法理解模型如何预测一段代码是脆弱的/不可破坏的,这可能会导致模型的效用值得怀疑。 人们可能会提出以下问题:模型是否值得信赖? 或者这个(个人)预测/分类可靠吗? 无法理解模型的行为可能是阻碍基于神经网络的模型在实践中应用于漏洞检测的障碍之一。