大语言模型在安全编码中的可靠性评估

本文通过实验评估了Claude Code和OpenAI Codex在检测Python Web应用安全漏洞方面的表现,研究发现AI在识别IDOR漏洞方面表现良好,但在SQL注入和XSS检测上准确率较低,且存在非确定性问题。

评估AI漏洞检测:大语言模型在安全编码中的可靠性如何?

AI能否发现真实世界中的安全漏洞?Semgrep的研究比较了LLMs在捕获SQL注入、XSS和IDOR漏洞方面的能力。

大型语言模型(LLMs)可用于生成源代码,这些AI编码助手改变了我们生产软件的方式。加速语法检查、生成测试用例和建议错误修复等样板任务,加快了交付生产就绪代码的时间。但是,保护我们的代码免受漏洞影响呢?

如果AI能在上下文窗口中理解整个代码库,人们可能会得出结论:它们也可以取代基于源代码静态分析的传统安全扫描工具。最近的一个安全研究项目对这个想法进行了测试,发现AI在识别某些类别问题的漏洞方面确实有效,但并不一致或可预测。

实验:AI对抗AI

安全研究人员评估了两个AI编码代理——Anthropic的Claude Code(v1.0.32,Sonnet 4)和OpenAI的Codex(v0.2.0,o4-mini)——在11个大型、积极维护的开源Python Web应用程序上的表现。

他们产生了400多个发现,我们的安全研究团队逐一进行了手动审查。结果很有趣:

  • Claude Code:发现46个真实漏洞(14%的真阳性率,86%假阳性)
  • Codex:发现21个真实漏洞(18%的真阳性率,82%假阳性)

是的,使用AI工具,我们可以在实时代码中识别真实的漏洞和安全缺陷。但就这作为常规工作流程的有效性而言,全貌更加微妙。

AI漏洞检测在上下文推理方面表现良好

AI代理在发现不安全的直接对象引用(IDOR)漏洞方面出奇地好。这些安全漏洞发生在应用程序使用可预测的标识符(如URL中的ID)暴露内部资源,而不验证用户是否有权访问它们时。

想象一下,您正在浏览在线商店的订单历史,并注意到这样的URL:

1
2
HTTP
1/findings-report/dzone

如果您将"dzone"改为"faang",突然看到别人的报告,那就是一个IDOR。出现此漏洞是因为后端代码假设知道报告ID意味着您有权查看它,这是一个错误的假设。

以下是该代码可能的样子:

1
2
3
4
def get_report(request):
    id = request.GET.get("id")
    report = get_report_safely(id)
    return JsonResponse(report.to_dict())

从程序分析的角度来看,如果get_report_safely()查找正在清理用户输入中的无效转义字符或其他注入攻击,这段代码可能没问题。然而,程序分析在这里很难做到的是识别缺少代码,特别是授权检查。用户输入处理是有效的;问题是提供它的用户未被授权。

像Claude Code这样的AI模型非常擅长发现这种模式。在我们的研究中,Claude在IDOR上达到了22%的真阳性率,远优于其他漏洞类型。

AI在数据流方面遇到困难

当涉及传统的注入漏洞,如SQL注入或跨站脚本(XSS)时,AI的性能急剧下降。

  • Claude Code的SQL注入真阳性率:5%
  • Codex的XSS真阳性率:0%

为什么?这些类别的漏洞需要理解不受信任的输入如何通过应用程序传播——一个称为污点跟踪的过程。污点跟踪是能够从数据源(如用户输入)跟踪到其接收器(该数据被使用的地方,如数据库查询或HTML页面)。如果该路径未经过适当的清理或验证,可能导致严重的安全问题。

以下是一个SQL注入漏洞的简单Python示例:

1
2
3
4
5
def search_users(request):
    username = request.GET.get("username")
    query = f"SELECT * FROM users WHERE name = '{username}'"
    results = db.execute(query)
    return JsonResponse(results)

这可能看起来无害,但如果不受信任的数据进入此函数,它可以被利用来暴露用户表中的每条记录。安全的版本将使用参数化查询。当像这样的函数在库之间远离请求对象被抽象化时,这会变得更加复杂。例如,从一个模块中的Web表单到另一个模块中的数据库调用。这就是当今LLMs遇到困难的地方。它们的上下文推理帮助它们识别看起来有风险的模式,但如果没有对数据流的深入理解,它们无法可靠地判断哪些输入是真正危险的,哪些已经是安全的。

混沌因素:非确定性

即使AI识别了模式,它也经常错过清理逻辑或生成破坏功能的"修复"。在一个案例中,模型试图通过双重转义HTML来修复DOM操作问题,在此过程中引入了一个新错误。

我们研究中最引人入胜(也最令人担忧)的部分是非确定性——AI工具每次运行时产生不同结果的特性。

通过在同一个应用程序上连续运行相同的提示三次来测试这一点。结果各不相同:

  • 一次运行发现3个漏洞。
  • 下一次发现6个。
  • 第三次发现11个。

虽然这可能看起来像是逐渐变得更彻底,但这不是解释;每次都是不同的发现。

这种不一致性对可靠性很重要。在典型的静态应用程序安全测试(SAST)流水线中,如果漏洞从扫描中消失,则假定它已被修复或代码已充分更改以假定问题不再相关。但对于非确定性AI,一个发现可能仅仅因为模型那次没有注意到它而消失。

原因在于LLMs如何处理大型上下文。当您向它们提供整个代码库时,它们在内部总结和压缩信息,这像其他压缩算法一样,可能是有损的。这被称为上下文压缩或上下文腐化。

重要的细节,如函数名称、访问装饰器,甚至变量关系,可能在运行之间被"遗忘"。把它想象成总结一部小说:您会捕捉主要情节,但会错过微妙的线索和支线故事。

基准测试和进步的幻觉

评估AI工具的安全性比看起来更难。许多现有的基准测试——如OWASP JuiceShop或易受攻击的应用程序数据集——不是很现实。这些项目很小,是合成的,并且通常通过训练数据已经为模型所知。

当我们测试真实的、现代的Python Web应用程序(Flask、Django、FastAPI)时,我们发现模型对每个代码库的表现不同。有时更好,有时更差,但更重要的是,可变性创造了进步的幻觉。

换句话说,不要只对AI工具进行一次基准测试,因为那是轶事。您需要反复测试它们,跨越真实代码。它们的非确定性行为意味着一次运行可能看起来很好,而下一次可能错过许多关键发现。

当"假阳性"仍然有用时

虽然80-90%的假阳性率听起来很糟糕,但一些"错误"发现实际上是良好的防护栏。例如,Claude Code经常建议参数化一个已经安全的SQL查询。从技术上讲,这是一个假阳性,但它仍然是一个好的安全编码建议,与标记样式改进的linter没有什么不同。结合使用LLM生成该问题修复的便利性,假阳性的成本降低了。

然而,您不能完全依赖AI来知道区别并避免破坏您需要的行为。在生产安全流水线中,噪音很快成为负担。最佳点是使用AI工具作为助手,而不是权威。它们非常适合想法生成、分类提示或优先级排序,但与确定性分析配对时效果更好。

开发团队的关键要点

如果您是使用Claude、Copilot、Windsurf、Ghostwriter等AI工具的开发者,这项研究可能感觉熟悉。它们擅长模式匹配和解释代码,但并不总是一致或精确。

当涉及安全时,不一致性成为一致的风险并导致不确定性。

以下是一些关键要点:

  • AI可以找到真实的漏洞。特别是逻辑缺陷,如IDOR和损坏的访问控制。
  • AI是非确定性的。运行相同的扫描两次可能产生不同的结果,因此,如果您已达到可接受风险的阈值,请预期可变性和不确定性。
  • AI在深度数据流方面遇到困难。注入和污点式漏洞仍然是静态分析的强项。
  • AI上下文可能有用。将发现视为围绕您正在构建的解决方案类型的防护栏。
  • 混合系统可以获胜。未来在于将AI的上下文推理与确定性的、基于规则的静态分析引擎相结合。

LLMs不会很快取代安全工程师或工具,但它们正在重塑我们思考软件安全的方式。

要查看方法和数据,请参阅原始报告:使用Claude Code和OpenAI Codex在现代Web应用程序中查找漏洞。

comments powered by Disqus
使用 Hugo 构建
主题 StackJimmy 设计