如果你正在学习软件安全或机器学习,你可能已经注意到人们对大语言模型 (LLMs) 的兴趣呈爆发式增长。我们知道 LLM 可以编写代码、解释算法,甚至翻译语言。但它们能担任安全审计员吗?它们能审视一段代码并告诉你: “嘿,这里有一个危险的 SQL 注入”吗?

简短的回答是肯定的,但有很大的局限性。虽然关于利用深度学习检测 C 和 C++ 等语言漏洞的研究已经相当深入,但网络上最主流的语言——PHP——却在很大程度上被遗忘了。这是一个巨大的缺口。PHP 支撑着前一千万个网站中近 80% 的网站,包括 WordPress 和维基百科等巨头。

今天,我们将深入探讨一篇名为 “RealVul: Can We Detect Vulnerabilities in Web Applications with LLM?” 的研究论文。这篇论文提出了一个名为 RealVul 的新颖框架,旨在解决检测 PHP 漏洞面临的特定挑战。

在这篇文章中,我们将探讨为什么传统数据集在 PHP 上失效,RealVul 框架如何智能地“切片”代码以发现漏洞,以及它如何利用合成数据训练出超越传统工具的模型。

现有数据集的问题

要训练一个 AI 模型来发现漏洞,你需要一个数据集。你需要成千上万个“有漏洞代码”和“安全代码”的示例。

历史上,研究人员使用一种称为漏洞修复 (Vulnerability Repair) 的方法来构建这些数据集。他们查看开源代码库 (如 GitHub) ,找到提及“修复漏洞”的提交信息 (commit messages) ,然后比较修复之前 (有漏洞) 和修复之后 (安全) 的代码。

这听起来很合乎逻辑,但在实践中,它充满噪声且往往不准确。

“Diff” 困境

当开发人员修复漏洞时,他们可能会更改配置文件、添加库或修改与实际触发漏洞完全不同的文件中的函数。

请看下面的 图 1 。 它展示了一个场景,其中漏洞涉及三个文件: page.phplib.phpconf.php

图 1: 在使用漏洞修复构建数据集的情况下,绿色部分将被视为安全,红色部分将被视为有漏洞。

在这个例子中,实际的修复发生在 conf.php 中 (添加了一个正则过滤器) 。然而,“漏洞修复”收集方法可能会查看提交中涉及的所有文件。它可能会将旧版本的 page.php 标记为“有漏洞”,将新版本标记为“已修复”,即使 page.php 中的代码根本没有改变

这会让模型感到困惑。它被告知两段相同的代码有不同的标签。此外,修复错误不仅仅意味着更改有漏洞的行;它通常涉及简单的“diff”差异对比无法捕捉的上下文。这种噪声使得 LLM 极难学习真正的漏洞是什么样子的。

RealVul 登场: 一个代码片段级的框架

为了解决这个问题,研究人员开发了 RealVul 。 RealVul 不依赖混乱的提交差异,而是使用静态分析来识别代码中特定的“触发点”,并仅提取验证漏洞所需的相关代码切片。

这种方法将重点从“文件”或“函数”转移到了代码片段上——即从用户输入导致潜在安全违规的精确逻辑序列。

这是 RealVul 系统的高层架构:

图 2: RealVul 架构概览。

工作流程包含四个主要阶段:

  1. 漏洞候选检测 (Vulnerability Candidate Detection) : 识别潜在的危险区域。
  2. 数据预处理 (Data Preprocessing) : 清洗和归一化代码。
  3. 数据合成 (Data Synthesis) : 人工创建更多训练数据。
  4. 模型训练 (Model Training) : 微调 LLM (如 CodeLlama 或 StarCoder) 以识别这些模式。

让我们一步步来拆解这些过程。

1. 漏洞候选检测与切片

这是框架中最具技术趣味的部分。你不能简单地将整个 2000 行的 PHP 文件喂给 LLM 并问: “这有 bug 吗?”。上下文窗口是有限的,而且噪声太大了。你需要隔离出真正重要的逻辑。

RealVul 使用基于污点分析 (Taint Analysis)程序切片 (Program Slicing) 技术。

在安全术语中,“源 (Source) ”是不受信任的数据进入应用程序的地方 (例如 $_GET['id']) ,而“汇 (Sink) ”是数据被危险使用的地方 (例如 mysql_query()) 。如果数据从源流向汇而没有经过清洗,就存在漏洞。

RealVul 自动化了这个发现过程:

  1. 识别触发器: 它扫描源代码以查找潜在的“汇”。对于 XSS 漏洞,这可能是一个 echo 语句。对于 SQL 注入,它会查找 SQL 字符串中的变量拼接。
  2. 抽象语法树 (AST) 分析: 它将 PHP 代码转换为树状结构 (AST) ,以理解不同代码行之间的关系。
  3. 流分析: 它向后追踪汇中使用的变量。它们从哪里来?它提取影响这些变量的语句。

图 3 清晰地展示了这个过程。

图 3: 从真实 PHP 项目中检测漏洞候选的过程。我们识别潜在的漏洞触发器,并通过源文件的 AST 分析数据流和控制流。获得的代码片段就是我们的样本。

在左侧,你看到一个完整的 PHP 源文件。它包含 HTML、数据库连接和逻辑。RealVul 将其解析为 AST (中间) ,识别数据流 (红色箭头) ,并提取代码片段 (右侧) 。

注意最终的片段是如何移除数据库连接设置、HTML 头部和其他无关行代码的。它只保留了 $_GET 数据被赋值给变量并最终被回显或在查询中使用的逻辑。这部分“提炼”后的代码正是 LLM 将要分析的内容。

2. 数据预处理和归一化

一旦片段被提取出来,它们仍然是“原始”的。RealVul 执行几个清洗步骤,使数据更容易被模型学习:

  • 打标签 (Labeling) : 由于提取过程遵循通往“汇”的特定路径,系统可以根据数据是否经过清洗 (安全) 或未经过清洗 (有漏洞) 来标记片段。
  • 归一化 (Normalization) :
  • 移除常量字符串: Web 应用程序充满了 HTML 字符串 (例如 <div class="menu">) 。这些不影响漏洞的逻辑。RealVul 将它们移除以减少噪声。
  • 重命名变量: 名为 \(user_id 的变量与 \)uid 的行为是一样的。为了防止模型过度拟合特定的变量名,RealVul 将变量映射为通用名称,如 \(var1\)var2 等 (但它保留了函数名,因为它们带有语义信息) 。
  • 去重 (Deduplication) : 它移除相同或高度相似的片段,以防止模型死记硬背重复内容。

3. 数据合成

训练 AI 进行安全检测的最大障碍之一是缺乏“有漏洞”的样本。在大多数开源项目中,99.9% 的代码是安全的。如果你在这样的数据上训练,模型只会学会一直说“安全”。

为了解决这种不平衡,RealVul 采用了数据合成 。 它提取“纯粹”的漏洞模式 (简短、清晰的 bug 示例) ,并将它们注入到复杂的、现实世界的“干净”函数中。

这创建了一个半合成数据集 。 它具有真实代码的复杂性 (复杂的控制流、奇怪的逻辑) ,但包含已知的漏洞。这使得研究人员能够显著扩充他们的训练数据,确保模型看到足够多的反面教材。

实验结果

研究人员通过微调几个最先进的代码 LLM (包括 CodeLlamaStarCoder2CodeT5 )来评估 RealVul。他们专注于两种主要的漏洞类型:

  • CWE-79: 跨站脚本攻击 (XSS)
  • CWE-89: SQL 注入

有效性 vs. 基线

第一个测试很简单: RealVul 是否比传统的“漏洞修复”数据集方法效果更好?

结果令人震惊。

表 1: 随机样本上的评估结果。ΔF1 是 RealVul 与基线方法之间 F1 分数的差值。

表 1 所示,RealVul (表格上半部分) 持续碾压基线方法 (下半部分) 。请看 F1 分数 , 它是精确率和召回率的平衡指标。

  • 对于 CodeLlama-7b 在 XSS (CWE-79) 上的表现,RealVul 达到了 83.68 的 F1 分数,而基线仅为 32.35 。 这是一个 +51.3 分的提升。
  • 对于 SQL 注入 (CWE-89) ,提升更为显著,在某些情况下提高了超过 +70 分

这证明了数据的准备方式与所使用的模型一样重要,甚至更重要。在使用 RealVul 数据训练的小模型 (如 CodeT5-base) 上,其表现优于在使用噪声数据训练的庞大模型。

与 SAST 工具的比较

静态应用程序安全测试 (SAST) 工具,如 RIPSFortify SCA , 是行业标准。它们使用严格的规则引擎来查找 bug。LLM 相比之下如何呢?

表 3: RealVul 与两个 SAST 工具的比较。我们还提供了评估所需的时间。

表 3 展示了对比结果。

  • 对于 XSS (CWE-79) : SAST 工具 (RIPS) 在原始识别率上稍好,但 RealVul 极具竞争力。
  • 对于 SQL 注入 (CWE-89) : RealVul 显著优于传统工具。RIPS 仅发现了 3 个真阳性 (TP) ,而 RealVul 模型发现了大约 30 个。

为什么 SAST 在 SQL 注入上失败了?传统工具通常依赖匹配特定的函数名 (如 mysql_query) 。如果开发人员将该函数包装在自定义辅助类中或使用框架,SAST 工具可能会漏掉它。而 RealVul 分析的是字符串拼接到 SQL 命令的,使其能够捕捉到基于规则的工具所遗漏的漏洞。

归一化有帮助吗? (消融实验)

你可能会想,“归一化”代码 (重命名变量、移除 HTML) 真的有帮助吗,还是会破坏有价值的上下文?研究人员通过在有无归一化的情况下训练模型来测试这一点。

图 4: 消融研究结果的比较,以及前两个实验结果的可视化。

图 4 对此进行了可视化。蓝色柱状图 (带有归一化的 RealVul) 通常比橙色柱状图 (无归一化) 达到更高的 F1 分数。灰色柱状图代表旧的基线方法。

数据证实,剥离“噪声” (如变量名和 HTML 内容) 有助于 LLM 专注于漏洞的结构逻辑,从而提高其预测性能。

案例研究: 眼见为实

为了真正体会 RealVul 带来的差异,让我们看看输入模型的实际数据。

下面的 图 5 比较了通过传统方法获得的样本与通过 RealVul 获得的样本。

图 5: 通过漏洞修复和 RealVul 获得的两组样本案例。我们标记了数据流和潜在的漏洞语句。

  • 片段 (a) & (b): 这些展示了 RealVul 提取的干净片段。注意它们是多么聚焦。在片段 (b) (CWE-89 案例) 中,你可以清楚地看到数据从 \(var1\)var2 流向 $staint,然后用于查询。没有任何杂乱的内容。
  • 脑补对比一下: 想象一个原始文件可能有数百行长,包含 CSS、JavaScript 和无关的 PHP 逻辑。

因为 LLM 看到了这些聚焦的片段,它可以学习漏洞的模式 (例如,“将用户输入拼接到 SQL 字符串中”) ,而不是死记硬背特定文件的无关特征。

结论与启示

RealVul 框架代表了自动化安全审计向前迈出的重要一步。通过摆脱充满噪声的“基于提交”的数据集,并拥抱静态分析 + LLM 的混合方法,研究人员在 PHP 漏洞检测方面取得了最先进的成果。

核心要点:

  1. 垃圾进,垃圾出 (Garbage In, Garbage Out) : 数据集的质量比模型的大小更重要。通过切片和归一化清洗数据带来了巨大的性能提升。
  2. 混合方法致胜: RealVul 不仅仅是“问 ChatGPT”。它使用传统的程序分析 (AST、控制流图) 在 AI 介入之前准备数据。这种经典计算机科学理论与现代 AI 的结合非常强大。
  3. PHP 安全至关重要: 作为网络的支柱,改进 PHP 安全工具具有巨大的现实意义。

随着 LLM 的不断发展,我们可以期待像 RealVul 这样的工具被集成到 IDE 和 CI/CD 管道中,充当智能结对程序员,在安全缺陷进入生产环境之前将其捕获。