DataCon 晚自习:浅谈大模型辅助漏洞挖掘

一、前言 大语言模型(LLM)近期成为安全研究和竞赛中的热门话题,涵盖了大模型在安全领域的应用以及自身的安全性等方向,这一趋势为许多非大模型安全研究领域的研究者提供了了解和探索的机会。 得益于强大的上下文理解与模式识别能力,大模型被认为具备从已知漏洞中学习特征并检测、修复未知漏洞的潜力。目前,大多数基于大模型的漏洞检测和修复方案集中在函数级别,只处理小范围的代码片段,不过也有少量研究开始探索代码库级别的问题。 本次 DataCon 聚焦于真实漏洞环境,提供了和漏洞相关的完整程序代码,要求参赛者"结合大模型技术自动化识别出漏洞样例中存在的安全隐患"。为此,本文将从函数级别和代码库级别两个方面简要分析和梳理当前研究进展,并结合代码库级别漏洞检测的需求,探讨未来的研究方向。 二、函数级别漏洞检测 本节主要参考 Large Language Model for Vulnerability Detection and Repair: Literature Review and the Road Ahead,未注明来源的研究方法,可在该综述中查阅 从提升大模型漏洞挖掘能力的角度,主要可以将当前研究分为三种方法:微调、提示工程和检索增强生成(RAG)。微调通过在漏洞数据上的定向训练来调整模型的参数;提示工程则以黑盒的方式,通过精心设计的 prompt 来优化模型在具体应用场景中的输出效果;RAG 从数据库中检索相关知识并整合到 LLM 的上下文中,同样不需要修改 LLM 的参数。 2.1 微调 一般的微调训练包含以下几个步骤:数据准备、模型设计、模型训练和模型优化。根据不同研究方法主要针对的训练阶段,可以划分为以下几个类别: 以数据为中心的创新(数据准备) 漏洞数据集通常存在标签不平衡和标签不正确的问题。一些研究通过数据采样、伪标签生成以及反事实数据生成等方法,尝试针对这些问题提出解决方案。 结合程序分析方法(数据准备) 一些研究将程序分析工具的结果引入模型的预训练或微调阶段,以帮助 LLM 更好地理解代码逻辑和数据依赖关系。例如: 可以提取抽象语法树(AST)和程序依赖图(PDG)来进行语句级控制依赖和数据依赖的预训练。 利用程序切片提取控制和数据依赖信息,将控制流图(CFG)分解为执行路径,为模型提供漏洞检测的支持。 结合其他深度学习模型(模型设计) 通过 Bi-LSTM (双向长短期记忆网络)处理分段后的代码输入克服了 LLM 的长度限制;亦或是通过 GNN (图神经网络)提取代码的图结构特征来补充 LLM 对代码结构的理解。 针对特定领域进行训练(模型训练) 通过在特定编程语言和特定漏洞类型的数据上进行预训练,使用如掩码语言模型、对比学习、程序依赖预测和漏洞语句标注等不同的预训练目标,可以增强模型对特定编程语言、特定漏洞模式以及复杂代码依赖关系的理解能力。 因果学习(训练优化) 通过识别和剔除那些与漏洞标签存在虚假相关的非稳健特征,进而使用因果推理算法来提升模型的因果推理能力。 其中,相比于其他方法更像是在解决一些大模型的通病,“结合程序分析方法"以及"针对特定领域进行训练"两类方法,则更依赖研究者对程序分析和漏洞挖掘领域的深入理解。限于时间原因笔者没能深入了解相关方法的研究细节,感兴趣的读者建议阅读相关论文。 2.2 微调:如何训练自己的模型 那如果我们想要微调自己的大模型,有哪些需要关注的问题呢?首先是选择使用的研究方法:根据数据规模、数据是否标记、模型选择和预算,可以划分为如图所示的模型训练方法。**CPT(持续预训练)**使用大量未标记的特定领域数据对已经预训练的大模型进行进一步训练;**SFT (有监督微调)**更专注于增强特定任务的性能,使用有标签的数据进行训练。**FULL(全参数微调)**细化所有参数,需要大量的计算能力和时间;相比之下,**PEFT(参数高效微调)**通过仅微调少量模型参数大大降低了计算成本,常见的 LoRA (Low Rank Approximation)就属于 PEFT 方法。在针对于漏洞检测的领域,许多研究采用了 SFT 和 PEFT。 此外,在一个不考虑特殊优化方法的微调过程中,还要涉及模型选择和数据集选择:...

2024年11月20日 · 4 分钟 · eeuk

Datacon 2023 漏洞分析赛道赛题二官方题解

0x00 前言 赛题二附件.zip ​本题目来源于对openwrt项目源码魔改。基于实战中的场景,在题目中设置了三种相对固定且常见的漏洞模式,希望选手们在对固定漏洞模式理解的基础上,可以利用静态分析工具辅助进行分析,探索各种漏洞分析工具与人工分析相结合的漏洞挖掘模式,减少一定量的重复人工审计。 ​静态分析工具都有其自身的缺陷,分析的结果很难做到尽善尽美。因此站在一位漏洞挖掘工程师的角度,我设置本题的目标是探索如何合理的使用静态分析工具,并最大程度的利用这种自动化的方式帮助我们减少人工分析的工作。 这里的题解主要使用我们自研的二进制静态分析工具——破壳平台的交互式查询来辅助我们进行分析,大致来说有以下思路: 根据漏洞模式的某些参数特征进行匹配 定义source点和sink点进行污点追踪 根据漏洞模式上下文特征来匹配漏洞 我们将会介绍这三种思路来进行查询解题,具体漏洞的答案和查询规则在文末可见。 0x01 根据参数特征查询 根据参数特征查询适用于过滤一些常见的危险函数的危险操作。 1.1 针对strcat函数 例如如果strcat的二个参数是一个常量字符串的话是很难有溢出的,即使有溢出也难以造成很大的危害。故此这种情况我们一般不需重点关注。 在本次datacon赛题二中,我们对strcat进行查询并设置其第二个参数是一个变量的情况。这里我们的查询规则如下,查找类型为变量(identifier),callee的筛选是为了筛选出调用这个变量的函数要是strcat函数,最后index指定了这个变量是strcat的第二个参数(下标从0开始),as taintPropagationPath RETURN taintPropagationPath 是为了前端将结果显示的更好看一些。 MATCH (n:identifier) WHERE n.callee="strcat" AND n.index=1 WITH [n] AS taintPropagationPath RETURN taintPropagationPath 查询结果如下,可以看到符合的结果只有两条。因为查询到的结果并不多,所以可以进行一下人工验证。验证后发现恰好是我们题目设置的答案odhcpd:0x000036A9 odhcpd:0x000035F9 依据这种思路我们可以查询到 漏洞3,漏洞4 总结 与之类似的情况还有strcpy函数,我们依然可以依照上面的原则进行编写规则进行查询。 在现实情况中,如果我们上传了整个固件可以如此查询一下他system和popen的调用情况,那么如果他执行的是一个常量字符串那么肯定不可能是一个命令注入漏洞。因此我们可以同样对他system和popen的第一个参数类型进行限制,帮助我们初步筛选一下目标,减轻人工逆向的工作量。 1.2 针对memmove函数 首先我们来看下memmove函数的函数定义,第一个参数是dst,第二个参数是src,第三个参数是len void * memmove(void *dst, const void *src, size_t len); 通常memmove安全的使用方法有以下两种 调用memmove函数的时候第三个参数是一个固定的值 memmove(dest, src, sizeof(dest)); memmove的dest大小是根据第三个参数的大小申请出来的 dest = malloc(size); memmove(dst, src, size); 我们针对这两种情况进行排除,编写查询命令。其中not (m)-[:dfg]-(n)即是现在第一个参数跟第三个参数之间不存在直接的数据流关系 MATCH (n:identifier{callee:"memmove", index:0}), (m:identifier{callee:"memmove", index:2}) WHERE n....

2023年11月22日 · 6 分钟 · w00d