跳到正文
Anthropic Research·· 5 小时前精选AI 评分70

Anthropic 用 Claude 减少代码攻击面,在 25 个开源项目中发现 493 个问题

Using Claude to reduce the attack surface of code

AI 导读

Anthropic 公布用 Claude 对 25 个开源项目(超 500 万行代码,涵盖 C、C++、Java、PHP、Python)做自动化攻击面分析的结果,共发现 493 个问题,并梳理出 17,000 多个配置项。

推荐理由

Anthropic 用 Claude 扫描 25 个开源项目并给出 OpenSSH 的实际修复过程,展示了减少攻击面这条不依赖逐个修漏洞的防御路径。

正文 · AI 翻译

Chris Rohlf

在过去一年里,我们发布了大量数据,表明前沿 AI 模型完全有能力发现并利用安全漏洞。然而,展示此前未知的漏洞可能如何被利用,只是前沿 AI 模型在网络防御方面所能做之事的起点。在本文中,我们总结了我们在自动化攻击面分析与缩减方面的部分初步研究:即使用 AI 模型来梳理可达代码,然后移除或限制对特定部署无需暴露的任何内容的访问。

自动化攻击面分析与缩减可以在短期内切实改善已部署软件的安全性。仅通过发现和修复单个漏洞来保障软件安全,其可扩展性很差:即使修复了一个严重漏洞,也无法告诉你还剩下哪些漏洞。相比之下,缩减代码可达性可以降低未知漏洞的严重程度,包括那些可能正被积极利用的漏洞。这些技术并不会消除代码中的未知漏洞,但它们确实使漏洞更难被触及,从而降低其严重程度。最小化代码库的攻击面,无需发现或修复任何单个漏洞,就能带来更好的安全性。

下面,我们预览一些我们使用 Claude 对大型开源代码库应用攻击面缩减技术所收集的数据。我们这样做的目的是表明,Claude 可以通过我们概述的方法,有意义且经济地改善软件安全。具体而言,我们在 25 个以上项目(涵盖多种语言)上运行了 Claude,它发现了 493 个问题。基于这些结果,我们讨论了开发者如何将类似技术应用于自己的代码。

缩减代码库攻击面的方法

随着时间推移,软件有一种变得更复杂的倾向,新的抽象层、新的依赖项和新功能慢慢彼此堆叠。这常常导致其实际运行方式与最初开发者的意图大相径庭。这也是攻击者往往如此成功的一个重要原因:他们研究的正是一段代码在实践中的行为方式,而不是其开发者意图或设计的工作方式。

自动化攻击面分析与缩减技术旨在发现不必要的攻击面,然后将该代码移到适当的门控之后。这可能涉及将代码从预认证移到认证后、从零点击移到一点击、从默认开启移到显式选择加入,或从协议的第一条消息移到会话状态机更深处。有些代码本应在这些阶段之前可达,但很多并非如此,而且,考虑到跨数千或数百万行代码的代码变动所带来的复杂性,功能的不必要暴露往往不被注意。

有许多方法可以缩减代码的攻击面。在我们自己的研究工作中,我们特别关注了三种方法:

  • 默认配置。我们识别出了在其发布默认配置中可达、但并非任何默认功能所意图使用的代码。
  • 配置交互。我们发现了一些单独看似乎合理的选项组合,但当它们一起配置时就会引发问题(例如,静默禁用某项安全控制,或在代码仍可触达的情况下让某项功能的行为处于未定义状态)。
  • 早期可达性。我们识别出了安全敏感且复杂的代码,这些代码会在适当的安全控制(如身份认证)之前运行、无需受害者交互即可运行,或在协议状态转换之前运行。

我们希望了解 Claude 能在多大程度上利用这三种攻击面描述,在大型复杂代码库中发现真实问题。我们分析了 25 个开源项目(代码总量超过五百万行),涵盖 C、C++、Java、PHP 和 Python 等语言。Claude 在这些项目中梳理出超过 17,000 个配置选项的清单。其中,3,842 个与安全相关的控制或功能配置有关。

为便于研究,我们将这些开源项目划分为三大类:

  • 公开型(Public)。这类项目旨在服务任何能够访问到它们的用户,或消费由无法识别身份的一方所提供的数据。(例如,解析上游应答的 DNS 解析器,或解析源站响应的代理。)
  • 门控型(Gated)。这类项目旨在服务已通过身份认证的用户(例如持有密码、密钥或证书的用户,或已注册的设备)。软件仍允许任意客户端请求,但在用户通过身份认证之前,不提供任何功能。
  • 私有型(Private)。这类项目构建并部署用于服务运营者自身的私有环境。在这种情况下,添加身份认证层之类的控制是可选的,但不属于软件本身的范围。

这些分类有助于为我们的结果提供背景。例如,我们预期公开型代码库中有相当大比例在默认配置下即可触达(因为它本就设计为服务任何用户),而门控型项目则恰恰相反。

Claude 的发现

Claude 使用上述三种方法共发现了 493 个问题。从结果中,我们注意到几个突出的主题。

首先,Claude 发现全部十一个门控型项目都存在非预期可达的代码(尽管这些代码在各自项目的总代码行数中占比并不大)。具体而言,Claude 在门控型项目的默认配置中发现了 93 处不必要的预认证攻击面、37 处在身份认证之前执行代码或记录状态的位置,以及 61 种会静默削弱管理员所配置的预认证控制的配置组合。这些问题单独来看都不会立即被利用,但它们造成了远超必要范围的攻击面。

按类别和每种技术划分的问题分布。在我们评估的 25 个项目中,10 个为公开型,11 个为门控型,4 个为私有型。门控型项目组的结果最为出人意料,早期可达性发现数量很高。

其次,Claude 在缓解配置交互问题方面的工作产生了一些最有趣且最具影响力的发现(涵盖所有项目类型)。Claude 发现了 162 个安全敏感的配置组合,这些组合被接受时既没有报错也没有警告,且没有任何关于其交互预期行为的文档说明。在其中 94 个案例中,该组合会静默关闭某项安全控制。另外 68 个案例则是同一安全机制中的不一致(例如,某个监听器或登录路径尽管配置声称已禁用,却仍然可达;两项设置相互冲突,而哪一项优先生效取决于它们在配置文件中的顺序;或者管理员配置的某项保护实际上不起作用,而其代码仍然可达)。虽然其中一些配置组合可能非标准或很少使用,但没有任何机制阻止这些项目的管理员以这种方式配置和部署代码。

Claude 还发现了一种特定模式,该模式在四个互不相关的项目中独立出现。其运作方式如下。管理员会使用主机名或通配符模式(而非 IP 地址)为远程客户端编写访问规则。当客户端连接时,服务器会将这条规则与客户端的主机名进行比对。服务器是否能获知该主机名取决于一个控制反向 DNS 查询的独立选项(大多数项目将其配置为关闭)。在查询关闭的情况下,服务器只能获得客户端的 IP 地址。服务器会将规则与该地址作为纯文本进行比对。但主机名模式永远无法匹配 IP 地址。这意味着拒绝规则永远不会触发,该列表会失效开放(fail open)。一些受影响的项目在文档中提到,主机名规则依赖于启用 DNS 查询,但没有任何项目说明以这种方式编写的拒绝列表会具有失效开放行为。

第三,Claude 经常发现两个配置选项会以某种方式冲突,从而静默地丢弃某项安全检查。在一个案例中,管理员可以要求每个连接的客户端用证书证明其身份。在另一个案例中,代码本意只是将该检查延迟到需要时再执行,但实际上却完全禁用了该检查。因此,一台配置为仅接受受信任客户端的服务器会接受任何人的连接。这将大量请求处理代码(本应位于证书检查之后)暴露给了未经身份验证的客户端。该软件在默认设置下同时接受这两个配置选项且没有任何警告;文档从未提及证书要求已被丢弃。这组相互冲突的配置选项在该软件中已存在了 21 年。

最后,Claude 在一个项目中发现了问题:该项目默认关闭身份验证(并期望管理员手动开启)。要求 TLS 客户端证书的选项在该项目的大多数网络端点上都被正确执行,但在少数其他端点上却被静默忽略(这些端点通过不同命名空间的路径加载其 TLS 设置)。这意味着没有证书的客户端可以在受影响的端点上完成 TLS 握手并打开会话。对于被忽略的设置,不会记录任何日志。该选项是否生效取决于管理员在配置中使用的命名空间。设置名称的一种形式在所有端点上都能生效,但大多数示例使用的较短形式在受影响的端点上会被丢弃。

案例研究:OpenSSH

令人惊讶的是,按占总代码行数的百分比计算,Claude 实现攻击面缩减幅度最大的项目是 OpenSSH。OpenSSH 是一个高质量的 C 代码库,提供安全的远程访问。Claude 追踪了 10.4 版本中 SSH 守护进程的输入路径,发现约 4,500 行用于 ML-DSA-44(一种后量子签名算法)的新增实验性代码,未认证的客户端在默认配置下即可触达这些代码。ML-DSA 默认并未启用,但无论是否启用,这些代码都可被触达,即使管理员明确排除了该算法也是如此。守护进程会解析客户端发送的任何密钥类型(对于证书,还会验证内嵌的 CA 签名)。直到这时,它才检查该密钥类型是否被允许。这段复杂且内存不安全的代码在配置未启用时本不应可被触达。ML-DSA-44 的这 4,500 行代码约占默认 sshd 中 OpenSSH 自身预认证代码的 16%。我们连同补丁一起向 OpenSSH 开发者报告了此问题。10.5 版本将检查移到了解析之前。

Claude 随后指出了 10.5 检查中的两个缺口。第一个是客户端声称的算法与其实际发送的内容不一致。该检查查看的是客户端通告的算法名称,但解析器却是由密钥 blob 内嵌的类型字符串选择的。客户端可以通告 ssh-ed25519,通过检查,然后仍然发送一个会被解析的 ML-DSA 密钥。

第二个缺口在于 10.5 检查对证书的处理。证书密钥类型默认是启用的。给定攻击者提供的证书,sshd 会反序列化内嵌的 CA 公钥,并对其运行完整的签名验证——对任何受支持的算法都如此——而且是在查询配置之前。用户密钥签名路径被正确地限制在允许连接服务器的公钥列表之后,但 CA 签名路径却没有。这使得二进制文件中每一个公钥签名验证器都能被任何能完成密钥交换的客户端触达。我们构建了一个概念验证,并与维护者一起迭代了多个修复方案。最终的改动将检查放入了解析器内部。编码的密钥类型和证书的 CA 签名算法现在会在相应的反序列化或签名验证之前,与配置的允许列表进行比对。

此修复移除了默认构建中未认证客户端此前可能触及的 OpenSSH 代码的大约五分之一。其中几乎全部都是新的 ML-DSA 代码,现在即使客户端谎报其密钥类型,或在其他方面可接受的证书中隐藏 ML-DSA CA 密钥,也无法触及这些代码。使用允许的 CA 算法签名的证书仍会被解析和验证,但检查现在在解析之前运行。维护者在 10.6 版本中发布了此处描述的更改。

OpenSSH 是世界上经过最严格审计的代码之一。如果不必要的可达性在那里都能存活,那么它在任何地方都能存活。这表明,减少代码库的攻击面很可能在许多重要代码库中带来回报。

结论

或许无法衡量任何给定代码库中存在多少未知漏洞。而且有大量数据表明,攻击者有足够时间就能找到这些漏洞(尤其是配备前沿 AI 模型时)。但是,防御者减少代码中不必要的攻击面,就能一次性降低该代码中所有未知漏洞带来的风险——包括任何已在被悄悄利用的漏洞。OpenSSH 是世界上经过最严格审计的 C 代码之一。然而它发布了大约 4,500 行实验性签名解析代码,攻击者在任何配置检查之前就可能触及这些代码。

我们已将上述攻击面减少技术整合为一个可复用的 Claude 技能,并正努力将其集成到 OSS-Scanner 中。该技能对代码库运行三轮检查。每轮都从头开始(使用空的上下文窗口),只接收上一轮传递的一小段上下文。

在第一轮中,该技能检查是否存在默认配置允许触及、但任何预期功能都未使用的代码。在第二轮中,它检查在任何配置下、在任何硬性关卡(如身份验证)之前或协议状态机入口点之前运行的代码。最后,第三轮中,该技能评估哪些配置组合会静默关闭安全控制或降低其有效性。每一轮中,Claude 都会从代码中创建入口点清单,并通过程序的动态跟踪确认每项发现。对于默认配置的发现,它会设计并实现一个关卡,并确保这不会改变程序的默认行为。它通过针对基线运行项目自身的测试套件(以及黑盒回归套件)来实现这一点;它要求修改后的构建具有相同的结果。任何会改变非默认配置的关卡都会被搁置,交由人类决定。对于另外两轮,它会提出更改建议,例如重新排序配置检查、添加守卫以强制状态顺序,或在配置加载时拒绝该组合。即使不使用这个特定技能,我们认为此处概述的广泛方法很可能也是有效的。

本文概述的技术只能让人一窥攻击面减少的可能性中非常有限的一部分。例如,Claude 还能够分析和比较运行时日志与配置,以确保只启用了所需功能:禁用未使用的解析器、旧协议和仪表板能以很小的成本降低安全风险。

我们鼓励各组织探索使用 Claude 来分析和缩减其所依赖软件的受攻击面。我们预计,这将成为开发者切实提升当今世界已有代码安全性的最实用方式之一。

来源:Anthropic Research · anthropic.com