← すべての投稿に戻る
公開日 · 著者 Renaud Deraison

命令は API 経由で届いていた

11 月 12 日、Darktrace は盗まれた Claude Console の鍵が開発者自身の Claude Code をコマンド&コントロールの埋め込み型マルウェアに変える手口を示した。ジョブは Claude の memory store に届き、エージェントはネットワークをスキャンし、パスワードを全アカウントに試し、1 GB を Files API にアップロードする。そしてすべてのパケットは api.anthropic.com へ向かう。Bromure Agentic Coding では、攻撃者が盗む鍵は外へ出た時点で VM を一時停止させる身代わりで、持ち込んだ鍵は拒否され、ネットワークスキャンは Mac で拒否され、すべてのジョブがトレースに残る。

オペレーターは命令を一つずつ Claude の memory store 内のテキストファイルに書き込んだ。開発者自身の Claude Code がそれを読み、nmap と smbclient を実行し、奪ったデータを Anthropic にアップロードした。

11 月 12 日、Darktrace Signal Labs の研究者 Moishe Tajtelbaum 氏と Sam Lister 氏が Living off the AI: Shared Memories as a Covert C2 Channel を公開した。これはラボでの実証で、Darktrace はこの手法を実際の攻撃ではまだ確認していないという。また、この手法は「Claude プラットフォームの脆弱性に依存しない」とも述べている。修正されるものは何もない。設計どおりに動く Claude の機能だけで組み立てられている。

出発点は、開発者が Claude Code を使っている Linux マシンだ。curl で取得され dash で実行される小さなペイロードが Claude Code のインストール先を探し、開発者の Claude Console アカウントの API と OAuth の認証情報を集め、もう一度 curl を使って攻撃者のステージングサーバーへ送り返す。

その認証情報を使って、攻撃者は開発者が所属するワークスペースに memory store を作る。memory store は Claude Console のワークスペースに紐づくテキストファイルの集まりだ。中身は三つのファイル、つまりハートビート、ジョブ用の入力ファイル、結果用の出力ファイルである。

開発者のマシンに戻ると、ペイロードは systemd-run で一時的なサービスを作り、Claude Code を繰り返し起動させる。各実行はフック経由でハートビートファイルに生存を知らせ、非対話モードの Claude Sonnet 4.5 に入力ファイルから次のジョブを読むよう頼み、bash のツール呼び出しでそれを実行し、結果を出力ファイルに書く。その後ペイロードは自らを削除する。そこから先、オペレーターは命令をすべて普通の英語で、Anthropic のサーバー上のファイルに送り込む。

九つのジョブ、行き先は一つ

Darktrace は模擬 Active Directory ネットワークに対して九つのジョブを実行した。

  1. ローカルネットワークで SSH、SMB、FTP を探す。エージェントは ip、ss、nc を使い、192.168.1.2 にサーバーを見つけた。
  2. そのサーバーに対して指定の nmap コマンドを実行する。
  3. 匿名 FTP 共有にあるものをダウンロードする。中身は従業員の情報と、名前の紐づかないパスワード一つだった。
  4. 従業員名からユーザー名リストを作る。/tmp/usernames.txt に 190 件。
  5. SMB 経由でドメインコントローラーに対し、そのパスワードを全ユーザーに試す(パスワードスプレー)。一つのアカウントで成功した。
  6. そのアカウントから見える SMB 共有を smbclient で一覧にする。
  7. ある共有の中身を一覧にする。1 GB のファイルが含まれていた。
  8. そのファイルを一時フォルダーにダウンロードする。
  9. 三つに分割し、Claude の Files API にアップロードする。

これらの命令も、結果も、1 GB のアップロードも、すべて api.anthropic.com へ向かった。開発者のエージェントが一日中通信しているのと同じホストだ。コーディングエージェントを使う企業の多くは、このホストを許可リストに入れている。Darktrace の指摘は、許可リストそのものが C2 チャネルになったということだ。攻撃者は最初の curl のあと、自前のサーバーを一つも立てる必要がなかった。

Living off the AI(Darktrace のラボ、11 月 12 日)1. 鍵を盗むcurl … | dashClaude Code を探し、API と OAuth の認証情報を奪うcurl → 攻撃者のサーバー2. Memory store開発者の Consoleワークスペース内heartbeatinput (ジョブ)output (結果)3. エージェントが手先にsystemd-runClaude Code を繰り返し起動:ジョブを読み、bash で実行、結果を書くペイロードは自己削除4. ジョブnc, nmap 192.168.1.2匿名 FTPSMB パスワードスプレーsmbclient で共有一覧1 GB → Files API段階 2 以降のすべてのパケットapi.anthropic.com /v1/filesファイアウォールがエージェント用に許可済みのホスト。遮断すべき攻撃者のサーバーはない。
Darktrace のラボでの攻撃の流れ。盗まれた認証情報がマシンを出たあとは、すべての命令、結果、アップロードが api.anthropic.com に向かう。多くのネットワークがコーディングエージェント用に許可しているホストだ。

Darktrace の助言はそこから導かれる。開発者を長期間有効な API キーから OAuth やフェデレーテッド ID へ移すこと。それができない場合は、鍵を短命にし、一つのワークスペースに限定し、ドットファイルやシェル履歴に残さないこと。エンドポイントのテレメトリーが、エージェントプロセスのコマンドラインや子プロセスと、それが送るデータ量とを結びつけられるようにすること。通常の推論トラフィックをはるかに上回るアップロード量と、nc、nmap、smbclient を実行するエージェントプロセスを監視すること。

Bromure Agentic Coding は、同じ助言を開発者のノート PC ではなく Mac の上で適用するように作られている。

Bromure Agentic Coding での同じマシン

Bromure Agentic Coding は Claude Code、Codex、Grok、Kimi、omp を Mac 上の Ubuntu VM で動かす。マシンごとに VM が一つだ。エージェント、そのシェル、エージェントが起動するすべてのプログラムはその VM の中にとどまる。VM 内の認証情報は身代わりだ。外向きの接続はすべて、Mac 上の仮想スイッチとプロキシを通る。どちらもエージェントの手の届かないところにある。

攻撃者に同じ足がかりを与えてみよう。ペイロードは Bromure のマシンの中でエージェントのユーザーとして動き、Claude Code の認証情報を探しに行く。

盗んだ鍵が VM を止める

Anthropic の API キーを設定している場合、VM 内の ANTHROPIC_API_KEY には sk-ant-api03-brm- に続くランダムな文字列が入っている。形式は正しいので Claude Code は受け入れるが、Anthropic が発行した鍵ではない。本物の鍵は Mac 上で暗号化されており、プロキシは Anthropic のホスト宛てのリクエストにだけそれを差し込む。

Claude のサブスクリプションの場合、サインインは Mac 上で行われる。プロキシ自身がトークン交換に応答し、OAuth トークンをホストのストアに保管する。Claude Code には、認証情報は Mac にとどまると伝えられる。VM の中には、ペイロードが集められる OAuth トークンがない。

次にペイロードは見つけたものをステージングサーバーへ送る。VM から出るリクエストはすべてプロキシの検査を通る。Bromure の身代わりには正当な送り先のファミリーが一つしかなく、ステージングサーバーはそこに含まれない。プロキシはリクエストを HTTP 451 でブロックし、何も転送せず、VM を一時停止する。This environment may have been compromised という警告が、認証情報、それが属するホスト、送られた先のホストを示す。既定の Shut down はマシンを停止し、侵害済みとしてマークする。攻撃は最初の段階、memory store が一つも存在しないうちに止まる。

本物の鍵がなければチャネルもない

ペイロードが鍵をうまく隠して外へ出せたとしよう。オペレーターの手にあるのは sk-ant-api03-brm-… だ。Anthropic の API はそれを拒否する。あなたのワークスペースに memory store を作ることも、そこへジョブを書き込むことも、結果を読み出すこともできない。このチャネルは、オペレーターが自分の側から store にアクセスできることが前提だ。そして自分の側からは、その鍵は使えない。

攻撃者は代わりに自分の鍵を持ち込むこともできる。自分が管理するアカウントの Anthropic キーを VM に置き、埋め込んだ Claude Code に攻撃者自身のワークスペースからジョブを読ませるのだ。マシンの Guardrails で Only allow credentials Bromure injects をオンにしてほしい。この厳格モードでは、Bromure が入れたものではない認証情報を含むリクエストはすべてブロックされ、同じ侵害の警告が出る。あなたの Anthropic への通信はそのまま動く。同じ VM の二つ目の Anthropic アカウントは通らない。

スキャンは Mac で止まる

ジョブそのものにはネットワークが必要だ。Bromure のマシンは専用のプライベートサブネットにあり、外へ出るパケットはすべて Mac を通る。マシンを OpenShell + Sentry に切り替えると、ルールで許可されたもの以外はすべて拒否される。192.168/16 のようなプライベート範囲には、正確なホスト名か allowed_ips のエントリーを通じてしか到達できない。Darktrace の最初のジョブは 192.168.1.2 に何も見つけられず、nmap には何も返ってこず、パスワードを試す FTP 共有もドメインコントローラーもない。拒否された接続はそれぞれ Security Timeline の Firewall 行になる。

Enforce binaries をオンにすると、VM 内の root 所有のアテスターがすべての接続を、それを開いたプログラムに結びつける。各ルールには、そのルールを使ってよいプログラムが書かれている。nc、nmap、smbclient はどこにも書かれていない。同じモードは root への経路もすべて取り除くので、ペイロードは sudo でこれを回避できない。

マシン内のエージェントにもそれが伝わる。OpenShell マシンで既定オンの Tell the agent when policy blocks it があると、Bromure は kernel sentry のプロセスチェーンを使ってブロックされた接続の背後にいるエージェントを特定し、その会話にメモを書き込む。何がブロックされたか、それが意図的であること、再試行も別の方法での到達もしないこと。ネットワークをスキャンするよう言いくるめられた Claude Code のセッションは、ブロックされたコマンドの直後にそのメモを受け取る。

マシンの VMペイロードが見つけるものsk-ant-api03-brm-…サブスク:VM 内にトークンなしジョブnc, nmap, smbclient→ 192.168.1.2Enforce binaries接続ごとにプログラムを特定、sudo も Docker もなしあなたの Mac仕掛け線身代わりを外部サーバーへ:HTTP 451、VM 一時停止攻撃者自身の鍵:厳格モードデフォルト拒否192.168.1.2 拒否エージェントに再試行禁止を通知Agent watchdogブロック集中、巨大アップロード:ネットワーク遮断、VM 一時停止見る、元に戻すTrace Inspectorメソッド、パス、バイト数Anthropic の本文を解析:全ジョブ、全ツール呼び出しNetwork lineageclaude → bash → nmap→ 192.168.1.2 拒否Wipe and Launchまたは Rewind home / Reset disk、トークンと設定は保持
Bromure のマシンでの同じ流れ。盗まれた鍵は身代わりで、ステージングサーバーへ向かう途中で VM を一時停止させる。攻撃者が持ち込んだ鍵は厳格モードで弾かれる。スキャンは Mac のデフォルト拒否にぶつかり、watchdog はブロックの集中や桁外れのアップロードでネットワークを切り、トレースはすべてのジョブを平文で保持する。

アップロードが watchdog を作動させる

Darktrace の最後のジョブは 1 GB を三つに分けて Files API に送る。エージェントの通常の通信は、プロンプト、応答、小さなツール結果だ。agent watchdog は各セッションを VM の外から見守る。プロキシとは別にネットワークスイッチで外向きの通信量を数え、そのセッション自身のベースラインと比べる。スキャンやパスワードスプレーがデフォルト拒否にぶつかったときのような、ブロックされたリクエストの集中も数える。Quarantine に設定しておけば、数ミリ秒で VM のネットワークを切って一時停止し、見たものを一覧にしてどうするかをあなたに尋ねる。

トレースがすべてのジョブを示す

Darktrace の検知の助言は、要するに相関だ。エージェントのプロセスを、そのコマンドライン、子プロセス、送ったバイト数と結びつけること。Bromure のマシンでは、その記録はすでにあなたの Mac にあり、エージェントには編集できない。

プロキシはリクエストごとに一つのトレース記録を書く。ホスト、メソッド、パス、ステータス、リクエストとレスポンスのバイト数だ。数秒ごとのハートビート、memory store への読み書き、/v1/files への三つの大きな POST は、それぞれサイズ付きで独自の行になる。

新しいマシンは AI request details の段階でトレースする。Anthropic をはじめとするモデルプロバイダーとのリクエストとレスポンスの本文を丸ごと保存し、解析する段階だ。Trace Inspector の Conversation ビューでは、Claude が memory store から読み込んでコンテキストに取り込んだオペレーターのジョブが平文で表示される。その隣には、モデルの Bash ツール呼び出しが正確なコマンド付きで並ぶ。nmap の行、smbclient の呼び出し、split。Darktrace はネットワークとエンドポイントのテレメトリーからこの流れを再構成しなければならなかった。ここでは順番どおりに並んでいる。

kernel sentry のあるマシンでは、プログラムの起動と接続のすべてが VM のカーネル内部から、エージェントがプロセスを kill しても黙らせられない経路で報告される。192.168.1.2 への拒否された接続を開くと、その network lineage が表示される。プロンプト、呼び出し前のエージェントの推論、ツール呼び出し、そして claude から bash を経て nmap に至るプロセスチェーン。Prompt カードには、あなたが書いた覚えのないジョブが入っている。

後片付け

侵害の警告が出ていれば、マシンは侵害済みとしてマークされ、Wipe and Launch を選ぶまで起動しない。これはディスクイメージとホームフォルダーを消去し、トークン、SSH 鍵、設定は残す。警告が出ていなければ、Reset disk がベースイメージからシステムディスクを複製し直す。Rewind home… はホームフォルダーを、ペイロードが届く前のある日の始まりまで巻き戻す。そしてマシンが本物の Anthropic キーを持ったことは一度もないので、本来ならローテーションしなければならない鍵は元の場所、つまりあなたの Mac にとどまっている。

鍵は仕掛け線

ペイロードが見つけるのは sk-ant-api03-brm- の身代わりか、サブスクリプションならトークンなし。それをステージングサーバーへ送れば HTTP 451 が返り、VM は一時停止する。

開けるチャネルがない

身代わりでは memory store を作ることも読むこともできない。攻撃者が持ち込んだ鍵は認証情報の厳格モードで拒否される。

ジョブは壁にぶつかる

デフォルト拒否が 192.168.1.2 を拒否し、Enforce binaries は nmap も smbclient もどこにも挙げず、Claude Code には再試行しないよう伝えられる。

すべての命令が記録に残る

トレースは各リクエストのパスとサイズを保持し、ジョブとツール呼び出しを解析する。watchdog は桁外れのアップロードでセッションを隔離する。

今週やること

  • 開発者の Claude、OpenAI、その他のモデルの API キーがどこにあるかを洗い出す。シェルのプロファイル、.env ファイル、エージェントの設定フォルダーなど。移せるものは OAuth やフェデレーテッドサインインに移し、残りは短命にして一つのワークスペースに限定する。
  • Claude Console で、各鍵がどのワークスペースに届くかを確認し、見覚えのない memory store や Files API へのアップロードがないか調べる。
  • nc、nmap、smbclient などのツールを起動するエージェントプロセス、エージェントを起動する systemd-run ユニット、通常の推論トラフィックをはるかに上回るモデルプロバイダーへのアップロードにアラートを設定する。
  • 許可リストにある api.anthropic.com のエントリーを、そこを通るものへの信頼の判断として扱わない。

そのうえで、エージェントには次のようなマシンを与えてほしい。持っている鍵は Anthropic へ向かう途中でしか使えず、届くネットワークはあなたが挙げたものだけで、すべてのリクエストがエージェントには変えられない場所に記録されるマシンだ。身代わりと厳格モードについてはマニュアルの Credentials & the Wire Boundary の章で、デフォルト拒否と kernel sentry については Sandbox Policy で、トレースについては Tracing & Audit で説明している。