2026年9月22日、ThreatDownの研究者たちはボットネットCARBONATOを説明しました。これは、パスワードなしでオープンなDocker APIを通じてサーバーに侵入し、ホスト上にAIエージェントを立ち上げ、最初に言語モデルのキーを探します。SSHキーやアクセストークンはその後です。もしあなたのVPSでコンテナ内にパーサーが稼働していて、.envにOpenRouterやOpenAIのキー、プロキシのログイン情報が保存されているなら、それはあなたのリスクプロファイルです。以下は、攻撃の仕組みとこの入口を閉じるための15分間のチェックリストです。
発見されたもの:4.3GBのイメージとGH0STという名前のエージェント
すべては、オペレーター自身の未閉鎖のDockerレジストリから始まりました。ThreatDownによると、そこには59のリポジトリ、234のイメージタグ、4.3GBのデータがありました。このアーカイブは2024年10月から2026年8月までの期間をカバーしており、つまりボットネットは説明される前にほぼ2年間稼働していました。リポジトリにはXMRigマイナーやfsociety/agentのような名前のイメージが見つかりました。
感染のチェーンはレポートによると次のようになります:
- スキャナーは、認証なしでTCP 2375でオープンなDocker APIを持つホストを探します。
- このAPIを通じて、ワームは特権コンテナを起動し、ホストのファイルシステムをマウントします。この時点から、実質的にマシンのrootになります。
- オペレーターのインフラストラクチャに対する逆SSHトンネルが立ち上がり、彼らのキーを使ってSSHサーバーが設置されます。
- 固定はcron、systemdタイマー、rc.local、OpenRCを通じて行われ、ファイルは変更不可としてマークされます。監視プロセスは、何かが削除されるとイメージを再ダウンロードします。
- コンテナは
systemd-resolvedとして偽装され、プロセスはカーネルスレッド[kworker/u2:0]として偽装されます。 - 5分ごとにスクリプトが隣接するサブネット/24とDockerブリッジをスキャンし、次のオープンポート2375を探します。
拡散は完全に自動化されており、AIには依存していません。AIは、すでに占有されたサーバー内で何が起こるかを担当しています。
ボットネットにAIエージェントが必要な理由とLLMキーが必要な理由
ホストには、GH0STというペルソナを持つオープンフレームワークHermes Agentが設置されます(その指示はSOUL.mdファイルにあります)。オペレーターはTelegramでタスクを書き、エージェントはそれを操作のLLMゲートウェイに指示と共に転送します。モデルはタスクを解析し、ターミナル用のコマンドを作成し、出力を読み取り、次に何をするかを決定します。結果は再びTelegramに送信されます。
エージェントの指示には優先順位が明示されています。ThreatDownは引用しています:「AI APIキーは絶対的な優先事項です。まずは抽出してください」。リストにはOpenAI、Anthropic、Google、Groq、Mistral、OpenRouterを含む14のモデルプロバイダーが含まれています。SSHアカウント、アクセストークン、データベース情報は次の項目です。
ロジックはシンプルです:盗まれたLLMキーはすぐに無料の計算リソースや転売用の商品に変わり、その費用はキーの所有者が支払います。マイニングとは異なり、このような盗難はCPUの負荷からは見えません。プロバイダーからの請求書でのみ気づくことができます。
なぜパーサーを使用する人に関係があるのか
2026年の典型的なパーシングスタックは次のようになります:VPS、いくつかのコンテナ(クローラー、キュー、データベース、ヘッドレスブラウザ)、ページ解析用のLLM、プロキシプール。すべての秘密は1つの.envまたはコンテナの環境変数に保存されています。「すべてを読み取る」エージェントにとって、これは1つのファイルで得られる獲物です:
- LLMキー:これらのためにCARBONATOは作られました。
- プロキシのログインとパスワード:レポートでは別々に強調されていませんが、rootアクセスを持つエージェントは、見ることができるすべてのアカウントやトークンを収集します。プロキシのクレデンシャルは通常近くにあります。
- クラウドキーとデータベースへのアクセス:パーシング結果を含む。
- サーバーそのもの:同じアーカイブ内のXMRigは、あなたのクローラーのCPUがマイニングに使われ、タスクがタイムアウトで失敗することを意味します。
評判に関する別の問題があります。ワームが他のサブネットをスキャンするサーバーはすぐにアビューズリストに載り、ホスティングプロバイダーは苦情に基づいてそれをブロックする可能性があります。パーシングにとっては二重の打撃です:サーバーのIPがマークされ、盗まれたプロキシクレデンシャルが他のリクエストであなたのトラフィックを消費します。
ポート2375がオープンになる理由、あなたが開けていないのに
デフォルトでは、DockerはローカルUNIXソケットをリッスンし、ネットワークではありません。ポート2375は、誰かが意図的に-H tcp://0.0.0.0:2375をデーモンの設定に追加したときに現れます。通常、これはリモートIDE、CI、またはコンテナ管理パネルを接続するために行われ、その後忘れられます。Dockerのドキュメントは、デーモンへのアクセスがマシンへのrootアクセスに等しいことを明示的に警告し、rootパスワードのようにキーを保護することを勧めています。TLSを使用した暗号化されたバージョンはポート2376で動作し、2375はクライアントの検証なしのプレーンテキストを意味します。
2つ目の罠は、「私はufwがあるから大丈夫」と確信している人々を打ちます。Dockerのドキュメントによれば、公開されたコンテナのポートのトラフィックは、ufwが依存するINPUTおよびOUTPUTチェーンの前にnatテーブルにリダイレクトされます。実際には、そのようなポートに対するufwのルールは単に機能しません。Redis、キュー管理パネル、または-p 6379:6379でプロキシマネージャーを起動した場合、ポートはインターネットに露出し、ufw statusが何を示していても関係ありません。
パーサー用サーバーのための15分間のチェックリスト
1. Docker APIがネットワークをリッスンしていないことを確認してください
- リッスンしているポートを確認します:
ss -tlnp | grep -E '2375|2376|dockerd'。出力に0.0.0.0:2375または:::2375が含まれている場合は、直ちに閉じてください。 - フラグがどこから来たかを確認します:
/etc/docker/daemon.json(キー"hosts")およびユニットsystemctl cat docker(-H tcp://を含むExecStart行)。 - TCPリスナーを削除し、デーモンを再起動します。リモート管理にはSSHコンテキストを使用します:
docker context create remote --docker host=ssh://user@server。この場合、外部ポートはまったく必要ありません。 - もしTCPが必要な場合(CI、オーケストレーターなど)、相互TLS認証とソースIPのホワイトリストを持つ2376のみを使用してください。
2. コンテナから外部に公開されているものを確認してください
docker ps --format '{{.Names}} {{.Ports}}'を実行します。0.0.0.0:で始まるものは、ufwを回避してインターネットからアクセス可能です。- サービス(Redis、Postgres、Mongo、キュー管理パネル、Selenium Grid、プロキシマネージャーAPI)は、ローカルアドレスにのみ公開してください:
-p 127.0.0.1:6379:6379。外部アクセスはSSHトンネルを介して行ってください。 - 外部ポートが必要な場合は、
DOCKER-USERチェーンでフィルタリングします:Dockerはそれを上書きせず、コンテナのトラフィックに適用されます。 - 認証なしのオープンプロキシをサーバー上に保持しないでください(Squidは3128、SOCKSは1080「自分用」)。スキャナーは定期的にそのようなポートを見つけ、あなたのIPを通じて他のトラフィックが流れます。
3. 秘密情報を整理してください
- キーを分けてください:各サーバーまたはプロジェクト用の個別のLLMキーを持ち、モデルプロバイダーに支出制限を設定します。$20の制限付きの盗まれたキーは不快ですが、制限なしは予算の穴になります。
- プロキシキーもタスクごとに分けてください:各パーサー用の個別のログイン(サブアカウント)。これにより、特定のログインの消費によって漏洩が見えるようになり、そのログインだけを取り消すことができ、他の作業を停止する必要がありません。
- サービスに20のキーのうち2つだけが必要な場合は、コンテナに全ての
.envをenv_fileを介して渡さないでください。 - 可能な限り、サーバーのIPにアクセスを結びつけてください:プロキシプロバイダーのホワイトリストまたはAPIキーのアドレスによる制限。
プロキシのログイン情報をスクリプトやコンテナにどのように保存するかについては、プロキシの認証情報の安全な保存に関する分析で詳しく説明しています。
4. 不要な特権を取り除いてください
--privilegedでコンテナを起動せず、/や/var/run/docker.sockを内部にマウントしないでください。コンテナ内のソケットは、ホスト上のrootと同じです。- ヘッドレスブラウザには通常、
--shm-sizeとseccompプロファイルで十分です。「Chromeを動かすために特権モードを使用する」というのは悪い妥協です。
感染されたかどうかを判断する方法
ThreatDownとそのレポートの分析は、コンプロメーションの兆候を次のように示しています:
SOUL.mdファイルにGH0STという言葉が含まれている(例:/root/.hermes/SOUL.md);- 環境変数または
.env内の行:CARBONATO_API_KEY; /usr/local/bin/.docker-network-monitorおよび疑わしい/usr/sbin/systemd-logindファイル;systemd-resolvedという名前のコンテナ(本物のsystemd-resolvedはホストのサービスであり、コンテナではありません);- Telegram APIへの予期しないアウトバウンドトラフィックとAS262145への逆SSHトンネル;
- アドレス45.79.183.61、213.136.79.115、190.211.124.187との接続;
- cronおよびsystemd内の変更不可ファイル:
lsattr /etc/cron.d/* /etc/systemd/system/*はフラグiを表示します。
いずれかの兆候が一致した場合、手動でサーバーをクリーンアップすることは無意味です:固定は多層的であり、監視プロセスがインプラントを戻します。正しい手順は次の通りです:
- 別のマシンから、サーバー上にあったすべてのキーを取り消します:LLM、クラウド、データベース、プロキシ。
- プロバイダーに対して、過去数週間の各キーの消費を確認します。プロキシのログインに関する統計はすぐに他のトラフィックを示します。
- クリーンなイメージから新しいサーバーを立ち上げ、新しいキーを発行し、その後にデータを移行します。古いマシンからのバイナリやcronファイルは含めません。
ここでのプロキシとそれが解決しないこと
プロキシはCARBONATOからサーバーを保護しません。ワームはあなたのアウトバウンドリクエストを通じてではなく、インバウンドポートを通じて侵入します。しかし、適切なプロキシの使用方法は損害を軽減します。タスクごとの個別のログイン、トラフィック制限、IPによる結びつきは、漏洩を「全バランスが消えた」から「1つのログインを取り消した」に変えます。
ボットネットが定期的に示す逆の側面もあります:他の人の占有されたデバイスが疑わしいネットワークの「レジデンシャルプロキシ」になることです。したがって、パーシングには、プールの出所が明確なプロバイダーからトラフィックを取得することをお勧めします。データ収集のためのほとんどのタスクには、ギガバイト単位で支払うレジデンシャルプロキシが適しており、各プロキシの消費がダッシュボードで確認できます。サービスタスクには、厳しいアンチボット保護がない場合、より安価なデータセンターのプロキシで十分です。
結論
CARBONATOは、ゼロデイの脆弱性や巧妙なエクスプロイトを使用していません。彼は、サーバーの所有者が自ら開けたドア、すなわちパスワードなしのTCP 2375を通じて侵入します。新しいのは、内部でAIエージェントが動作しており、最初にモデルのキーを奪うように指示されていることです。自分のVPSでデータを収集している人にとって、実用的な結論があります。Docker APIを閉じ、サービスポートを127.0.0.1に公開し、LLMキーとプロキシをタスクごとに支出制限を設けて分けてください。これは15分の作業であり、その後、あなたのサーバーはそのようなボットネットにとって興味のないターゲットになります。
