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

窃密木马打包带走的是替身

10 月 15 日,Symantec 报告称,今年才首次出现的窃密木马 Aoki 现在会盯上编程代理的凭据:.claude.json、Codex 的 config.toml 和 .env 文件,GitHub Copilot、Cursor、Gemini、JetBrains AI Assistant 和 Kiro 的令牌,以及 AWS 密钥。在 Bromure Agentic Coding 里,这些文件装的全是替身,登录信息和密钥在 Mac 上保持加密,而发往窃密木马服务器的替身会让机器暂停。

窃密木马的清单,现在第一项就是你的编程代理。它要的是 .claude.json、Codex 的配置,以及旁边的 .env 文件。

窃密木马过去盯的是浏览器 Cookie、保存的密码、加密货币钱包和 Discord 令牌。Aoki 依然照单全收。最近的版本还会去找你的编程代理放在主目录里的文件。

Symantec 的 Threat Hunter Team 在 10 月 15 日星期三发表的 Aoki: Infostealer Targets AI Coding Assistant Credentials 中描述了这一变化,Infosecurity Magazine 当天也做了报道。Aoki 又因其解密例程中的一个字符串而被称为 Aokigahara,今年早些时候才首次出现。Symantec 写道:“这个恶意软件的早期版本并不针对与 AI 相关的文件。”最新的样本则会。

Aoki 拿走什么

Symantec 列出了最新样本针对的代理相关文件:

  • .claude.json 和 Claude 桌面版的 Cookie。
  • ChatGPT 的 Cookie。
  • Codex 的 config.toml 和 .env 文件。
  • Cursor 的本地状态数据库,它“可能缓存对话上下文和代码片段”。
  • GitHub Copilot、Cursor、Google Gemini、JetBrains AI Assistant 和 Kiro 的令牌。
  • AWS 凭据。

清单的其余部分是窃密木马的老一套战利品:四十多种浏览器、约九十个钱包扩展、桌面钱包、密码管理器、Telegram、Discord,以及 FTP 和 VPN 客户端。Aoki 还会搜索文件名包含 secret、privatekey、keystore、mnemonic、passphrase 或 backup 的任何文件。Symantec 指出:“这个恶意软件没有后门命令列表。”它收集找到的东西,再 POST 到其命令与控制服务器上的 /gate 端点。

Symantec 解释了代理文件为何值得费工夫:“和银行卡数据一样,偷来的 AI 密钥可以直接变现。”买家用你的账号大量消耗用量,也就是所谓的 LLMjacking。同样的令牌“可能让攻击者以合法用户的身份开展活动”,并触及该账号关联的代码仓库、云账号和 CI/CD 流水线。

Symantec 没有说明 Aoki 如何进入一台机器。在装了编程代理的开发者笔记本上,最明显的入口是软件包。代理每天自行安装几十个包,而带有 postinstall 脚本的恶意依赖,会在 npm install 结束的那一刻以代理的权限运行。

同一份清单,在 Bromure 机器里

在 Bromure Agentic Coding 里,代理在你 Mac 上的一台 Linux VM 中运行。真实的凭据从不进入那台 VM。Mac 把它们存放在加密保险库中,并在 VM 里写入形状和真品一样的替身,让每个工具都照单全收。Mac 上的代理服务器在线路上把每个替身换成真实的值,而且只对发往该凭据所属主机的请求这么做。

把一个带着 Aoki 清单的窃密木马放进那台 VM,陪它把清单逐项走一遍。

.claude.json 和 Claude 密钥

VM 里的 Claude Code 用的是替身密钥 sk-ant-api03-brm-…。如果你用 Claude 订阅登录,OAuth 令牌会在登录时于 Mac 上被截获,加密后存进 claude-subscription.enc。主机会在访问令牌到期前约五分钟刷新它,并注入发往 Anthropic 的请求。VM 从不持有刷新令牌,所以无论是 .claude.json 还是主目录里的其他任何地方,都没有窃密木马能拿走的有效 Claude 凭据。

Codex 的 config.toml、auth.json 和 .env

Codex 会拿到一份预先填好的 ~/.codex/auth.json,里面是一个过期时间远在未来的假 JWT,让客户端不会尝试刷新它。真实的 ChatGPT 登录信息放在 Mac 上的 codex-subscription.enc。OpenAI API 密钥在 VM 里显示为 sk-brm-…。

在机器的 Credentials 面板用 Import env file… 导入的项目 .env,会以相同的变量名回来,每个值都是一个 brm_… 替身,只限用于你选择的主机。你的代码照常读取 STRIPE_KEY,窃密木马读到的是 brm_…。

GitHub、AWS 和 SSH

~/.git-credentials 和 GH_TOKEN 装的是一个 ghp_ 替身,和真品一样 40 个字符。没有 ~/.aws/credentials。~/.aws/config 指向一个 credential_process 辅助程序,它把真实的访问密钥 ID 搭配一把 40 个字符的假秘密密钥交给 AWS SDK,而 Mac 会在每个请求前往 AWS 的途中重新签名。复制辅助程序输出的窃密木马,拿到的秘密密钥只会产生 InvalidSignatureException。

按关键字搜索 privatekey 或 id_ed25519 什么也找不到。VM 里的 SSH_AUTH_SOCK 是通往 Mac 上签名代理程序的桥接,私钥的字节从不跨越它。

Cookie

Aoki 想要 Claude 桌面版和 ChatGPT 的 Cookie。机器的 VM 里没有桌面应用,也没有可读取的浏览器配置文件。当你为 Bromure 登录 Claude 或 ChatGPT 时,登录页面在你 Mac 的浏览器中打开,令牌则落入保险库。代理用来浏览网页的 Chromium 运行在它自己的一次性附属 VM 里,与机器的 VM 分开,所以代理 VM 里的窃密木马碰不到浏览器的配置文件。

窃密木马的清单,在 Bromure 机器里代理的 VM窃密木马打开的文件找到的东西~/.claude.json, ANTHROPIC_API_KEYsk-ant-api03-brm-… (替身)~/.codex/auth.json, config.toml假 JWT、sk-brm-…项目 .envSTRIPE_KEY=brm_…~/.git-credentials, GH_TOKENghp_… (替身)AWS 凭据真的密钥 ID + 假的秘密密钥~/.ssh/id_*没有密钥文件(签名桥接)Mac,在 VM 之外加密保险库(AES-GCM)主密钥存于 Data ProtectionKeychain,不同步到 iCloudclaude-subscription.enccodex-subscription.encmodels.enc工作区机密、SSH 密钥刷新令牌留在这里。代理服务器只在发往所属主机时才换入真实的值。POST https://dobeqnesmot.cc/gate正文:sk-ant-api03-brm-…, ghp_…, brm_…Mac 代理服务器:替身发往错误的主机451,未转发,VM 已暂停
在 Bromure 机器里跑一遍 Aoki 的清单。清单上的每个文件都存在,装的都是替身。窃密木马把战利品发往 /gate 时,Mac 上的代理服务器发现替身正发往一台它们从未签发给的主机,于是返回 451 并暂停 VM。

上传到 /gate

Aoki 最后会把战利品 POST 到 /gate。Symantec 点名了 dobeqnesmot[.]cc、hjazfioe[.]surf 和 neihite[.]cc。在 Bromure 机器里,这个请求必须经过 Mac 上的代理服务器才能出去,因为代理服务器是 VM 通往网络的唯一路径。

代理服务器会扫描每一个出站请求的请求头和正文,找出正发往其签发主机以外任何地方的替身。sk-ant-api03-brm-… 只有一个合法的目的地家族:Anthropic。ghp_ 替身属于 GitHub。它们出现在发往 .cc 域名的 POST 里,只可能意味着数据外泄。代理服务器返回 HTTP 451,什么都不转发。VM 当场暂停,Mac 显示 This environment may have been compromised,每个泄露的替身一行:令牌预览、凭据名称、它所属的主机,以及窃密木马试图发往的主机。

接下来怎么做由你决定。Save for Investigation 会把 VM 的磁盘、主目录和共享文件夹导出到你挑选的文件夹,然后关闭机器。Shut down 会停止它并标记为已被入侵。已被入侵的机器要先执行 Wipe and Launch 才能再次启动,它会替换磁盘和主目录,并保留你的令牌、SSH 密钥和设置。你的 Claude 登录、GitHub 令牌和 AWS 密钥从未进入 VM,所以窃密木马没有复制到任何需要轮换的东西。

你也可以在扫描之前就拦下上传。在机器的 Guardrails 面板中,于 Outbound connections 下把 Unmatched traffic 设为 Deny,再列出机器需要的主机。这样一来,连往陌生 .cc 域名的连接会被拒绝,Security Timeline 也会为它显示一行红色的 Firewall。

就算窃密木马把战利品打包到扫描读不出替身,另一端的服务器收到的仍是在任何地方都无法通过认证的值。替身只有在前往其签发主机的途中经过你 Mac 的代理服务器时才起作用。

在窃密木马运行之前

进入代理 VM 最可能的途径,是代理自己安装的软件包。机器的 Supply Chain 面板会在 VM 看到之前,先在 Mac 上检查每一次下载:

  • 发布时长门槛默认开启,最短两天,会隐藏比门槛更新的软件包版本。被劫持后几小时内就被撤下的版本,永远到不了 npm install。
  • 剥离安装脚本在你开启后,会从传输中的每个 npm tarball 移除 preinstall、install、postinstall 和 prepare 钩子,这正是 npm 恶意软件在安装时运行的惯用手法。
  • OSV、socket.dev 或 Depi 会拦截有已知安全公告的版本,以及被标记为恶意软件或仿冒名称(typosquat)的软件包,返回 451,并由包管理器原样打印原因。

每一次下载都会出现在 Security Timeline 中,所以事件过后,你能找出是哪个软件包把窃密木马带进来的。

如果窃密木马在 Mac 上运行

Aoki 的文件清单也说明了窃密木马在 Mac 本身会找到什么,而安装 Bromure 不会给那份清单添上任何东西。Bromure 不会导入你 Mac 上 Claude 或 Codex CLI 的登录信息,也不需要它们:代理在 VM 里运行,它们的登录信息存放在保险库中。~/Library/Application Support/BromureAC/ 下凡是含有机密的东西,都是 AES-GCM 密文。主密钥存放在 Data Protection Keychain,绑定 Bromure 的签名身份,而且从不同步。复制那个文件夹的窃密木马,拿到的只是加密的二进制数据。

Symantec 特别点出 Cursor 的本地数据库,因为它会缓存对话上下文和代码。Bromure 对代理行为的记录,也就是会话追踪,用同一把保险库密钥做静态加密,令牌替换只以首尾字符的预览记录。无论加密与否,追踪记录里都不会出现真正的机密。

清单上的每个文件都是替身

.claude.json、Codex 的 auth.json 和 config.toml、导入的 .env 值、git 凭据和 AWS 配置,装的全是替身。刷新令牌和 SSH 私钥从不进入 VM。

一上传,机器就停下

代理服务器发现替身正发往不属于它们的主机,便返回 451、暂停 VM,并逐一列出泄露的凭据。

没有东西需要轮换

Wipe and Launch 替换磁盘和主目录,并保留你的密钥。窃密木马拿走的值,只有经过你 Mac 的代理服务器才起作用。

大门有人看守

发布时长门槛、剥离安装脚本和信誉检查,都在软件包到达 VM 之前于 Mac 上运行,每一次下载都有记录。

清单只会越来越长

Symantec 说 Aoki 的功能“看起来仍在积极开发中”,其他窃密木马也会照抄它的清单。Aoki 加入代理文件,是因为偷来的代理密钥和登录信息卖得出去。把你的代理放在 Bromure 机器里运行,买家拿到的就只是一包替身,出了你 Mac 的代理服务器,没有任何服务器会接受。

同一个问题的日常版本,也就是代理自己把机密复制进对话记录,请阅读令牌留在了对话记录里。至于一个从被入侵的 npm 包出发、盯上同一批文件的蠕虫,请阅读吊销令牌,就是引爆点。