用 Claude 缩小代码攻击面
Anthropic 发布研究文章,探讨使用 Claude 减少代码攻击面。所给材料未包含具体方法、适用范围或效果数据。
完整中文译文
过去一年,我们发布了大量数据,表明前沿 AI 模型完全有能力发现并利用安全漏洞。然而,展示此前未知的漏洞可能如何被利用,只是前沿 AI 模型在网络防御领域发挥作用的起点。本文将概述我们在自动化攻击面分析与缩减方面的一些初步研究:利用 AI 模型梳理可达代码,然后移除特定部署无需暴露的部分,或限制对这些部分的访问。
自动化攻击面分析与缩减能够在短期内显著提升已部署软件的安全性。仅靠逐一发现并修复漏洞来保障软件安全,很难规模化:即使修复了一个严重漏洞,你对剩余漏洞仍然一无所知。相比之下,降低代码可达性可以减轻未知漏洞的严重程度,包括那些可能正在遭到利用的漏洞。这些技术不会消除代码中的未知漏洞,但会让攻击者更难触及这些漏洞,从而降低其严重程度。尽可能缩小代码库的攻击面,无需发现或修复任何一个具体漏洞,就能提升安全性。
下文将初步展示我们使用 Claude 对大型开源代码库应用攻击面缩减技术时收集的部分数据。我们希望借此说明,通过本文介绍的方法,Claude 能以经济可行的方式显著提升软件安全性。具体而言,我们让 Claude 分析了 25 个使用不同语言编写的项目,它发现了 493 个问题。结合这些结果,我们将讨论开发者如何将类似技术应用于自己的代码。
缩减代码库攻击面的方法
随着时间推移,软件往往会变得越来越复杂,新的抽象层、依赖和功能不断叠加。这常常导致软件的实际运行方式与最初开发者的设想大相径庭。这也是攻击者往往能够得手的重要原因:他们研究的是代码在实际运行中究竟如何表现,而非开发者希望或设计它如何工作。
自动化攻击面分析与缩减技术旨在发现不必要的攻击面,再为相应代码设置适当的访问门槛。例如,将代码从身份验证前移至身份验证后,从零点击触发改为需要一次点击,从默认启用改为必须显式选择启用,或从协议的第一条消息处理阶段移至会话状态机中更靠后的阶段。有些代码本来就应该在这些阶段之前可达,但许多代码并非如此。数千乃至数百万行代码持续变更所带来的复杂性,使得功能的不必要暴露往往难以被察觉。
缩减代码攻击面的方法有很多。在我们的研究中,重点关注了以下三种方法:
- 默认配置。 找出在软件随附的默认配置下可达、但并非任何默认功能预期会使用的代码。
- 配置交互。 找出单独看都合理、但组合配置后会引发问题的选项对,例如悄然禁用某项安全控制,或让某个功能的行为处于未定义状态,而其代码仍然可达。
- 过早可达。 找出在适当的安全控制(如身份验证)生效之前、无需受害者交互,或在协议状态转换之前就会运行的安全敏感且复杂的代码。
我们想了解,Claude 能在多大程度上根据这三类攻击面的描述,在庞大而复杂的代码库中发现真实问题。我们分析了 25 个开源项目,总计超过 500 万行代码,涉及 C、C++、Java、PHP 和 Python 等语言。Claude 为这些项目整理了一份包含超过 17,000 个配置选项的清单。其中,3,842 个选项涉及与安全相关的控制措施或功能的配置。
为开展研究,我们将这些开源项目划分为三大类:
- 公开型(Public)。 这类项目旨在为任何能够访问它们的用户提供服务,或处理由身份无法确认的参与方生成的数据。例如,解析上游应答的 DNS 解析器,或解析源站响应的代理。
- 认证型(Gated)。 这类项目旨在为经过身份验证的用户提供服务,例如拥有密码、持有密钥或证书的用户,或已注册的设备。软件仍然允许客户端发送任意请求,但在用户通过身份验证之前,不提供任何功能。
- 私有型(Private)。 这类项目的构建与部署旨在服务于运营方自身的私有环境。在这些场景中,可以选择添加身份验证层之类的控制措施,但这不属于软件本身的职责范围。
这些分类有助于结合背景理解我们的结果。例如,我们预期公开型代码库中会有相当大比例的代码在默认配置下可达,因为它本来就是为所有用户提供服务的;而认证型项目的情况则应当相反。
Claude 使用上述三种方法发现了 493 个问题。结果中有几个现象引起了我们的注意。
首先,Claude 发现,全部 11 个认证型项目都存在非预期可达的代码,尽管这些代码占各项目总代码行数的比例都不高。具体而言,Claude 在认证型项目的默认配置中发现了 93 处不必要的身份验证前攻击面、37 处在身份验证前执行代码或记录状态的位置,以及 61 种会悄然削弱管理员所配置的身份验证前控制措施的配置组合。这些问题单独来看都无法被立即利用,但它们使攻击面远超实际需要。
按项目类别和分析技术划分的问题数量。在我们评估的 25 个项目中,10 个属于公开型,11 个属于认证型,4 个属于私有型。认证型项目的结果最令人意外,其中发现了大量过早可达的问题。

其次,在所有项目类型中,Claude 为缓解配置交互问题所做的工作,带来了一些最有意思、也最具影响力的发现。Claude 找到了 162 种安全敏感的配置组合:软件接受这些组合时既不报错也不发出警告,文档也未说明这些配置交互时的预期行为。其中有 94 种组合会悄然关闭某项安全控制。其余 68 种情况则表现为相关安全机制内部的不一致,例如:配置显示某个监听器或登录路径已禁用,但它仍然可达;两个设置相互冲突,最终哪个生效取决于它们在配置文件中的顺序;或者管理员配置的某项防护完全不起作用,而其代码依然可达。虽然其中一些配置组合可能并不常规或很少使用,但这些项目中没有任何机制阻止管理员以这种方式配置和部署代码。
Claude 还发现了一种特定模式,它分别出现在四个互不相关的项目中,具体过程如下。管理员使用主机名或通配符模式,而非 IP 地址,为远程客户端编写访问规则。客户端连接时,服务器会将该规则与客户端的主机名进行匹配。服务器能否获取这个主机名,取决于另一个控制反向 DNS 查询的选项,而大多数项目默认关闭了该选项。关闭查询后,服务器只有客户端的 IP 地址,于是会将规则与该地址按纯文本进行匹配。但主机名模式永远无法匹配 IP 地址。这意味着拒绝规则永远不会触发,拒绝列表会在失效时放行。部分受影响的项目在文档中提到,主机名规则依赖于启用 DNS 查询,但没有任何项目说明,以这种方式编写的拒绝列表会在失效时放行。
第三,Claude 经常发现,两个配置选项会相互冲突,导致某项安全检查被悄然跳过。在一个案例中,管理员可以要求每个连接的客户端通过证书证明自己的身份。另一个选项原本只是要将这项检查推迟到需要时再执行,实际却完全禁用了它。因此,一台被配置为只接受可信客户端的服务器,会接受任何人发起的连接。这使得大量原本应受证书检查保护的请求处理代码暴露给了未经身份验证的客户端。在默认设置下,软件允许同时使用这两个配置选项,且不会发出任何警告;文档也从未提及证书要求已被取消。这组相互冲突的配置选项已经在软件中存在了 21 年。
最后,Claude 在一个默认关闭身份验证、并期望管理员自行开启的项目中发现了一个问题。要求 TLS 客户端证书的选项在该项目的大多数网络端点上都能生效,但在少数端点上会被悄然忽略——这些端点通过使用不同命名空间的路径加载 TLS 设置。这意味着,没有证书的客户端也能在受影响的端点上完成 TLS 握手并建立会话。设置被忽略一事不会留下任何日志。该选项是否生效,取决于管理员在配置中使用的命名空间。设置名称的一种写法在所有端点上都有效,但大多数示例使用的较短写法,在受影响的端点上会被忽略。
令人意外的是,如果按减少的代码行数占总代码行数的比例衡量,Claude 缩减攻击面幅度最大的项目是 OpenSSH。OpenSSH 是一个提供安全远程访问功能的高质量 C 代码库。Claude 追踪了 10.4 版本中 SSH 守护进程的输入路径,发现未经身份验证的客户端在默认配置下,可以触达约 4,500 行用于后量子签名算法 ML-DSA-44 的新增实验性代码。ML-DSA 默认并未启用,但无论是否启用,这些代码都可以被触达,即使管理员明确排除了该算法也不例外。守护进程会解析客户端发来的任意密钥类型;对于证书,它还会验证其中嵌入的 CA 签名。直到这之后,它才会检查该密钥类型是否被允许。在配置尚未启用相应功能时,没有充分理由让这些复杂且不具备内存安全性的代码可被触达。这 4,500 行 ML-DSA-44 代码,约占默认 sshd 中 OpenSSH 自身身份验证前代码的 16%。我们向 OpenSSH 开发者报告了这一问题,并提交了补丁。10.5 版本将这项检查移到了解析之前。
随后,Claude 又发现了 10.5 版本检查中的两个缺口。第一个是客户端声称使用的算法与实际发送的内容可能不一致。检查针对的是客户端声明的算法名称,但解析器的选择依据却是密钥数据块内部嵌入的类型字符串。客户端可以声明使用 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 来分析和缩减其所依赖软件的攻击面。我们预计,这将成为开发者切实提升当今世界所依赖代码的安全性、并能衡量改进成效的最实用方法之一。