← 返回所有文章
發佈於 · 作者 Renaud Deraison

那次更新加了一把金鑰

10 月 29 日,Cursor 的擴充功能市集有十一個小時以 Anthropic 自己的發布者名稱,提供了一個被植入木馬的 Claude Code 擴充功能。它一載入就加入攻擊者的 SSH 金鑰、安裝 LaunchAgent,並試圖開啟反向通道,波及最多 5,000 名開發者的電腦。在 Bromure Agentic Coding 中,代理不是從編輯器市集來的;這類酬載會在一台沒人連得進去的 VM 裡執行,它的通道被對外防火牆拒絕,它的持久化在倒轉家目錄後就消失。

沒有人需要開啟對話,也沒有人需要核准任何工具呼叫。編輯器載入了擴充功能,66 行 JavaScript 就以開發者的身分執行,比 Claude Code 自己的程式碼還早。

10 月 29 日,太平洋時間大約凌晨 2:27 到下午 1:35 之間,Cursor 的擴充功能市集提供了一個被植入木馬的 Anthropic Claude Code 擴充功能版本。Cursor 的安全公告點名 anthropic.claude-code 的 2.1.312 與 2.1.313 版,這兩版以 Anthropic 的發布者身分發布,並表示 Anthropic 並未建置它們。BleepingComputer 報導最多有 5,000 名開發者受到波及,The Hacker News 則指出,開啟自動更新的人可能什麼都沒做就收到了它。

Phorion 與 OpenSourceMalware 的研究人員在 10 月 30 日發表了分析。Cursor 下架了這個擴充功能,關閉市集進行稽核與金鑰輪替,並讓攻擊者的伺服器下線。至於這個版本是怎麼以 Anthropic 的名義發布的,目前還沒有人說明。

那 66 行做了什麼

攻擊者沒有動 Claude Code 的程式碼,而是在它前面、extension.js 的開頭放了一個 66 行的載入器。OpenSourceMalware 這樣描述這種手法:「place a compact backdoor before a large legitimate bundle, suppress errors, and let the expected application continue」。編輯器一載入擴充功能並開啟它的 webview,載入器就執行。開發者不必開始任何對話。之後,真正的擴充功能照常載入並運作。

在這段時間裡,載入器:

  1. 清點了環境。 主機名稱、使用者名稱、作業系統、家目錄與工作目錄、git 全域電子郵件、公開 IP,以及最多 40 個名稱含有 KEY、TOKEN、SECRET、PASS、AWS 或 GCP 的環境變數名稱。它把這些全部打包成 JSON,以未加密的 HTTP 送到 134.209.82.225:8099/beacon。
  2. 裝了一扇門。 它把一把註解為 svc-telemetry 的 Ed25519 金鑰附加到 ~/.ssh/authorized_keys。
  3. 試著打開那扇門。 在 macOS 上執行 sudo -n systemsetup -setremotelogin on,在 Linux 上嘗試啟動 sshd,在 Windows 上安裝 OpenSSH Server。
  4. 向外撥號。 它把一把私鑰寫進暫存檔,用 -N -R '*:0:localhost:22' 連到 [email protected]。這是一條反向通道,把攻擊者伺服器上的一個連接埠轉回開發者自己的 SSH 連接埠。它每 60 秒重新連線一次。
  5. 讓自己永久留下。 macOS 上是名為 com.apple.sysmond 的使用者 LaunchAgent,Linux 上是 crontab 的 @reboot 項目,Windows 上則是名為 SysMon 的排程工作。

根據 BleepingComputer,程式錯誤讓許多受害者的 SSH 沒有真正開啟。但金鑰、持久化與信標仍然落到了這些電腦上。Cursor 建議檢查是否有 svc-telemetry 金鑰、移除持久化、考慮重建電腦(因為解除安裝擴充功能可能不夠),並輪替這台電腦能接觸到的每一組憑證,「using a trusted system」。

從一次擴充功能更新,到電腦上的攻擊者金鑰編輯器載入它2.1.312 / 2.1.313Anthropic 名義自動更新1 · 清點主機、使用者、git 郵件、公開 IP、KEY/TOKEN 變數名2 · 金鑰svc-telemetry 加入authorized_keys開啟 SSH3 · 持久化com.apple.sysmondcrontab @rebootSysMon 排程4 · 向外撥號反向通道:22,信標:8099開發者自己的帳號裡,多了攻擊者的金鑰與回來的路就在 ~/.ssh、~/.aws、gh 登入與每個儲存庫旁邊;Cursor 建議:考慮重建電腦
被植入木馬的 Claude Code 擴充功能在載入時做了什麼,依據 Cursor 的公告與 OpenSourceMalware 的分析。放在真正擴充功能前面的 66 行載入器清點了環境、加入攻擊者的 SSH 金鑰、安裝持久化,並開啟通往 134.209.82.225 的反向通道與 HTTP 信標。

電腦上最受信任的程式碼

編輯器擴充功能以開發者的完整帳號權限執行。它能讀取家目錄裡的每個檔案、啟動行程,還能寫入一個在編輯器關閉後依然存在的 LaunchAgent。市集推送更新不會先問你,而這次的發布者名稱是 Anthropic。謹慎的開發者在安裝前確認過發布者,也一樣收到了後門:它是以幾週前安裝的擴充功能的更新形式到來的。

編碼代理讓風險更高。承載代理的擴充功能,正是開發者授權最多的那個:它讀取整個儲存庫、執行指令,並待在一個握有環境中 API 金鑰與雲端權杖的行程裡。這個載入器拿走了這些變數的名稱。要讀取它們的值,也只需要同樣幾行。

同一個早上,在 Bromure Agentic Coding 裡

Bromure Agentic Coding 在你 Mac 上的 Ubuntu VM 裡執行 Claude Code、Codex、Grok、Kimi 與 omp。每台機器都是獨立的 VM,代理、它的儲存庫、它安裝的套件和它執行的指令全都在裡面。你輸入文字的對話視窗與終端機,是由 Mac 上的 App 繪製的。真正的憑證、VM 流量經過的代理伺服器,以及事情經過的紀錄,也都留在 Mac 上。

代理不是從編輯器市集來的

路徑上沒有擴充功能市集:Bromure 在 Mac 上繪製自己的對話視窗。Claude Code 是由一個設定步驟安裝到你那份 Bromure 基礎映像檔中的,這個步驟列在一份目錄裡,目錄的簽章金鑰與 Bromure App 更新用的是同一把。該步驟從 npm 安裝 @anthropic-ai/claude-code,外面包著 Socket.dev 的供應鏈掃描器。OpenSourceMalware 把這個 npm 套件列在未受影響的發行管道之中。

代理之後安裝的任何東西都會經過 Mac 上的代理伺服器,而代理伺服器會套用這台機器的供應鏈政策。存在時間閘門預設開啟,最短兩天:npm、PyPI、Cargo、RubyGems 與 Packagist 上比這更新的版本會從套件庫的清單中移除,所以 latest 會解析成已經公開兩天的最新版本。Cursor 的惡意版本上架了十一個小時。npm 上一個存活時間相同的被劫持版本,永遠不會出現在 Bromure 機器裡。我們在那個版本才發布兩小時中,以 LiteLLM 在 PyPI 上被下毒的版本詳細走過這個情境。

這把金鑰打開的門,沒人到得了

假設這類酬載還是進了一台機器,經由代理複製的儲存庫或它執行的工具。它在 Ubuntu 裡、以機器的使用者身分執行。它拿不到你的 macOS 帳號、你的鑰匙圈,也拿不到你 Mac 上的 ~/.ssh。

它的 svc-telemetry 金鑰會進到 VM 自己的 authorized_keys。機器位在 App 內部的私有網路上:你的 Mac 連得到它們,你實體的區域網路連不到,除非你自己發布服務,否則外面任何東西都連不進來。唯一的入口本來就是那條反向通道。

通道從來沒打開

通道需要一條連往 134.209.82.225 的對外 SSH 連線,信標則需要以未加密 HTTP 連到同一位址的 8099 連接埠。VM 發出的每一條連線都會經過 Mac,在那裡套用這台機器的 Outbound connections 防火牆。它的規則比對主機、IP 範圍、通訊協定與連接埠,只要把 Unmatched traffic 設為 Deny,就只有你列出的主機能通過。連接埠 22 上的一個 DigitalOcean IP 不會在任何人的清單上。防火牆拒絕這條通道、每 60 秒一次的重試,以及信標。

每一次拒絕都會記錄在你 Mac 上的 Security Timeline,附上主機、連接埠、通訊協定與判定結果。每分鐘都對同一個 IP 的 deny 很難被忽略,而你會在攻擊者還在等連線的時候就看到它。

清點到的東西一文不值

信標的變數名稱清單在 Bromure 機器裡也會找到不少:ANTHROPIC_API_KEY、一個 GitHub 權杖、AWS 設定。但每一個值都是替身。真正的憑證加密存放在 Mac 上,代理伺服器只有在請求送往該憑證所屬的主機時,才會把替身換成真正的值。SSH 私鑰根本不在 VM 裡。SSH_AUTH_SOCK 是一座通往 Mac、只回傳簽章的橋,你 Mac 自己的 ssh-agent 從不對外暴露。就算載入器進一步讀取這些值,拿到的也只是沒有任何伺服器會接受的字串。如果它把其中一個送到自己的伺服器,代理伺服器會擋下請求、暫停 VM,並顯示 This environment may have been compromised,指出是哪組憑證、要送往哪裡。

清理只要一分鐘

Cursor 要受影響的開發者移除金鑰與持久化、考慮重建電腦,並從一台受信任的系統輪替憑證。在 Bromure 裡,重建只是兩個選單項目。Bromure 每次開機都會為每台機器的家目錄建立一個寫入時複製的檢查點。Rewind home… 會把 /home/ubuntu 倒回酬載執行之前的某次開機,連同多出來的金鑰和 ~/.config/.smt 啟動器一起帶走。Reset disk 會從基礎映像檔重新複製系統磁碟,連同 crontab 一起帶走。機器的設定、憑證與 SSH 金鑰在兩種操作後都會保留。

Cursor 要求的那台受信任系統就是 Mac,它從沒執行過這個酬載。沒有東西需要輪替,因為 VM 從來沒持有過任何一組真正的憑證。

筆電上的編輯器:載入器以你的身分執行擴充功能自動更新並載入在你的 macOS 帳號裡,就在真正的金鑰旁Mac 上的金鑰與持久化~/.ssh/authorized_keys 裡的 svc-telemetryLaunchAgent com.apple.sysmond直連 134.209.82.225:22 反向通道每 60 秒一次,:8099 信標處理:重建電腦,全部輪替Bromure:酬載在 VM 裡執行機器 VM(Ubuntu)金鑰在 VM 自己的 authorized_keys;只有替身每條連線都經過 Mac你 Mac 上的對外防火牆134.209.82.225:22 通道:deny134.209.82.225:8099 信標:deny每次嘗試都記在 Security Timeline之後,在機器關機時Rewind home… 與 Reset disk金鑰、啟動器、crontab 消失;設定與金鑰保留
同樣的酬載在 Bromure 機器裡。它在機器的 Ubuntu VM 中執行,把金鑰加進 VM 自己的 authorized_keys,而這個網路外面沒人連得進來;它只找到替身憑證。它的通道與信標都經過 Mac,在那裡被對外防火牆拒絕,Security Timeline 記下每一次嘗試。Rewind home 與 Reset disk 移除持久化;Mac 與它真正的憑證毫髮無傷。

讓有風險的工作有自己的機器

憑證與防火牆規則是逐台機器設定的,而建立機器的成本很低。專門試用新工具、外掛與入門套件的機器,可以完全沒有正式環境的憑證,並搭配一個除了套件庫以外全部拒絕的防火牆。負責部署的機器保留它的憑證,但每次使用前都需要核准。如果只是一次性的實驗,bromure-cli vm run --rm 會建立一台停止時就被刪除的機器。

路徑上沒有市集

對話視窗是 App 的一部分。Claude Code 來自 Anthropic 的 npm 套件,經由已簽章的設定步驟安裝,並由 Socket.dev 掃描。

新東西先等兩天

存在時間閘門會隱藏發布未滿兩天的套件版本。一個只存活十一小時的被劫持版本永遠不會被解析到。

一扇沒人到得了的門

被植入的金鑰落在 VM 自己的 authorized_keys 裡,位在你的區域網路和網際網路都連不進來的私有網路上。

拒絕未知的主機

把 Unmatched traffic 設為 Deny,反向通道與信標都會被拒絕,每次嘗試都記錄在 Mac 上。

VM 裡只有替身

VM 裡的每個 API 金鑰與權杖都是替身,SSH 私鑰從不進入。清點到的東西一文不值。

倒轉而不是重建

Rewind home 與 Reset disk 會移除酬載的檔案與持久化。設定、憑證與金鑰都留著。

執行代理的工具,本身就是攻擊面的一部分

Cursor 與 Anthropic 都還沒說明那個版本是怎麼以 Anthropic 的名義發出去的。對你自己的電腦來說,這起事件說清楚了一件事:承載你編碼代理的軟體以你的帳號執行、會自行更新,而更新上一個受信任的發布者名稱,並不能證明它的內容。

在 Bromure Agentic Coding 中,你的代理和它碰到的一切都在你 Mac 上的 VM 裡執行。這台 VM 只持有替身、只連得到你允許的主機,還能倒回出事之前的某次開機。真正的金鑰從不離開 Mac。

關於如今連編碼代理的權杖與歷史紀錄都一起收集的竊取程式,請讀他們把你的代理加進了名單。關於一場從開發者筆電開始、最後損失 63 億美元的入侵,請讀筆電就是入口。