修漏洞这件事,从业者一直有个朴素的抱怨:找到一个、堵上一个,账单上剩下的洞一个没少。Anthropic 的前沿红队最近换了个思路——不去猜下一个洞在哪,而是去问「这套部署下,哪些代码根本不该被摸到」。
他们在 10 月 20 日发布的研究文章(https://www.anthropic.com/research/attack-surface-reduction)里,把这个思路叫作攻击面分析与削减,并用 Claude 跑了一遍:25 个开源项目、超过 500 万行代码,涉及 C、C++、Java、PHP 和 Python。Claude 为这些项目盘出了超过 17000 个配置项,其中 3842 个与安全相关的控制或功能有关,最终报出 493 个问题。
三种查法,不是三种找 bug
文章里明确区分了「找漏洞」和「削可达性」:前者针对具体缺陷,后者降低那些尚未被发现的缺陷的严重度。
第一种查默认配置:哪些代码在出厂配置下就可达,却没有任何默认功能会用到它。
第二种查配置交互:哪些选项单独看都合理,凑一起就出事。Claude 找到 162 组安全敏感的组合,既不报错也不告警;其中 94 组直接把某项安全控制静默关掉,剩下 68 组则是同一机制内部的不一致,比如配置声明某监听已禁用、实际路径却还留着。
第三种查早期可达:哪些敏感又复杂的代码跑在安全控制(通常是认证)之前,或者跑在协议状态机切换之前。
最意外的是需要先登录的那一组
Anthropic 把 25 个项目分成三类:面向任意来访者的 Public 10 个、面向已认证用户的 Gated 11 个、仅供运营方私用的 Private 4 个。逻辑上 Public 天然有大量默认可达代码,Gated 则本该相反——结果恰恰是 Gated 组最出人意料:默认配置下 93 处不必要的认证前暴露面、37 处认证前就执行代码或记录状态的位置、61 组静默削弱认证前控制的配置组合。
另有两个个案更能说明问题。一个反向 DNS 的 fail-open 模式在四个互不相关的项目里各自独立出现:管理员用主机名而非 IP 写访问规则,而反向 DNS 查询默认关闭,服务器只拿到 IP,主机名模式永远匹配不上 IP,于是拒绝规则永不触发。另一个是证书校验冲突,一个本意是「延迟校验」的选项实际把校验整个关掉,只接受可信客户端的服务器会接受任何人,而这组冲突的选项在软件里存在了 21 年。
OpenSSH:审计最狠的代码也漏了
Anthropic 称,按代码行占比计,25 个项目里 OpenSSH 的攻击面降幅最大。10.4 版本中,Claude 沿 sshd 的输入路径追踪到约 4500 行 ML-DSA-44(后量子签名算法)的新实验代码,未认证客户端在默认配置下就能触达。ML-DSA 默认并未启用,甚至管理员显式排除该算法,代码照样可达——守护进程先解析客户端发来的密钥类型(证书还会验证内嵌 CA 签名),之后才去查这个类型是否被允许。那 4500 行约占默认 sshd 认证前代码的 16%。
10.5 把检查挪到了解析之前,Claude 又指出两处遗留:一是检查看的是客户端宣称的算法名,而解析器由密钥内部的一个类型串决定,客户端可以宣称 ssh-ed25519 通过检查、却塞进一把 ML-DSA 密钥;二是证书路径没被挡住,攻击者提供的证书会让 sshd 对任意受支持算法跑完整验签,把二进制里每个公钥验证器都暴露出去。最终的修复把检查放进解析器内部,在反序列化和验签之前先比对允许列表。Anthropic 称这修掉了默认构建下未认证客户端可达代码的约五分之一。
这一点在 OpenSSH 官方 10.6 发布说明里能对上:该版本确实加入了「在密钥解析期间就拿允许列表比对密钥与 CA 的签名类型」,并注明由 Chris Rohlf 联合 Claude 与 Anthropic Research 提出并提供了大量反馈(https://www.openssh.com/releasenotes.html)。官方还提到,近期收到大量安全报告,其中不少来自 AI 模型或其辅助,因此会改为更频繁地发版。
怎么落地,以及我的看法
这套方法被打包成一个 Claude skill,Anthropic 说正在整合进面向开源项目的自愿扫描服务 OSS-Scanner。skill 对代码库跑三趟,每趟都开干净的上下文窗口,只从上一趟继承一小段上下文;每趟都先盘出入口点,再用动态轨迹确认每条发现。涉及默认配置的改动会被一道闸拦住——跑项目自带测试套件加一套黑盒回归套件,要求改前改后结果一致;任何会动到非默认配置的改动则留给人类决定。
我的看法是,这件事的价值恰恰不在「AI 又发现了多少洞」,而在它换了一个衡量单位。493 这个数字读起来平淡,也大概率不会单独构成什么安全事故;真正被改掉的是严重度的分母。当 OpenSSH 这样被审到教科书级别的代码都能默认露出 4500 行可达的实验性解析代码,那么「未被发现的漏洞」这个一直无法量化的东西,第一次有了可操作的替代指标:不修 bug,只让够不着的代码不够着。
这条路子对运维和自研服务的负责人尤其现实——你未必需要买更大的扫描器,你需要的是知道自己这套部署到底暴露了什么。文中提到的把运行时日志与配置做比对,也是同一思路的延伸:关掉没人用的解析器、遗留协议和空面板,成本极低,安全收益直接。