← 返回所有文章
发布于 · 作者 Renaud Deraison

那次更新加了一把密钥

10 月 29 日,Cursor 的扩展市场有十一个小时以 Anthropic 自己的发布者名称,提供了一个被植入木马的 Claude Code 扩展。它一加载就添加攻击者的 SSH 密钥、安装 LaunchAgent,并试图打开反向隧道,波及多达 5,000 名开发者的电脑。在 Bromure Agentic Coding 中,代理不是从编辑器市场来的;这类载荷会在一台谁也连不进去的 VM 里运行,它的隧道被出站防火墙拒绝,它的持久化在回退主目录后就消失。

没有人需要打开对话,也没有人需要批准任何工具调用。编辑器加载了扩展,66 行 JavaScript 就以开发者的身份运行,比 Claude Code 自己的代码还早。

10 月 29 日,太平洋时间大约凌晨 2:27 到下午 1:35 之间,Cursor 的扩展市场提供了一个被植入木马的 Anthropic Claude Code 扩展版本。Cursor 的安全公告点名了 anthropic.claude-code 的 2.1.312 和 2.1.313 版,这两个版本以 Anthropic 的发布者身份发布,并表示 Anthropic 并没有构建它们。BleepingComputer 报道称多达 5,000 名开发者受到波及,The Hacker News 则指出,开启了自动更新的人可能什么都没做就收到了它。

Phorion 和 OpenSourceMalware 的研究人员在 10 月 30 日发布了分析。Cursor 下架了这个扩展,关闭市场进行审计和密钥轮换,并让攻击者的服务器下线。至于这个版本是怎么以 Anthropic 的名义发布的,目前还没有人说明。

那 66 行做了什么

攻击者没有动 Claude Code 的代码,而是在它前面、extension.js 的开头放了一个 66 行的加载器。OpenSourceMalware 这样描述这种手法:“place a compact backdoor before a large legitimate bundle, suppress errors, and let the expected application continue”。编辑器一加载扩展并打开它的 webview,加载器就运行。开发者不需要开始任何对话。之后,真正的扩展照常加载并工作。

在这段时间里,加载器:

  1. 清点了环境。 主机名、用户名、操作系统、主目录和工作目录、git 全局邮箱、公网 IP,以及最多 40 个名称中含有 KEY、TOKEN、SECRET、PASS、AWS 或 GCP 的环境变量名。它把这些全部打包成 JSON,通过未加密的 HTTP 发送到 134.209.82.225:8099/beacon。
  2. 装了一扇门。 它把一把注释为 svc-telemetry 的 Ed25519 密钥追加到 ~/.ssh/authorized_keys。
  3. 试着打开这扇门。 在 macOS 上运行 sudo -n systemsetup -setremotelogin on,在 Linux 上尝试启动 sshd,在 Windows 上安装 OpenSSH Server。
  4. 向外拨号。 它把一把私钥写入临时文件,用 -N -R '*:0:localhost:22' 连接 [email protected]。这是一条反向隧道,把攻击者服务器上的一个端口转发回开发者自己的 SSH 端口。它每 60 秒重连一次。
  5. 让自己永久驻留。 macOS 上是名为 com.apple.sysmond 的用户 LaunchAgent,Linux 上是 crontab 的 @reboot 条目,Windows 上则是名为 SysMon 的计划任务。

据 BleepingComputer 报道,代码错误让许多受害者的 SSH 没能真正开启。但密钥、持久化和信标仍然落到了这些电脑上。Cursor 建议检查是否存在 svc-telemetry 密钥、移除持久化、考虑重建电脑(因为卸载扩展可能不够),并轮换这台电脑能接触到的每一组凭据,“using a trusted system”。

从一次扩展更新,到电脑上的攻击者密钥编辑器加载它2.1.312 / 2.1.313Anthropic 名义自动更新1 · 清点主机、用户、git 邮箱、公网 IP、KEY/TOKEN 变量名2 · 密钥svc-telemetry 加入authorized_keys开启 SSH3 · 持久化com.apple.sysmondcrontab @rebootSysMon 计划任务4 · 向外拨号反向隧道:22,信标:8099开发者自己的账户里,多了攻击者的密钥和回来的路就在 ~/.ssh、~/.aws、gh 登录和每个仓库旁边;Cursor 建议:考虑重建电脑
被植入木马的 Claude Code 扩展在加载时做了什么,依据 Cursor 的公告和 OpenSourceMalware 的分析。放在真正扩展前面的 66 行加载器清点了环境、添加攻击者的 SSH 密钥、安装持久化,并打开通往 134.209.82.225 的反向隧道和 HTTP 信标。

电脑上最受信任的代码

编辑器扩展以开发者的完整账户权限运行。它能读取主目录里的每个文件、启动进程,还能写入一个在编辑器关闭后依然存在的 LaunchAgent。市场推送更新不会先问你,而这次的发布者名称是 Anthropic。谨慎的开发者在安装前确认过发布者,也一样收到了后门:它是以几周前安装的扩展的更新形式到来的。

编码代理让风险更高。承载代理的扩展,正是开发者授权最多的那个:它读取整个仓库、执行命令,并待在一个持有环境中 API 密钥和云令牌的进程里。这个加载器拿走了这些变量的名称。要读取它们的值,也只需要同样几行。

同一个早上,在 Bromure Agentic Coding 里

Bromure Agentic Coding 在你 Mac 上的 Ubuntu VM 里运行 Claude Code、Codex、Grok、Kimi 和 omp。每台机器都是独立的 VM,代理、它的仓库、它安装的软件包和它执行的命令全都在里面。你输入文字的对话窗口和终端,是由 Mac 上的应用绘制的。真正的凭据、VM 流量经过的代理服务器,以及事情经过的记录,也都留在 Mac 上。

代理不是从编辑器市场来的

路径上没有扩展市场:Bromure 在 Mac 上绘制自己的对话窗口。Claude Code 是由一个配置步骤安装到你那份 Bromure 基础镜像中的,这个步骤列在一份目录里,目录的签名密钥与 Bromure 应用更新用的是同一把。该步骤从 npm 安装 @anthropic-ai/claude-code,外面套着 Socket.dev 的供应链扫描器。OpenSourceMalware 把这个 npm 包列在未受影响的分发渠道之中。

代理之后安装的任何东西都会经过 Mac 上的代理服务器,而代理服务器会应用这台机器的供应链策略。存在时间闸门默认开启,最短两天:npm、PyPI、Cargo、RubyGems 和 Packagist 上比这更新的版本会从仓库的列表中移除,所以 latest 会解析为已经公开两天的最新版本。Cursor 的恶意版本上架了十一个小时。npm 上一个存活时间相同的被劫持版本,永远不会出现在 Bromure 机器里。我们在那个版本才发布两小时中,以 LiteLLM 在 PyPI 上被投毒的版本详细讲过这种情况。

这把密钥打开的门,谁也到不了

假设这类载荷还是进了一台机器,通过代理克隆的仓库或它运行的工具。它在 Ubuntu 里、以机器的用户身份运行。它拿不到你的 macOS 账户、你的钥匙串,也拿不到你 Mac 上的 ~/.ssh。

它的 svc-telemetry 密钥会进入 VM 自己的 authorized_keys。机器位于应用内部的私有网络上:你的 Mac 能访问它们,你的物理局域网不能,除非你自己发布服务,否则外部任何东西都连不进来。唯一的入口本来就是那条反向隧道。

隧道从来没打开

隧道需要一条连往 134.209.82.225 的出站 SSH 连接,信标则需要通过未加密 HTTP 连到同一地址的 8099 端口。VM 发起的每一条连接都会经过 Mac,在那里应用这台机器的 Outbound connections 防火墙。它的规则匹配主机、IP 范围、协议和端口,只要把 Unmatched traffic 设为 Deny,就只有你列出的主机能通过。22 端口上的一个 DigitalOcean IP 不会在任何人的列表上。防火墙拒绝这条隧道、每 60 秒一次的重试,以及信标。

每一次拒绝都会记录在你 Mac 上的 Security Timeline 里,附带主机、端口、协议和判定结果。每分钟都对同一个 IP 的 deny 很难被忽视,而你会在攻击者还在等连接的时候就看到它。

清点到的东西一文不值

信标的变量名列表在 Bromure 机器里也会找到不少:ANTHROPIC_API_KEY、一个 GitHub 令牌、AWS 设置。但每一个值都是替身。真正的凭据加密保存在 Mac 上,代理服务器只有在请求发往该凭据所属的主机时,才会把替身换成真正的值。SSH 私钥根本不在 VM 里。SSH_AUTH_SOCK 是一座通往 Mac、只返回签名的桥,你 Mac 自己的 ssh-agent 从不对外暴露。就算加载器进一步读取这些值,拿到的也只是任何服务器都不会接受的字符串。如果它把其中一个发到自己的服务器,代理服务器会拦下请求、暂停 VM,并显示 This environment may have been compromised,指出是哪组凭据、要发往哪里。

清理只要一分钟

Cursor 要受影响的开发者移除密钥和持久化、考虑重建电脑,并从一台可信的系统轮换凭据。在 Bromure 里,重建只是两个菜单项。Bromure 每次启动都会为每台机器的主目录创建一个写时复制的检查点。Rewind home… 会把 /home/ubuntu 回退到载荷运行之前的某次启动,连同多出来的密钥和 ~/.config/.smt 启动器一起带走。Reset disk 会从基础镜像重新克隆系统磁盘,连同 crontab 一起带走。机器的设置、凭据和 SSH 密钥在这两种操作后都会保留。

Cursor 要求的那台可信系统就是 Mac,它从没运行过这个载荷。没有东西需要轮换,因为 VM 从来没持有过任何一组真正的凭据。

笔记本上的编辑器:加载器以你的身份运行扩展自动更新并加载在你的 macOS 账户里,就在真正的密钥旁Mac 上的密钥和持久化~/.ssh/authorized_keys 里的 svc-telemetryLaunchAgent com.apple.sysmond直连 134.209.82.225:22 反向隧道每 60 秒一次,:8099 信标处理:重建电脑,全部轮换Bromure:载荷在 VM 里运行机器 VM(Ubuntu)密钥在 VM 自己的 authorized_keys;只有替身每条连接都经过 Mac你 Mac 上的出站防火墙134.209.82.225:22 隧道:deny134.209.82.225:8099 信标:deny每次尝试都记在 Security Timeline之后,在机器关机时Rewind home… 和 Reset disk密钥、启动器、crontab 消失;设置和密钥保留
同样的载荷在 Bromure 机器里。它在机器的 Ubuntu VM 中运行,把密钥加进 VM 自己的 authorized_keys,而这个网络外部谁也连不进来;它只找到替身凭据。它的隧道和信标都经过 Mac,在那里被出站防火墙拒绝,Security Timeline 记下每一次尝试。Rewind home 和 Reset disk 移除持久化;Mac 和它真正的凭据毫发无损。

让有风险的工作有自己的机器

凭据和防火墙规则是按机器设置的,而创建机器的成本很低。专门试用新工具、插件和入门套件的机器,可以完全没有生产环境的凭据,并配上一个除了软件包仓库以外全部拒绝的防火墙。负责部署的机器保留它的凭据,但每次使用前都需要批准。如果只是一次性的实验,bromure-cli vm run --rm 会创建一台停止时就被删除的机器。

路径上没有市场

对话窗口是应用的一部分。Claude Code 来自 Anthropic 的 npm 包,通过已签名的配置步骤安装,并由 Socket.dev 扫描。

新东西先等两天

存在时间闸门会隐藏发布不满两天的软件包版本。一个只存活十一小时的被劫持版本永远不会被解析到。

一扇谁也到不了的门

被植入的密钥落在 VM 自己的 authorized_keys 里,位于你的局域网和互联网都连不进来的私有网络上。

拒绝未知的主机

把 Unmatched traffic 设为 Deny,反向隧道和信标都会被拒绝,每次尝试都记录在 Mac 上。

VM 里只有替身

VM 里的每个 API 密钥和令牌都是替身,SSH 私钥从不进入。清点到的东西一文不值。

回退而不是重建

Rewind home 和 Reset disk 会移除载荷的文件和持久化。设置、凭据和密钥都保留。

运行代理的工具,本身就是攻击面的一部分

Cursor 和 Anthropic 都还没说明那个版本是怎么以 Anthropic 的名义发出去的。对你自己的电脑来说,这起事件说清楚了一件事:承载你编码代理的软件以你的账户运行、会自行更新,而更新上一个可信的发布者名称,并不能证明它的内容。

在 Bromure Agentic Coding 中,你的代理和它接触的一切都在你 Mac 上的 VM 里运行。这台 VM 只持有替身、只能访问你允许的主机,还能回退到出事之前的某次启动。真正的密钥从不离开 Mac。

关于如今连编码代理的令牌和历史记录都一起收集的窃密木马,请读他们把你的智能体加进了名单。关于一场从开发者笔记本电脑开始、最终损失 63 亿美元的入侵,请读笔记本电脑就是入口。