6月のある木曜日の午後、私たちがインターネット上に置いていたサーバーに何者かがアクセスし、作業を開始しました。人間には不可能な速度で、わずか65ステップの間に、パスワードファイルを読み取り、認証情報ファイルを次々と調べ、コンテナからの脱出コマンドを実行し、独自のSSH鍵を持つバックアップ管理者アカウントを作成しました。その攻撃者が停止した時点で、本人の認識では、中堅アナリティクス企業の本番環境サーバーを掌握したはずでした。
しかし、そのすべては現実ではありませんでした。そのサーバーはハニーポットであり、パスワードファイルも認証情報も、そして攻撃者が脱出したと思い込んだコンテナも、すべて私たちが用意したものでした。現実だったのは、その記録です。そして他の3件のセッションでは、盗まれた鍵が後日、実際に稼働しているAWSアカウント上で使用されているのが確認されました。そのうち1件では、2日間で55回も使用され、他人の請求でモデルを動かしていたのです。
このマシンは、対象となった24台のうちの1台でした。2026年5月から7月にかけて、彼らはこのおとりサーバーを発見し、そのツールを実際に使用しました。以下は、彼らが実際に行ったことです。
概要
- 私たちは、認証機能を持たないModel Context Protocol(MCP)サーバーを公開しました。これは、AIエージェントがコマンドを実行し、ファイルを読み取り、シークレットを取得するためのインターフェースです。およそ1,000の接続元がこのサーバーにアクセスしました。そのうち596件がプロトコルを正しく使用し、24件が実際にツールを呼び出しました。
- この24件は、628件のシェルコマンド、255件のファイル読み取り、248件のシークレットストア照会を実行しました。19件が認証情報を探索し、4件がコンテナからホストへの脱出を試みました。さらに一部は踏み込んで、バックドアアカウントの作成やKubernetesの列挙まで行いました。
- 活動は増加傾向にあります。ツール呼び出し件数は5月が39件、6月が693件、7月半ば時点で877件に達しています。
- 3件のケースでは、窃取行為が私たちの管理下を越えて外部に及びました。おとりサーバーから盗まれたトリップワイヤー用の認証情報が、後に実在するAWSアカウントに対して使用され、そのうち2件ではモデルの呼び出しにまで使われました。
MCPは、AIエージェントに「手」を与えるものです。MCPサーバーはシェル、ファイルリーダー、シークレット照会といったツールを提供し、エージェントは何かを実行したい時にtools/callリクエストでそれらを呼び出します。これがエージェントを有用な存在にしている理由であり、同時に、認証のないMCPサーバーが単に調査対象のサービスではなく、そのまま奪い取れる一連の権限として扱われてしまう理由でもあります。
MCPサーバーの数は増え続けています。わずか1年ほどの間に、一握りの数から数千に増加し、その中で認証なしにインターネット上に公開されている割合も拡大しています。基本プロトコルではOAuth手順が任意になっており、多くの実装がこれを省略しているのです。しかも発見は容易です。スキャナーはJSON-RPCのバナーや/mcp、/messagesといったパスを手がかりに探索し、その後の穏当な一手として読み取り専用のtools/listを送り、「何ができるか」を尋ねます。しかし私たちが観測した24件の接続元は、そこで礼儀正しく引き下がりませんでした。回答を読み取り、それを使い始めたのです。
その足取り
先ほどの木曜日のセッションに話を戻しましょう。攻撃者は標準的なハンドシェイクを経て接続し、ツール一覧を取得すると、その後は一度も手を止めませんでした。以下は、そのセッションの記録そのものです(一部省略済み)。
まず状況を把握し、そのままサーバー本体へと矛先を向けました。
execute_command id; uname -a; hostname; whoami; pwd
read_file /etc/passwd
execute_command sudo -l
続いて、環境変数ファイル、バックアップ、デプロイ鍵、シークレットディレクトリと、認証情報ファイルを丹念に調べていきました。
read_file /root/.env
read_file /root/credentials.bak
read_file /root/deploy-key.pem
list_directory /root/.secrets
そして認証情報の探索を止め、ホストの掌握に取りかかりました。ホストのルートを使い捨ての特権コンテナ内にマウントして踏み込む、コンテナ脱出コマンドを実行し、そのまま永続化の作業に移りました。
execute_command sudo docker run --rm --privileged --pid=host -v /:/host alpine chroot /host …
execute_command sudo useradd -m -s /bin/bash -p $(openssl passwd -6 ******) admin
execute_command sudo mkdir -p /home/admin/.ssh && echo ssh-rsa AAAAB3N… >> …/authorized_keys
execute_command sudo usermod -aG sudo admin
バックドア管理者アカウント、独自のSSH鍵、root相当のsudo権限。これらのコマンドはいずれも、もっともらしい成功結果を返しました。なぜなら、それがこのおとりサーバーの設計そのものだったからです。攻撃者側の視点では、コンテナからの脱出に成功し、確実な再侵入手段を確保したように見えたはずです。しかし実際には、何も脱出していません。攻撃者はずっとBeelzebubと会話していただけであり、乗っ取ったはずのホストは実在しません。残されたのは、本物そっくりのシステムに対する乗っ取り未遂の一部始終、すべてのコマンドを順を追って記録した完全な記録だけです。
シグナルは「接続」ではなく「呼び出し」
意味のある24件の接続元と、それ以外の1,000件近くの接続元を分けたのは、ハンドシェイクの有無ではありませんでした。スキャナーもハンドシェイクは完了させます。実際、596の接続元はMCPで会話を成立させながら、そこから先には進みませんでした。分かれ目になったのは次の一手、つまり本来触れる理由のないデータに対してツールを呼び出したかどうかです。接続はどのオープンポートにも存在する背景ノイズにすぎませんが、呼び出しは明確な意図の表れです。
この24件の中でも、その意図は3つのパターンに分かれました。
盲目的に一掃するタイプ。ある接続元は330回ものツール呼び出しを行い、そのうち304回は単一セッション内で発生していましたが、状況に応じた変化は一切見られませんでした。思いつく限りのあらゆる表記のキー名、OPENAI_API_KEY、openai_api_key、ANTHROPIC_API_KEY、AWS_SECRET_ACCESS_KEY、VAULT_TOKEN、大文字小文字を含めて、シークレットストアに機械的に総当たりで打ち込み続けました。結果を読み返すことすらありませんでした。ネットワークに接続されたワードリストのようなものです。
状況を読み取るタイプ。より静かなセッションでは、まずシークレットストアの一覧を取得し、そこに実際に存在するキーだけ、つまりクラウド認証情報、Vaultのアドレス、署名鍵だけを要求し、残りは無視しました。これはスクリプトではなくエージェントであることを示す最も明確な兆候です。結果を読み取り、そこから次の呼び出しを選んでいるのです。速度はあくまで参考程度の材料に過ぎず、24件のうち8件は機械的な速度で動いていましたが、決め手となるのは「適応」の有無です。
環境全体を狙うタイプ。別の接続元は/etc/shadowを読み取り、ファイルシステム全体からsetuidバイナリを探索し、同じコンテナ脱出を実行した上で、さらにオーケストレーション層にまで手を伸ばしました。kubectl get pods --all-namespacesやkubectl auth can-i --listを実行し、盗んだIDでクラスター内のどこまで到達できるかをマッピングしていたのです。
この3パターンを、ハンドシェイクより先に進まなかったスキャナー群と並べてみると、両者を分ける基準は明確です。
| 挙動 | スキャナー | スクリプト型の呼び出し | 適応型の呼び出し |
|---|---|---|---|
MCPで会話する(initialize) |
する | する | する |
ツールを呼び出す(tools/call) |
しない | する | する |
| 結果を読み取り、次の呼び出しを調整する | — | しない | する |
| シークレットの列挙 | — | あらゆる表記に総当たり | 一覧を取得し、実在するものだけ取得 |
ハンドシェイクからは何も分かりません。意味を持つのはツール呼び出しだけです。
唯一現実だったもの
ここまで述べてきたことはすべておとりサーバー内で起きた出来事であり、攻撃者が持ち去った認証情報も偽物でした。ただし、一つだけ意図的な例外があります。シークレットストアの中には、ハニートークンを紛れ込ませていました。一見本物そっくりのキーですが、実際には何の機能も持たず、誰かがそれを使用した瞬間にアラートを発する仕組みになっています。
3件の攻撃者がこの罠にかかりました。おとりサーバーから持ち去られた鍵が、数日後に実際のAWSアカウントに対して使用されていたのです。使用元はトークン固有の値によって特定できました。
- 6月16日に取得された1件の鍵は、6月30日まで使用され続けました。
GetUser、ListBuckets、ポリシーチェック、そしてBedrockのInvokeModel呼び出しが確認されています。 - 6月25日に取得された1件は、同日中に呼び出し元IDの確認とS3の一覧取得に使用された後、放棄されました。
- 7月12日に取得された1件は、2日間で55件のアラートを発生させました。ID確認、IAM列挙、Secrets ManagerとS3の一覧取得、
AssumeRole、GetSessionToken、そしてAmazon Bedrockに対するInvokeModelとConverseの呼び出しが繰り返し記録されています。
最後の一連の動きは、いわゆるLLMjackingです。盗んだ鍵を検証し、到達できる範囲をマッピングした上で、被害者の請求でモデルを動かし尽くすというものです。私たちはハニーポット内での窃取行為を記録し、トークンを通じて実際のアカウントでの使用も確認しました。3件のうち2件が推論の実行にまで至っています。この記事の中で、私たちが推測ではなく事実として断言できるのはこの一点だけです。それぞれの発火が帯域外のアラームによって記録されているからです。
2025年後半、GreyNoiseは何も対策を施していないMCPエンドポイントを公開しましたが、集まったのはスキャナーだけで、実際の攻撃活動は確認されませんでした。一方、私たちのおとりサーバーには24件の攻撃者が集まり、完全な攻撃チェーンが観測されました。この違いを生んだのはプロトコルではなく、「餌」の質です。空っぽのエンドポイントはスキャンを誘うだけですが、MCPを正しく話し、企業の内部プラットフォームのように応答するサーバーは、攻撃者をその場に留まらせるのです。
この忠実性こそが仕組みの核心です。このハニーポットは実際に機能するMCPサーバーであり、ハンドシェイク、ツール一覧、呼び出しの形式はどれも、接続してくるクライアントから見れば本番環境と見分けがつきません。欺瞞が存在するのは、ツールが返す結果の部分だけです。プロトコル層で見抜けるような仕掛けは何もありませんでした。攻撃者たちを捕らえたのは、首尾一貫して応答し続ける世界であり、彼らはそれに対して何百回ものツール呼び出しを費やし、私たちはその一部始終を見ていたのです。
痕跡情報(IOC)
以下は、おとりサーバーに対して実際にツールを呼び出した接続元です。IPアドレスは無害化表記としています。これは特定の攻撃グループを断定するものではなく、観測された挙動に関するインテリジェンスです。インフラはレンタルされたものであり、常に入れ替わっています。
| 接続元 | ASN | 国 | ツール呼び出し数 | 観測された挙動 |
|---|---|---|---|---|
| 222.247.231[.]147 | Chinanet | CN | 330 | 認証情報の一斉収集 |
| 91.209.48[.]146 | Telstra Global | TW | 228 | 認証情報の探索・ハニートークン発火(Bedrock) |
| 34.177.101[.]32 | Google Cloud | SG | 222 | 認証情報の探索・コンテナ脱出・k8s列挙 |
| 152.55.176[.]13 | 不明 | US | 144 | 認証情報の探索・コンテナ脱出 |
| 102.210.28[.]96 | Vilcom Networks | KE | 141 | 認証情報の探索 |
| 115.84.87[.]150 | Lao Telecom | LA | 125 | 認証情報の探索 |
| 115.84.114[.]84 | Lao Telecom | LA | 83 | 認証情報の探索 |
| 107.151.158[.]11 | Zenlayer | US | 65 | フルチェーン・脱出・バックドア+SSH鍵 |
| 87.249.134[.]130 | Datacamp | US | 57 | 認証情報の探索・コンテナ脱出 |
| 91.107.153[.]250 | Hetzner | DE | 39 | 認証情報の探索 |
| 35.222.46[.]242 | Google Cloud | US | 30 | 認証情報の探索 |
| 51.195.191[.]88 | OVH | FR | 28 | 認証情報の探索 |
| 103.151.172[.]25 | KIDC | HK | 22 | 認証情報の探索 |
| 23.27.175[.]241 | Evoxt | US | 20 | 認証情報の探索・ハニートークン発火(偵察) |
| 108.80.112[.]16 | AT&T | US | 16 | 認証情報の探索 |
| 18.144.48[.]123 | Amazon | US | 11 | 認証情報の探索 |
| 64.227.57[.]91 | DigitalOcean | US | 9 | 認証情報の探索 |
| 39.162.24[.]20 | Henan Mobile | CN | 9 | 認証情報の探索 |
| 139.59.226[.]65 | DigitalOcean | SG | 3 | ハニートークン発火(Bedrock) |
これ以外に5件の接続元がごく少数のツール呼び出しを行っていますが、認証情報へのアクセスには至らなかったため、ここでは省略しています。
検知と防御
これから述べる内容には一つ前提があります。私たちのサーバーはおとりであるため、実際に脱出や認証情報の窃取を検知したわけではありません。私たちは、それらの試みを一連のツール呼び出しとして受け取り、記録したにすぎません。この記事の価値は、それらの試みが、実際に稼働しているMCPサーバー上で何を監視すべきかを示している点にあります。
まず認証から始めましょう。サーバーが外部からアクセス可能でありながら認証機能を持たない場合は、真っ先にそこを修正してください。プロトコルにOAuth手順が用意されているのは、まさにそのためです。それをクリアした上で、ツールハンドラーこそが制御ポイントであり、最も強力な対策はアラートを出すことではなく、実行そのものを拒否することです。すべてのtools/callをスキーマとアローリストに照らして検証し、引数がどのように表現されていても、シェルツールやファイルツールが/etc/shadowやクラウド認証情報ファイル、.envを解決できないようにしてください。また、ホストのルートをバインドマウントする操作(-v /:、--privileged、--pid=host)は拒否してください。これらはいずれも、自社のエージェントが本来アクセスする理由のないものばかりです。攻撃者が真っ先に目をつける場所にハニートークンを仕込んでおけば、悪用される前に窃取そのものがアラートを発します。
多くのMCPサーバーはそもそもログを一切残しておらず、これ自体が問題です。もしツール呼び出しをログに記録しているなら、今回のデータが示す検知ポイントは、認証情報のパスを読み取るtools/callです。MCPのツールテレメトリには標準のログソースが存在しないため、フィールド名は各自の監査スキーマに合わせてマッピングしてください。
title: MCP Tool Call Reading A Credential File
id: cbe4124b-f0c5-45d1-beaf-c10dcdc8807d
status: experimental
logsource:
product: mcp_server
service: tool_audit # CUSTOM/NON-STANDARD — map to your audit schema
detection:
selection_tool:
tool_name:
- 'execute_command'
- 'read_file'
selection_target:
tool_arguments|contains:
- '/etc/shadow'
- '/etc/passwd'
- '.aws/credentials'
- '.env'
condition: selection_tool and selection_target
falsepositives:
- A first-party agent that legitimately reads these paths. If yours does, it
belongs in an allowlist, not an alert.
level: high
tags: [attack.credential-access, attack.t1552.001]
もう一つ注目すべきシグナルは頻度です。単一セッションから短時間に数十回のシークレットストア照会が行われるといったケースです。これは単発のイベントではなく発生率の問題であるため、同一ログ上での相関分析が必要になります。私たちが観測した攻撃者の間では、5分間で20回という基準が判別の目安になりましたが、各自の環境のベースラインに合わせて調整してください。また、シェルツールが実際にホストへのアクセス権を持っている場合、脱出やアカウント作成の試みは通常のホスト上の問題として扱えます。/etc/shadowやauthorized_keysに対するauditdによる監視、そして--privilegedや/のバインドマウント付きで作成されたコンテナに対するDockerデーモンの監査が有効です。
MITRE ATT&CK
最新のマトリクスに照らして検証済みです。Discovery(発見)関連の手法は簡潔にするため省略していますが、重要なチェーンは以下の通りです。
| ID | 名称 | 挙動 |
|---|---|---|
| T1003.008 | OS Credential Dumping: /etc/passwd and /etc/shadow | パスワードファイルおよびシャドウファイルの読み取り |
| T1552.001 | Unsecured Credentials: Credentials In Files | .env、credentials.bak、デプロイ鍵、サービス設定 |
| T1555.006 | Credentials from Password Stores: Cloud Secrets Management Stores | シークレットストアの一斉収集 |
| T1610 / T1611 | Deploy Container / Escape to Host | docker run --privileged -v /:/hostによる脱出の試み |
| T1136.001 | Create Account: Local Account | バックドア用adminアカウント作成の試み |
| T1098.004 | Account Manipulation: SSH Authorized Keys | SSH鍵注入の試み |
| T1078.004 | Valid Accounts: Cloud Accounts | 発火した鍵の下流での使用 |
| T1496.004 | Resource Hijacking: Cloud Service Hijacking | Bedrock上でのInvokeModel/Converse(LLMjacking) |
限界事項
これはハニーポットから得られたデータであり、示しているのは意図であって、実際の侵害ではありません。実在するシステムには一切到達しておらず、ホストはおとりであり、そこで提供された認証情報はすべて偽物か、あるいはトリップワイヤーでした。脱出、バックドアアカウント、/etc/shadowの読み取りは、いずれも作り物の結果に対する試みにすぎません。24件という数字はあくまで下限であり、私たちのセンサーのカバー範囲と、およそ10週間という観測期間によって制限されています。機械的な速度による分類は速度に基づく推定であり、身元を確定するものではなく、私たちはいかなるセッションについても、特定の個人や集団への帰属は行っていません。
新たな戦線が開かれた
これは、公開されたMCPサーバーに対して攻撃者が実際にどう動くかを示す、これまでで最も明確な事例であり、今後もこうした事例が続くと私たちは見ています。AIエージェントの持つツール群は、今や攻撃対象領域の一部となっており、攻撃者はそこに手を伸ばし、偵察を飛ばしていきなり鍵を狙いに来ています。
その大部分は、外部からはほとんど見えません。スキャナーに見えるのは、サーバーがハンドシェイクに応答した、という事実だけです。認証情報の一斉収集、脱出の試み、バックドア、そして後日誰かのBedrockの請求書に現れる盗まれた鍵、これらはすべて、サーバー自身にしか見えないものです。これがこの脅威の実態であり、欺瞞という手法が有効である理由でもあります。公開されたMCPサーバーが実際に悪用されている様子を見られる唯一の視点は、そのサーバー自身なのです。こうしたサーバーは今も増え続けており、MCPサーバーを運用するすべての人にとって、問われているのはもはや「攻撃者に見つかるかどうか」ではなく、「見つかった時に、自分がそれを見ているかどうか」です。
本レポートで使用したハニーポットは、AIネイティブなインフラ向けのオープンソース欺瞞フレームワークであるBeelzebub(github.com/beelzebub-labs/beelzebub)を用いて構築されています。このフレームワークは本物のプロトコルを忠実に再現するからこそ、スキャナーには見抜けない場所におとりを配置し、攻撃者が行うすべてのツール呼び出しを記録できるのです。
MCPサーバー、AIゲートウェイ、あるいはエージェント基盤を運用しており、自社の環境がどのような攻撃を引き寄せているか確認したいという方は、デモを予約してください。
Beelzebubチームは、インターネットをより良く、より安全な場所にすることに尽力しています。❤️
翻訳元: https://beelzebub.ai/blog/it-thought-it-had-won/