Cursor市场Claude Code扩展被植入SSH后门:一次供应链投毒的完整拆解与自查手册

摘要 :2026年10月29日,Cursor 编辑器的扩展市场里出现了 Anthropic.claude-code 的恶意版本(2.1.312 / 2.1.313),安装后会向 ~/.ssh/authorized_keys 写入攻击者公钥、建立反向 SSH 隧道并落地持久化。本文拆解这次投毒的完整攻击链,给出可以直接跑的排查脚本,以及普通开发者该养成的三个习惯。如果你在用 Cursor 且装过 Claude Code 扩展,建议直接跳到第4节自查。

如果你这几天刷过 Hacker News,可能见过那个 562 分的帖子------安全公司 Phorion 披露:Cursor VS Code 扩展市场上的官方 Claude Code 扩展被投毒了。我第一反应是"又一个 npm 恶意包",点进去看完技术细节才发现,这次的东西比想象中精致:攻击者直接在官方扩展的 bundle 前面塞了一段注入代码 ,SHA-256 校验值是 ecb58cb29078d9646ad1dcdbe51526f2d9cfea06be5fb2ab183e8ecc3ab6bf15。

事件窗口只有约11小时(太平洋时间 10月29日 凌晨2:27 到下午1:35),但装上的人就是把自己的开发机钥匙递了出去。

1. 背景与痛点:为什么编辑器扩展是完美投毒载体

先交代背景。Cursor 是一个基于 VS Code 的 AI 编辑器,它有自己的扩展市场(Cursor Marketplace),格式和 VS Code 生态兼容。问题在于:扩展以 IDE 和当前用户的权限运行 。这意味着一个恶意扩展在 activate() 被调用的瞬间,就能:

  • 读本地文件和源代码
  • 访问开发工具链(git 凭证、SSH 密钥、云凭证环境变量)
  • 写任意用户目录(包括 ~/.ssh/)

对攻击者来说,开发机是性价比最高的目标------一台机器上往往同时躺着源代码、云账号凭证、CI 密钥。而大多数开发者对"装个扩展"这件事的心理防线,约等于零。

这次事件的诡异之处在于:恶意版本来自官方扩展的镜像分发渠道被污染,第三方冒充的痕迹反而没有。Cursor 官方声明明确说:这些版本不是 Anthropic 开发的,且只影响通过 Cursor 市场分发的 Windows 和 macOS 版本。Anthropic 官方渠道(VS Code 市场和 npm)的 2.1.313 虽然也被 Cursor 联动下架排查,但没有证据表明官方分发被波及。

2. 技术原理:三段式攻击链

2.1 注入方式

被篡改的 extension.js 在压缩后的正常 bundle 前面 追加了一个立即执行函数(IIFE)。也就是说,文件的其余部分------Claude Code 的正常代码、activate/deactivate 导出、UI 字符串------全都完好无损。扩展功能一切正常,杀毒扫描也看不出异常,这是供应链投毒的标准做法。

2.2 攻击链三阶段

恶意代码加载后分三步走:

阶段一:铺路。 收集主机信息(hostname、用户名、OS、架构、home 目录、环境变量名、工作目录、git 邮箱、公网 IP)并 POST 给攻击者服务器。同时在 ~/.ssh/authorized_keys 里追加一把 Ed25519 公钥(注释为 svc-telemetry)。注意这一步用的是 Node.js 的 fs.appendFileSync 直接写文件------不经过 shell ,所以那些监控 echo/tee 命令触碰 authorized_keys 的进程规则全部失效。

阶段二:打洞。 用内置的另一把私钥(注释 svc-telemetry-tun)连到攻击者服务器 134.209.82[.]225 的 22 端口,建立反向 SSH 隧道,参数是 -R *:0:localhost:22------让攻击者服务器动态分配端口,把流量转回受害者本机的 22 端口。攻击者想进入时,通过隧道用阶段一植入的密钥登录本地 sshd,拿到完整交互 shell。有 autossh 用 autossh,没有就用裸 ssh,外面包一个 60 秒重试的脱离循环,IDE 关了隧道也不断。

阶段三:赖着不走。 macOS 上伪装成系统服务 com.apple.sysmond.plist 放进 ~/Library/LaunchAgents/;Linux 写 @reboot crontab;Windows 建一个请求 SYSTEM 权限的名为 SysMon 的计划任务。持久化脚本藏在 ~/.config/.smt,私钥落在 ~/.config/.smtk。

复制代码
flowchart TD
    A[安装恶意扩展 2.1.312/2.1.313] --> B[IIFE 注入代码随 activate 执行]
    B --> C[阶段一: 收集主机信息 POST 出去]
    B --> D[阶段一: 向 authorized_keys 追加 svc-telemetry 公钥]
    C --> E[阶段二: 反向 SSH 隧道连攻击者服务器]
    D --> E
    E --> F[阶段三: LaunchAgent/cron/计划任务 持久化]
    F --> G[攻击者经隧道登录本地 sshd 拿 shell]
    E -.macOS 特有 bug.-> H[systemsetup 权限判断错误<br>SSH 多数情况下没被真正开启]

2.3 一个救了所有人的 bug

最有意思的技术细节来了。macOS 上恶意代码想开启远程登录(SSH 服务),逻辑是:先检查当前状态,如果输出 Off 就执行 sudo -n systemsetup -setremotelogin on。

但它没料到一件事:普通用户执行 systemsetup -getremotelogin 会打印一条"需要管理员权限"的错误并以状态码 0 退出 ,而不是返回 Off。脚本一看输出不匹配 Off,直接跳过开启步骤。结果就是:在绝大多数没开过远程登录的 Mac 上,反向隧道虽然建立了,但隧道那头捅到的是本机一个关闭的 22 端口------攻击者进不来。

写恶意软件的人把"我没权限查看 SSH 是否关闭"理解成了"SSH 已经开着"。一个 if 判断的疏忽,砍掉了整条访问链的最后一环。当然,密钥照样植入、持久化照样落地、主机信息照样外泄,所以不能因此说没风险。

3. 环境准备:判断自己是否在影响范围内

先确认三件事:

  1. 你用的是 Cursor 编辑器(不是 VS Code 官方)------这次只影响 Cursor Marketplace 分发的版本
  2. 装过 Claude Code 扩展(扩展 ID:anthropic.claude-code)
  3. 版本号是 2.1.312 或 2.1.313,时间在 2026-10-29 前后

查看已装扩展目录:

复制代码
# macOS / Linux
ls ~/.cursor/extensions/ | grep claude-code

# Windows (PowerShell)
Get-ChildItem "$env:USERPROFILE\.cursor\extensions" -Filter "*claude-code*"

如果列出来的目录是 anthropic.claude-code-2.1.313-darwin-arm64 这种带问题版本号的,继续往下走。

4. 实战实现:一键排查脚本

下面这个脚本覆盖了 Phorion 公开的全部主机侧 IOC,macOS 和 Linux 都能跑,Windows 用户看脚本后的手工清单:

复制代码
#!/usr/bin/env bash
# claude-code-backdoor-check.sh ------ Cursor 市场 Claude Code 投毒自查
set -u
hit=0
check() {  # $1=描述 $2=路径
  if [ -e "$2" ]; then
    echo "[!!] 命中: $1 -> $2"
    hit=1
  fi
}

# 1. 问题版本扩展目录
for d in ~/.cursor/extensions/anthropic.claude-code-2.1.31{2,3}*; do
  [ -e "$d" ] && { echo "[!!] 命中: 恶意版本扩展存在 -> $d"; hit=1; }
done

# 2. authorized_keys 里的攻击者公钥
if grep -q "svc-telemetry" ~/.ssh/authorized_keys 2>/dev/null; then
  echo "[!!] 命中: authorized_keys 含 svc-telemetry 公钥"
  hit=1
fi

# 3. 持久化文件
check "macOS/Linux 持久化脚本" ~/.config/.smt
check "重建的隧道私钥"        ~/.config/.smtk

# 4. macOS LaunchAgent 伪装
check "伪装系统服务的 LaunchAgent" ~/Library/LaunchAgents/com.apple.sysmond.plist

# 5. crontab 里的 @reboot 持久化
if crontab -l 2>/dev/null | grep -q "\.smt"; then
  echo "[!!] 命中: crontab 含 .smt 持久化条目"; hit=1
fi

# 6. 临时目录隧道私钥 (.stk_ 前缀)
found=$(ls "${TMPDIR:-/tmp}"/.stk_* /tmp/.stk_* 2>/dev/null)
[ -n "$found" ] && { echo "[!!] 命中: 隧道私钥残留 -> $found"; hit=1; }

# 7. macOS: 远程登录是否被意外开启
if command -v systemsetup >/dev/null 2>&1; then
  sudo -n systemsetup -getremotelogin 2>/dev/null | grep -q "On" && \
    echo "[警告] 远程登录处于开启状态,请确认是否本人操作"
fi

[ $hit -eq 0 ] && echo "[OK] 未发现已知 IOC,环境干净"
exit $hit

Windows 手工排查清单:

  • Get-ScheduledTask -TaskName "SysMon" 是否存在名为 SysMon 的计划任务
  • %USERPROFILE%\.config\smt.cmd 和 %USERPROFILE%\.config\smtk 是否存在
  • type %USERPROFILE%\.ssh\authorized_keys | findstr svc-telemetry

命中之后怎么清理

  1. 删除扩展:Cursor 里卸载 Claude Code,删掉 ~/.cursor/extensions/ 下对应版本目录,重装官方市场的最新版
  2. 从 ~/.ssh/authorized_keys 删掉 svc-telemetry 那行公钥
  3. 删除 ~/.config/.smt、~/.config/.smtk、${TMPDIR}/.stk_*、LaunchAgent 那个 plist(删完 launchctl unload 一下)
    | 4. 轮换凭证 :重点轮换环境变量名匹配 KEY|TOKEN|SECRET|PASS|AWS|GCP 模式的所有凭证------恶意代码的第一阶段就是按这个正则筛凭证的。git 保存的凭证、云平台 AK/SK、CI token 一个都别留 |
  4. 查 SSH 登录日志:如果隧道真的被登录过,日志里的来源会显示为本机回环地址(localhost 或 ::1),认证密钥是 svc-telemetry。有这种记录就是实锤被人进过,按入侵事件处理

5. 效果验证:官方渠道 vs 恶意版本对照

把这次事件里"官方分发"和"投毒版本"的关键差异整理成表:

对比项 官方 VS Code 市场 / npm Cursor 市场恶意版本
版本号 各版本正常分发 2.1.312 / 2.1.313(仅 Win/macOS)
extension.js 原始 bundle bundle 前被前置注入 IIFE
SHA-256 正常 ecb58c...bf15(Phorion 公布)
authorized_keys 不触碰 追加 svc-telemetry 公钥
网络行为 正常 API 调用 连 134.209.82[.]225:22 反向隧道
持久化 无 LaunchAgent / crontab / 计划任务
状态 不受影响证据 已全部下架,C2 服务器已被云服务商下线

再补一句时效性说明:截至 10月31日,Cursor 已重建整个市场、轮换了密钥,攻击者服务器已下线。但这只意味着"新装机不会再中招",已经中招的机器上的持久化文件不会自己消失。

6. 踩坑记录:这次事件暴露的三层失守

第一层,市场审核形同虚设。 一个被篡改的官方扩展能顺利上架并分发11个小时,说明市场的发布验证没有做 bundle 级别的签名校验。你信任的是"Claude Code 官方扩展",但真正给你代码的是中间的市场管道。

第二层,检测规则抓不住它。 写 authorized_keys 用的是 Node 内置 fs.appendFileSync,绕开了所有盯着 shell 命令的进程监控。教训很直接:对 ~/.ssh/ 这种高危路径,靠"监控可疑命令"不如直接做文件完整性监控------甚至可以学 Phorion 的思路,用文件访问控制把 ~/.ssh/ 锁死,只允许 ssh 进程碰它。

第三层,用户对开发工具的信任被滥用。 我们给 CI 加密钥要审批,给服务器开端口要走流程,但给编辑器装扩展点一下就完事。扩展拿到的权限和你的开发机权限完全等价,这件事值得每个团队写进安全基线。

顺带一提,这次 macOS 上那个救场的 bug 也说明了另一件事:攻击者的代码也会有低级失误。做应急响应时别假设恶意代码"应该都能跑通",实际验证每个阶段到底落地没有,才能准确评估暴露面------这台机器是"信息泄露+残留文件"还是"被人登录过",处置等级完全不同。

7. 总结与展望

这次 Cursor 市场投毒事件给了一个完整的教科书案例:供应链投毒 → 高权限执行 → 持久化 → 反向隧道,全链路在一个 activate() 里完成。对个人开发者,最小行动清单是:跑一遍第4节的脚本、检查扩展版本号、轮换敏感环境变量;对团队,认真考虑给开发机的 ~/.ssh/ 上文件访问控制,并在安全基线里写明"扩展市场 ≠ 可信源"。

有一个问题想抛给你:你现在的项目里,有多少凭证是以环境变量形式躺在开发机上的?如果明天你的某个常用扩展被投毒,你的轮换成本是十分钟还是一周?评论区聊聊你的防线是怎么搭的------尤其是多人团队怎么管 ~/.ssh/ 权限,我很好奇有没有比"全员上文件完整性监控"更轻量的实践。

相关推荐
叼烟扛炮1 小时前
Linux 学习笔记(四十五):Web 安全基石——Cookie、Session 与 HTTPS 原理解析
linux·前端·网络·笔记·学习·tcp/ip·安全
~央千澈~1 小时前
优雅草新产品2026 年 10 月 31 日公测完毕v1.0.0 优雅草人机盾正式运营上线
安全·网络安全·安全防御
是真的小外套1 小时前
网络安全实战第10期:Nmap主机发现之一键扫清整个网段
网络·安全·web安全
垚垚学技术_聚焦云原生1 小时前
Ansible Vault 安全实践:敏感密码、密钥加密存储方案
安全·elasticsearch·ansible
鬼手点金2 小时前
提示注入:上下文安全的核心威胁
人工智能·安全·microsoft·机器学习·缓存·prompt
山川绿水2 小时前
DeepSeek-DSH安装报错[deploy] 命令失败:npx -y pnpm install --prefer-offline
人工智能·网络安全
ScilogyHunter3 小时前
Hercules系列安全MCU功能安全原理详解
java·单片机·安全·hercules
Data-Miner3 小时前
不本地部署,大模型怎么安全用?
大数据·人工智能·安全
李纲明3 小时前
WordPress 媒体库上传失败或一直转圈:先核 PHP 上传限制与目录权限,再查安全插件与对象存储
运维·开发语言·安全·php·wordpress·媒体库·devdiy