AI图鉴

AI图鉴首页 › AI 资讯 › 一个版本号失守:Claude Code 2.1.313 扩展后门事件,开发者机器

一个版本号失守:Claude Code 2.1.313 扩展后门事件,开发者机器如何变成别人的 SSH 入口

来源:掘金 · 发布时间:10-31 · 由 AI图鉴每小时自动聚合

八百六十三个点赞、五百一十三条评论,10 月 30 日 Hacker News 头条不属于任何新模型,而属于一个版本号:Claude Code for VS Code 的 2.1.313。macOS

八百六十三个点赞、五百一十三条评论,10 月 30 日 Hacker News 头条不属于任何新模型,而属于一个版本号:Claude Code for VS Code 的 2.1.313。macOS 安全厂商 Phorion 当天发布通告,确认这个挂在 Open VSX 市场上、页面里写着 Anthropic 官方字样的扩展包被注入了持久化 SSH 后门,攻击链覆盖 macOS、Linux、Windows 三个平台。Cursor 方面给出的统计是受影响用户至多五千人。数字本身不算惊人,刺眼的是渠道:投毒者没有碰任何野生下载站,而是把后门直接塞进了开发者最不设防的地方,也就是编辑器自带的扩展市场。对每天让 AI 编程助手读写自己代码的人来说,这件事值得逐帧看清楚。

事件回放:48 小时里发生了什么

10 月 29 日,Cursor 在自己的扩展市场里发现了被篡改的 Claude Code 扩展,版本号 2.1.313。这个扩展在 Open VSX 上的列表页显示发布者为 Anthropic,实际提交账号却是一个名为 igorkofman 的账户。Open VSX 是 Cursor、Windsurf 等 VS Code 系编辑器共用的扩展注册中心,开发者在这些编辑器里搜索安装扩展,命中的就是它。

Cursor 的处置动作很快:下架扩展、重建整个市场、协助把攻击者的服务器下线。Anthropic 随后也把 NPM 和 VS Code 官方市场里 2.1.313 的对应版本一并撤掉。处置过程里有个细节值得记住:恶意包的部分安装步骤因为需要管理员权限而失败,但它收集信息和部署持久化的动作在普通用户权限下就完成了,权限不足并没有拦住核心破坏面。10 月 30 日,Phorion 公布完整逆向报告,把后门的工作原理、持久化手法和入侵指示器全部摊开,同一天这个话题冲上 HN 头条,评论区里最多的感慨是:原来编辑器扩展一直是个没人看的权限黑洞。

需要明确的一点是,这是一起市场渠道的包替换事件,不是 Anthropic 官方构建管线被攻破。但站在受害机器的视角,这个区别毫无意义:扩展以 IDE 和当前用户的权限运行,加载即执行,不需要任何额外交互。

后门藏在哪里:扩展包的第一行

被篡改的 extension.js 有一个非常朴素的特点:恶意代码不是混淆在几万行压缩代码中间,而是作为一个立即执行函数直接拼在整个压缩包的最前面。后面的部分是完全正常的扩展代码,Claude Code 的字符串、标准的 activate 和 deactivate 导出、界面逻辑一应俱全。

这个设计意味着两件事。第一,Node 加载这个文件时,前置的恶意函数立刻执行,根本等不到扩展的 activate 回调被调用,用户不点任何按钮、不开任何面板, payload 照样跑。第二,它只引用了 child_process、fs、os、path、http、crypto 这几个 Node 标准模块,没有任何外部依赖,也就没有可疑的网络安装行为可供静态扫描发现。

对审计来说这是个提醒:扩展安全扫描如果只查依赖树和安装脚本,对这种前置注入是盲的。文件哈希才是硬证据,Phorion 给出的带毒包 SHA-256 是 ecb58cb2 开头的一串,任何环境里的 2.1.313 都可以对着它验。更实际的一点在于团队管理:大多数公司能说出生产服务器上跑了哪些依赖版本,却说不出五十个开发者的编辑器里装着哪些扩展。这次事件之后,扩展清单应该和依赖清单一样进入资产台账,否则下一次通告来的时候,你连排查范围都画不出来。

四段攻击链:从 authorized_keys 到反向隧道

整个 payload 的目标是长期交互式访问,逻辑分成四段,每一段都很克制。

第一段是铺 SSH 入口。脚本确保用户家目录下的 .ssh 存在,然后把一个攻击者控制的 Ed25519 公钥追加进 authorized_keys,目录权限设为 0700,文件权限设为 0600。公钥的注释字符串是 svc-telemetry,伪装成遥测服务。有意思的是它判重时查的是注释字符串而不是密钥指纹,所以取证时不能只按注释搜,要按指纹对。

第二段是确保 SSH 服务在跑。Linux 上尝试用 systemctl 拉起 sshd,失败再退到 service 和 init.d。macOS 上先查 Remote Login 状态,报 Off 就用 sudo -n 去开。Windows 上尝试用 PowerShell 安装并启动 OpenSSH Server。这一段没有任何提权漏洞,非交互的 sudo -n 在大多数机器上直接失败。

第三段是反向隧道,也是整条链的核心,逻辑大致如下:

// 隧道私钥落盘:文件名取主机名与家目录拼接值 MD5 的前 10 位

var kf = path.join(TMP, ".stk_" + crypto.createHash("md5")

.update(String(os.hostname()) + HOME).digest("hex").slice(0, 10));

// 反向端口转发:让攻击者服务器动态分配端口,回连受害机 22 端口

var RF = "'*:0:localhost:22'";

// -N 只维持转发不执行命令,BatchMode 保证静默,每 60 秒重试

// 优先用 autossh,没有就用系统 ssh,pgrep 防重复起隧道

机器主动向外连到 134.209.82.225 的 22 端口,用一个注释为 svc-telemetry-tun 的内置私钥认证。因为连接方向是出站的,防火墙通常不会拦。攻击者想进来时,从自己服务器上动态分配的端口走既有隧道回到受害机的 22 端口,再用第一段种下的公钥登录。由于隧道进程是脱离父进程独立运行的,关掉 IDE 它照样活着。

第四段是侦察信标。脚本收集主机名、用户名、系统平台、家目录、全局 Git 邮箱,用 ifconfig.me 查公网 IP,再收集至多 40 个匹配 KEY、TOKEN、SECRET、PASS、AWS、GCP 的环境变量的名字,注意只是名字不是值。这份清单通过明文 HTTP POST 到攻击者服务器的 8099 端口,让运营者快速判断哪台机器上有云凭证值得优先动手。

救场的 bug:权限检查写反了之后

这份恶意代码的质量并不高明,两个实现错误客观上减了灾。

macOS 上的错误最戏剧化。脚本用普通权限跑 systemsetup -getremotelogin 想知道 SSH 是否开着,但这个命令在标准用户下根本不返回状态,而是打印一行"你需要管理员权限"然后以退出码 0 正常结束。脚本拿到这段错误文本,用正则去匹配 Off,匹配不上,于是得出结论:SSH 已经开了,跳过开启步骤。它把"我没权限查"当成了"已经是开着的"。结果就是,在一台本来没开 Remote Login 的 Mac 上,公钥和持久化都种下了,唯独 22 端口没人听,攻击者连回来只能撞一堵墙。当然这不是防线,机器上只要本来开着 SSH,或者之后有人打开,后门立刻完整生效。

Windows 上更离谱:负责执行命令的辅助函数把 shell 路径写死成了 /bin/sh,这个路径在标准 Windows 上不存在,整条服务安装链直接空转。Linux 侧也有一个 bug, crontab 判重逻辑写错了,重复运行可能把用户已有的 cron 任务整个清掉,属于损人不利己的破坏。

这几个 bug 的教训不在攻击者粗心,而在于防御方不能把运气当控制措施。入侵是否成功,这次取决于受害机器 Remote Login 的开关状态和攻击者一个正则表达式的写法,这两样都不在任何人的安全策略里。一个健康的防护体系应该假设对方代码没有 bug,假设隧道一定建得起来,然后在这个前提下问:我的机器上有没有进程该写 authorized_keys 却不该写?有没有 LaunchAgent 在执行隐藏目录里的脚本?这两个问题,Phorion 报告里给出的检测思路都能回答,普通团队用 osquery 之类的开源工具也能搭出基础版本。下一次投毒者把正则写对,整批 Mac 就是另一个故事。

为什么卸载扩展清不干净

Cursor 在事件后给出的清理建议里有一条很容易被忽略:只卸载扩展是不够的。后门在第一次运行时就把自己复制到了扩展目录之外,扩展没了,持久化机制还在。三平台的残留物对比如下:

还有一条容易漏的:SSH 日志里通过隧道进来的成功登录,来源地址会显示成 localhost。如果机器上过这条链,要查的不只是隧道有没有建起来,还有攻击者有没有真的登进来过,登进来过就意味着那台机器上所有该用户可触达的凭证都要轮换。

十分钟自查脚本

不管用不用 Claude Code,只要用过 Cursor 或 Windsurf 装过扩展,下面这段脚本值得跑一遍,覆盖上面所有主机侧痕迹:

#!/bin/bash

# Claude Code 2.1.313 后门自查:只读检查,不改动任何文件

echo "[1] authorized_keys 可疑公钥"

grep -n "svc-telemetry" ~/.ssh/authorized_keys 2>/dev/null || echo " 干净"

echo "[2] 隧道私钥临时文件"

ls -la /tmp/.stk_* "$TMPDIR"/.stk_* 2>/dev/null || echo " 干净"

echo "[3] 持久化脚本"

ls -la ~/.config/.smt ~/.config/.smtk ~/.config/smt.cmd 2>/dev/null || echo " 干净"

echo "[4] macOS LaunchAgent"

ls -la ~/Library/LaunchAgents/com.apple.sysmond.plist 2>/dev/null || echo " 干净"

echo "[5] 活着的隧道进程"

ps aux | grep -E "autossh|ssh .*-R" | grep -v grep || echo " 干净"

echo "[6] 外联痕迹"

lsof -i -n 2>/dev/null | grep "134.209.82.225" || echo " 干净"

echo "[7] 已安装的扩展版本"

ls -d ~/.cursor/extensions/anthropic.claude-code-2.1.313* ~/.vscode/extensions/anthropic.claude-code-2.1.313* 2>/dev/null || echo " 未装 2.1.313"

任何一项有输出,就按上一节的清单走完整清理,然后从一台确定干净的机器上轮换这台机器碰过的所有凭证。顺序很重要:在被污染的机器上改密码等于把新密码也交出去。

扩展市场的信任账该重算了

把视角拉远,这起事件不是孤例。去年 11 月就有攻击者用恶意的 Solidity 扩展在 Open VSX 上投毒偷开发者数据,Forever Security 上个月还演示过把一份带指令的文件丢进 Downloads 目录,就能诱导在那里打开的 AI 编程助手自己去装包、改配置。甚至连模型服务本身都会出卖你:Cloudflare 上个月披露,它托管的 GLM 模型因为 SGLang 的错误处理 bug 和配置错配,会把一个客户的长提示词缓存内容吐给下一个请求。攻击面正在从依赖库转向编辑器本身,理由很简单:扩展有用户的全部权限,审查强度却远低于 npm。

对比之下,几个环节的落差很明显。包管理器社区这几年陆续上了构建溯源和签名,而多数扩展市场仍停留在账号加扫描的阶段,发布者身份核验形同虚设,一个陌生账号能顶着官方名义出现在列表页。编辑器侧也缺一层默认隔离,扩展进程能直接读写 authorized_keys 这件事本身,在移动端操作系统里早就是不可想象的。

对普通开发者,可行的动作是把扩展也纳入资产管理:装了什么、什么版本、哈希对不对,像锁依赖一样锁住。对团队,把 Open VSX 的扩展安装收敛到白名单,配合终端侧的文件遥测盯住 SSH 配置目录,是性价比最高的两步。扩展市场这套信任体系是 Web2 时代留给 AI 编程时代的遗产,这次只是第一次有人用力踹了一脚,门轴已经响了。

本文由 AI图鉴自动抓取并翻译,版权归原作者所有;如需查看原文请点下方链接。

相关 AI 工具

相关免费羊毛

同源资讯

阅读原文(juejin.cn)

标题、摘要与正文均来自该信源的公开页面,版权归原作者所有;本站自动聚合与翻译,仅作出处跳转。

← 返回 AI 资讯列表AI工具图鉴首页

返回 AI图鉴首页 · 提交工具 · 商务合作 · 关于本站 · 603 款 AI 工具分类导航 · 每日 AI 热门项目与动态