✨ 要点🔬 技术摘要
想象一下,你正试图在一面由数百万块完美砖块组成的巨大墙壁中,寻找一块唯一的、略有破损的砖头。
问题所在:“抛硬币”困境 通常情况下,要找到这些破损的砖块,你需要一个专家团队,他们研究过成千上万个破损案例,并准确掌握了它们看起来是什么样子的。这就是目前大多数计算机程序的工作方式:它们是“监督学习者”。但这里有一个巨大的问题:我们并没有足够的“破损代码”样本来让它们进行充分学习。
最近,我们拥有这些超级智能的 AI 模型(称为大语言模型,或 LLM),它们几乎读过了有史以来写过的每一段代码。你可能会想:“太棒了!既然它们见多识广,一定能识别出破损的地方。”但令人惊讶的是,当你仅仅问它们:“这行代码是不是坏了?”它们的表现并不比抛硬币好多少。它们擅长编写 代码,却不擅长评判 代码,因为它们被训练去模仿模式,而不是去发现错误。
解决方案:ANVIL(“找不同”游戏) 这项研究背后的研究人员开发了 ANVIL ,他们决定反其道而行之。他们不再试图教 AI “坏代码”长什么样,而是问道:“AI 认为一行‘正常’的代码应该长什么样?”
以下是 ANVIL 的工作原理,使用了一个简单的类比:
遮盖游戏: 想象你从一个故事中取出一行,用黑笔将其涂掉。然后你要求 AI 根据前后的句子来猜猜被遮盖的那一行原本是什么。
预期: 如果被遮盖的是一行正常、标准的代码,AI 很可能会猜对(或者非常接近),因为它已经见过这种模式数百万次了。
异常: 如果被遮盖的是一行“存在漏洞”(损坏)的代码,它很可能与其余训练数据相比显得怪异或不同寻常。AI 会难以猜出它。它可能会猜出一个完全不同的内容,或者表现得非常犹豫不决。
评分: ANVIL 衡量 AI 的猜测与原始代码行之间的差异程度。如果猜测偏差很大,或者 AI 显得很困惑,ANVIL 就会将该行标记为“异常”(可疑)。
“混合型”侦探 研究人员意识到,仅仅测量差异是不够的。有时一个微小的差异(比如将 > 改为 >=)是一个巨大的错误,但 AI 可能并不认为这是个大问题。因此,他们创建了一个“混合评分”(Hybrid Score),就像一个配备了四种工具的侦探:
精确匹配: AI 是否做到了 100% 正确?如果不是,这就是一个红旗信号。
困惑度计: AI 有多不确定?如果 AI 在模棱两可,那么代码可能很奇怪。
复杂度检查: 这行代码是否过于复杂?复杂的代码往往是错误隐藏的地方。
“损失”得分: 一个衡量 AI 对原始行感到多么“惊讶”的数学指标。
结果:大海捞针 团队在海量的真实代码数据集上测试了 ANVIL。
击败专家: 他们将 ANVIL 与现有的、确实需要训练数据的最佳工具进行了对比。尽管 ANVIL 没有使用任何训练数据,但它发现漏洞的准确率是其他工具的两倍。
上下文技巧: 他们发现,给 AI 阅读整个文件的上下文反而会造成困扰(就像试图通过观察整个谷仓来寻找一根针)。相反,ANVL 使用了一种“智能上下文”方法:它只关注可疑行周围的具体代码块(函数)。这使得它更快、更准确。
现实世界中的成功: 为了证明其在现实世界中的有效性,他们将 ANVIL 连接到一个“模糊测试器”(fuzzer,一种通过投喂随机数据来尝试破坏软件的工具)。ANVIL 帮助该模糊测试器发现了两个全新的、此前未知的漏洞,其中一个漏洞非常严重,甚至获得了官方的安全 ID(CVE)。
核心结论 ANVIL 证明了你不需要教 AI “坏代码”长什么样也能找到它。你只需要问 AI “正常代码”长什么样。当代码不符合“正常”模式时,它很可能就是坏的。这是一种更聪明、更快且更通用的方法,可以在不需要庞大的过去错误库进行学习的情况下,找到安全漏洞。
技术摘要:ANVIL —— 无需标注训练数据的基于异常的漏洞识别方法
问题陈述
基于监督学习的漏洞检测器由于缺乏大规模、高质量的标注训练数据集,其性能经常不尽如人意。虽然大语言模型(LLMs)在海量无标注代码语料库上进行了训练并在代码生成方面表现出色,但在直接提示其进行漏洞检测时,其表现却很差,准确率往往并不比随机猜测高。这种局限性源于 LLMs 是为了生成符合其训练分布的代码而训练的,而非针对“有缺陷”或“存在漏洞”的代码进行显式监督。因此,它们缺乏区分漏洞代码与良性代码的领域特定知识。此外,现有试图通过生成合成漏洞或选择特定代码特征来弥补数据短缺的尝试仅取得了有限的改进,因为合成数据无法捕捉到现实世界中漏洞的多样化表现形式。
方法论
本文介绍了 ANVIL ,一种将漏洞检测重新定义为异常检测 任务的行级漏洞定位方法。其核心前提是:漏洞代码是稀有的,因此相对于 LLMs 在预训练期间学习到的分布而言,构成了一种异常。
核心工作流
掩码代码重构(Masked Code Reconstruction): 对于正在分析的给定代码行,将原始行进行掩码处理(移除)。随后,指令 LLM 根据上下文信息重构该行。
异常评分(Anomaly Scoring): 将 LLM 生成的重构结果与地面真值(原始行)进行比较。偏差将被计为异常。高异常得分表明原始行对于模型而言是“分布外”的,暗示该行可能存在漏洞。
上下文选择(自适应上下文,Adaptive Context): 为了解决选择合适上下文的挑战,ANVIL 采用了**自适应上下文(AC)**策略。AC 并非使用固定的行窗口,而是选择包含被掩码行在内的最大复合语句(例如函数体)。这确保了模型能够接收到语义相关的上下文,同时避免了无关代码带来的噪声,也解决了与过长上下文相关的“迷失在中部(lost-in-the-middle)”问题。
混合异常评分
ANVIL 提出了一种混合异常评分 (δ h y b r i d \delta_{hybrid} δ h y b r i d ),它聚合了四个不同的组件来量化生成代码与原始代码之间的差异:
交叉熵损失 (δ l o s s \delta_{loss} δ l oss ): 重构行的平均交叉熵损失,用于衡量生成 token 的概率。
精确匹配指示器 (δ E M \delta_{EM} δ E M ): 一个二元指标,会对任何与地面真值的偏差进行惩罚。如果生成的行与原始行不完全匹配,则会贡献异常得分。这解决了软损失值(soft loss values)的局限性,即微小但关键的字符差异(例如 > 与 >=)可能会被低估。
首个 Token 方差 (δ v a r \delta_{var} δ v a r ): 一种衡量模型置信度的方法,通过计算前 10 个预测 token 在第一个生成位置的方差得出。漏洞行倾向于表现出中等程度的方差,而良性行通常表现为高方差(清晰的补全)或低方差(在简单上下文中进行规避/犹豫)。
AST 复杂度 (δ a s t \delta_{ast} δ a s t ): 一个基于原始行抽象语法树(AST)节点数量的指标。较高的复杂度与更高的被忽视边缘情况的风险相关联。
最终得分是这些组件的归一化总和,旨在奖励精确匹配,同时捕捉细微偏差、模型不确定性和代码复杂度。
核心贡献
ANVIL 框架: 一种新颖的行级漏洞检测方法,无需标注训练数据 ,利用预训练的 LLMs 通过掩码重构来识别作为异常的漏洞。
混合评分机制: 提出了并验证了一种复合评分函数,该函数结合了损失、精确匹配、置信度方差和句法复杂度,证明了这种组合优于单一指标。
自适应上下文策略: 引入了一种结构感知的上下文选择方法,能够动态识别相关的复合语句,与固定大小的窗口相比,提高了检测准确性和计算效率。
全面评估: 在多个 LLM 系列、上下文规模和评分方法上进行了严格评估,包括针对 LLM 训练截止日期后披露的漏洞进行的无泄漏评估。
实验结果
作者在 PrimeVul 数据集(一个大规模开源 C/C++ 项目集合)上对 ANVIL 进行了评估,并将其与最先进的监督检测器进行了对比:LineVul 、LineVD 和 LLMAO 。
性能对比监督检测器: ANVIL 显著优于所有监督基准模型。
Top-3 准确率: ANVIL 的准确率最高可达基准模型最优者的 2 倍 (31.3% 对比 17.3%)。
归一化 MFR: ANVIL 实现了 75% 的提升 (0.18 对比 0.39)。
ROC-AUC: ANVIL 达到了 61.8% ,远高于徘徊在接近随机猜测(~50%)水平的基准模型。
上下文与评分: 研究证实,混合评分 方法和自适应上下文 产生了最佳性能。低于 100 行的固定上下文会导致性能下降,而较大的固定上下文则会引入噪声和内存问题。
泛化能力: ANVIL 在包含 LLM 训练截止日期后披露的漏洞的无泄漏数据集上展示了强大的泛化能力,证明了其在无需重新训练的情况下检测未知漏洞的能力。
实用价值: 通过将 ANVIL 与模糊测试工具(fuzzers)集成以引导种子选择,作者发现了两个此前未知的漏洞 ,其中之一已被分配了 CVE 编号,证明了异常引导检测的实际应用价值。
重要性
本文声称,ANVIL 通过绕过标注数据的瓶颈,为漏洞检测提供了一种实用的替代方案。通过利用 LLMs 所学习到的代码内在的“自然性”,ANVIL 有效地在行级隔离了漏洞。结果表明,异常检测(特别是通过混合评分和自适应上下文增强后)可以超越当前的监督方法,尤其是在缺乏训练数据的全新或未知代码库场景下。这项工作强调,尽管 LLMs 本身可能并不真正“理解”什么是漏洞,但它们可以有效地识别出偏离正确代码统计规范的代码。
每周获取最佳 machine learning 论文。
受到斯坦福、剑桥和法国科学院研究人员的信赖。
请查收邮箱确认订阅。
出了点问题,再试一次?
无垃圾邮件,随时退订。