SSH 后门不只在扩展里:Cursor 假扩展的 5 步排查法
2026 年 10 月 29 日,Cursor 的 VS Code 扩展市场短暂上架了并非 Anthropic 开发的 Anthropic.claude-code 恶意版本 2.1.312 和 2.1.313。攻击者试图植入 SSH 后门。现在值得看,不只是因为又出现了一个“假扩展”,而是它暴露出一个容易被忽略的边界:卸载扩展不等于清除后门,排查范围也不能只框定在扩展上架的几小时内。
据 Cursor 安全公告,恶意版本在太平洋时间当天约凌晨 2:27 至下午 1:35 可用。按这两个时间点复算,窗口约为 11 小时 8 分钟,而不是整个自然日。
扩展被下架,不等于机器已经干净
Cursor 公告描述的恶意行为并不只是收集数据。扩展会尝试读取主机名、用户名、操作系统、架构、主目录路径、环境变量名称、工作目录、Git 邮箱和公网 IP,并尝试把攻击者控制的 SSH 公钥加入 authorized_keys。
随后,它还会尝试启用本地 SSH 服务、建立反向 SSH 隧道,并在 macOS 上使用 LaunchAgent、在 Windows 上使用计划任务维持连接。后台脚本约每 60 秒重试一次连接。
Cursor 公告列了两个限制:其一,在大多数没有管理员权限的主机上,启用 SSH 服务这一步会失败,反向隧道因此可能无法正常工作;其二,恶意代码本身存在错误。但 Expel 记录的实际案例里,隧道在用户不是管理员的情况下照样连了出去 —— 公告说的是”可能失败”,不是”一定失败”。所以这不等于机器没有受害:公钥和持久化机制的安装尝试仍可能发生,主机信息也可能已经上报。
Expel 的事件响应记录进一步给出了边界。该机构调查了四起相关事件,每起涉及一台 Mac;三起发生在 Cursor 所述窗口内,另一起在窗口结束后约 8 小时才出现首次恶意活动。这里需要区分来源口径:四起事件与时间差来自 Expel 的客户侧调查,不是 Cursor 公布的官方用户总数,也不能据此推断整个事件的感染率。
但按官方暴露窗口推算,如果响应人员只搜索那 11 个多小时,理论上会漏掉窗口关闭后才发现活动的机器。这是我的边界推导,不是官方结论。
11 小时的窗口,为什么不够覆盖处置周期
| 排查方法 | 能发现什么 | 容易漏掉什么 | 本文建议 |
|---|---|---|---|
| 只按扩展上架时间搜索 | 上架期间安装或启动过的机器 | 窗口关闭后的首次活动、持续连接 | 把起止时间各向外扩一段调查 |
| 只看扩展列表 | 仍在安装的恶意版本 | 已卸载但后门仍驻留 | 同时检查 SSH、启动项和计划任务 |
只检查 authorized_keys |
被写入的 SSH 公钥 | 持久化脚本、反向隧道、进程 | 按“公钥—任务—进程—网络”四层查 |
| 只卸载扩展 | 移除扩展包 | 已经落盘的脚本和配置 | 卸载后独立执行主机侧清理 |
| 只依赖厂商公告 | 已知版本和文件线索 | 改名、变体或本机残留 | 同时采用版本、行为和持久化三类信号 |
按官方时间点计算,2:27 到 13:35 的间隔是 11 小时 8 分钟。Expel 所述四起事件中,一起首次活动发生在 Cursor 所述窗口结束后约 8 小时。把官方窗口和 Expel 案例里的这段时间相加,可以得到约 19 小时的调查跨度 —— 注意这个数跨了官方公告和第三方处置记录两个来源,不是官方口径:
官方暴露窗口:11 小时 8 分钟
窗口结束后的新增活动:约 8 小时
官方窗口 + Expel 案例新增活动:约 19 小时(跨两个来源,不是官方口径)
这不是安全团队必须采用的固定隔离时长,而是提醒读者:市场下架只是停止分发,不等于远端活动和本机持久化同时停止。
5 步排查:先找证据,再做清理
第一步:确认版本,不凭扩展名称判断
先在 Cursor 的扩展界面和安装记录中确认是否存在 Anthropic.claude-code 的 2.1.312 或 2.1.313。Cursor 明确表示,这两个版本不是 Anthropic 开发的。
可按操作系统收集线索。macOS 可查看 Cursor 扩展目录和 shell 历史记录;Windows 可在 PowerShell 中检查扩展安装目录、任务和 SSH 配置:
# 查看 Cursor 扩展目录中是否存在涉事版本
Get-ChildItem "$env:USERPROFILE.cursorextensions" `
-Recurse -ErrorAction SilentlyContinue |
Where-Object { $_.FullName -match "claude-code|2.1.31[23]" }
# 列出计划任务,寻找异常名称
Get-ScheduledTask |
Where-Object { $_.TaskName -match "claude|telemetry|ssh|svc" } |
Select-Object TaskName, TaskPath, State
# 查找包含 authorized_keys 的脚本或配置引用
Select-String `
-Path "$env:USERPROFILE.cursorextensions*" `
-Pattern "authorized_keys|LaunchAgent|reverse.*ssh" `
-ErrorAction SilentlyContinue
这些命令是防御性排查建议,输出命中不能单独证明入侵;没命中也不能排除已经卸载后的残留。
第二步:检查 SSH 公钥与本地服务
macOS 和 Linux 用户可检查自己的 SSH 授权文件,并列出 SSH 相关进程:
# 检查 SSH 授权公钥;未知公钥不能直接删除,应先核对来源
nl -ba ~/.ssh/authorized_keys
# 查看 SSH 与隧道相关进程
ps aux | grep -E '[s]sh|[t]elemetry'
# 检查用户级 LaunchAgent 目录
find ~/Library/LaunchAgents -maxdepth 1 -type f -print
Windows 用户则应结合 Get-ScheduledTask、任务执行程序和 SSH 配置目录交叉检查。发现陌生公钥时,先保存文件内容、路径和时间信息用于取证,再删除;不要因为文件名陌生就直接清空整个 authorized_keys,否则可能破坏正常部署。
第三步:追持久化,而不是只卸载扩展
Cursor 公告明确指出,持久化分别落在 macOS 的 LaunchAgent 和 Windows 的计划任务上。macOS 可用 launchctl list 辅助定位,Windows 可用 Get-ScheduledTask 查看任务,再核对任务动作指向的文件是否与扩展、SSH 隧道或遥测脚本有关。
关键是做因果关联:一个名字可疑但与事件无关的任务不应被贸然判定;一个名称普通、却写入攻击者公钥或执行隐藏脚本的任务,也不能因为名字正常而放过。
第四步:查连接痕迹,但不要只依赖端口扫描
反向 SSH 隧道在建立成功时可能留下连接记录。macOS 可检查 SSH 配置和已知主机记录,Windows 可查看活动 TCP 连接及对应进程。Linux 用户还可以查看 ss -tpn 输出,把远端地址与进程对应起来。
不过,端口扫描只能回答“此刻是否还能看到连接”,不能回答“过去是否连接过”。连接已经中断或服务器已下线时,主机上仍可能残留授权公钥与启动项。因此,网络检查必须与文件和持久化检查配套。
第五步:保全记录后再清理和轮换
如果确认安装过涉事版本,应先记录扩展版本、相关文件路径、SSH 公钥、计划任务、启动项和可疑进程,再执行删除。清理后还要检查远程登录凭据是否需要轮换,而不仅是删除扩展。
Yahoo 转述的 Fast Company 报道也提到,Cursor 已与服务器托管方合作让攻击者服务器下线,并称没有发现其他扩展被篡改;Anthropic 则表示事件只影响 Cursor 用户,与其自身系统无关。这些属于报道引述的各方口径,不应扩张成“所有 AI 编程工具都已失陷”。
假扩展市场:名字像真的,风险却来自权限
这次事件最值得普通用户吸取的教训,不是“Claude Code 四个字不能信”,而是 AI 编程扩展天然拥有较高权限。它能读写项目、调用开发工具,也可能接触 Git 配置和环境变量。安装一个看似提供 Claude Code 能力的扩展,等于把一整套自动化能力接入本机。
在 Cursor 或 VS Code 市场里,普通用户可以先做三个低门槛检查:看发布者身份与官方渠道是否一致,看安装量和版本反馈是否突然异常,以及安装后是否出现自己从未配置过的 SSH、任务或后台脚本。扩展图标相似、名称几乎相同,并不构成安全证明。
对团队而言,还应把“是否安装过涉事版本”与“主机是否仍可能驻留”分成两个问题处理。前者通常能通过安装清单回答,后者则必须结合 SSH、持久化、进程和网络证据。企业还可以参考 Expel 文档中的检测与响应方法,把一次事件转成可重复执行的排查流程。
这次公开信息最终给出了哪些受害者数量、是否能证明没有数据外传,官方材料之外仍有严格边界。安全响应最重要的目标不是把未知压缩成一个结论,而是让每个可疑版本、文件和任务都能被单独验证。
参考来源
评论区
登录后可评论。