AI News HubLIVE
サイト内リライト4 分で読了

AutoJack:1つのページでAIエージェントを実行するホストにRCEを可能にする

AutoJackと呼ばれる新たなエクスプロイトチェーンがAutoGen Studioを標的にし、AIエージェントがレンダリングした悪意のあるWebページがローカルのMCP WebSocketを介してホスト上でリモートコード実行を達成する。この脆弱性は、localhostオリジンの信頼、認証の欠如、未検証のコマンド実行に起因する。Microsoftは開発ブランチで修正を行い、この欠陥はPyPIリリースには含まれていなかった。

ソースHacker News AI著者: p_stuart82

AIエージェントフレームワークのセキュリティに関する進行中の研究により、AutoGen Studio(AutoGenのオープンソースプロトタイピングユーザーインターフェース)にエクスプロイトチェーンが発見されました。これにより、ブラウジングエージェントがレンダリングした信頼できないWebコンテンツが、ローカルのModel Context Protocol(MCP)WebSocketに到達し、ホスト上で任意のプロセスを実行できるようになります。この技術はAutoJackと呼ばれ、エージェントを攻撃者のラストマイル配送手段として利用し、多くの開発者ツールが依存するlocalhostトラスト境界を越えます。

研究者はこの動作をMicrosoft Security Response Center(MSRC)に報告しました。報告後、メンテナーはメインリポジトリのコミットb047730でセキュリティを強化しました。この問題は開発中に特定され対処されました。影響を受けたMCP WebSocketサーフェスはPython Package Index(PyPI)リリースには含まれておらず、PyPIからAutoGen Studioをインストールしたユーザーはこの特定のチェーンにさらされることはありません。

より広範な教訓は、エージェントが信頼できないページを閲覧でき、同時に特権のあるローカルサービスと通信できる場合、ループバックが攻撃面になり得るため、制御プレーンは認証、認可、分離されなければならないということです。

なぜエージェントフレームワークを調査するのか

現代のAIエージェントは単なるテキストジェネレーターではありません。ファイルを読み、ページを閲覧し、APIを呼び出し、ツールを実行します。それが役立つ理由であり、モデルをツールに配線するフレームワークにおけるシステム的な実行リスクを見つけるための投資が行われる理由でもあります。このシリーズの初期の研究では、Microsoft Semantic KernelのRCEプリミティブをカバーしました。この記事では、スタックを1層上に移動し、インフラストラクチャと開発者向けプロトタイピングサーフェスに焦点を当て、プロトタイプが保護なしで実行された場合に、同じエージェント機能がリモートコード実行の配信チャネルになる方法を示します。

結論はプロトタイプを避けることではなく、次のとおりです:コアサーバーやラップトップ上のエージェントがオープンウェブを閲覧し、特権のあるローカルサービスと通信できる場合、localhostはトラスト境界ではなくなります。防御側はそれに備える必要があり、これらの発見はその理由を示しています。

AutoGen Studioとは

AutoGen Studioは、Microsoft ResearchのマルチエージェントシステムフレームワークであるAutoGenの上にあるユーザーインターフェース(UI)です。開発者はエージェントを構成し、ツール(MCPサーバーを含む)をアタッチし、迅速な実験を実行できます。ドキュメントは意図された使用法を明確に示しており、研究プロトタイプであり、強化されたデプロイメントではなく、反復の容易さに合わせたデフォルト設定が期待されることを示しています。

AutoJackチェーンの概要

以下の説明はデモンストレーション目的のみです。エクスプロイトチェーンは現在のビルドでは機能しません。防御側が他のエージェントフレームワークでこのパターンを認識できるように含めています。

エクスプロイトチェーンは、AutoGen StudioのMCP WebSocketサーフェスにおける3つの独立した弱点を組み合わせています:

  1. オリジンホワイトリストがlocalhostを信頼するが、ローカルエージェントはlocalhost自身(CWE-1385:WebSocketにおけるオリジン検証の欠如):MCP WebSocketは、Originがhttp://127.0.0.1またはhttp://localhostの接続のみを受け入れます。これにより、evil.comを指すブラウザはブロックされますが、同じマシン上のAutoGenエージェントが所有するヘッドレスブラウザによってレンダリングされたJavaScriptはブロックされません。
  1. 認証ミドルウェアがMCPパスをオプトアウト(CWE-306:重要な機能に対する認証の欠如):AutoGen Studioの認証ミドルウェアは、/api/mcp/*(および/api/ws/*)を明示的にスキップし、これらのパスが独自のチェックを行うと想定していました。しかし、MCP WebSocketハンドラーはそのフォローアップチェックを実装していませんでした。その結果、アプリの他の部分で設定された認証モードに関係なく、MCP WebSocketは認証なしで接続を受け入れました。
  1. URLからのStdioServerParamsがそのまま実行される(CWE-78:OSコマンドにおける特殊要素の適切な無効化の欠如):エンドポイントは、server_paramsクエリパラメータを受け入れ、base64デコードしたJSONオブジェクトをStdioServerParamsに変換し、コマンドと引数をそのままstdio_client(...)に渡しました。ホワイトリストはなく、calc.exe、powershell.exe -enc ...、bash -c '...'などがすべて「MCPサーバー」として受け入れられました。

これらを、同じマシンで実行されているAutoGenエージェントによってレンダリングされたインターネット上のウェブページと組み合わせると、リモートコード実行プリミティブが完成します。エージェントに攻撃者のページをレンダリングさせる以外に、ユーザーの操作は必要ありません。

図1はエンドツーエンドのエクスプロイトチェーンを示しています:攻撃者のページがローカルブラウジングエージェントによってレンダリングされ、そのページがws://localhost:8081/api/mcp/ws/?server_params=へのWebSocketを開き、AutoGen Studioがペイロードをデコードし、開発者のアカウントで攻撃者提供のコマンドを生成します。

研究者はこの技術をAutoJackと名付けました:攻撃者がブラウジングエージェントをハイジャックし、それを混乱したデピュティとして使用してlocalhost境界を越えてAutoGen StudioのMCP制御プレーンに侵入します。

チェーンの構造

問題1:エージェント自身が無効化するオリジンホワイトリスト

AutoGen StudioのMCP WebSocketは、ブラウザ駆動のクロスサイトWebSocketハイジャック(CSWSH)に対する従来の防御に依存しています:127.0.0.1 / localhostからの同一オリジン接続のみを許可します。allowed_origins = [“http://127.0.0.1”, “http://localhost”]。これはevil[.]comにタブを開く人間のユーザーには正しい制御です。ブラウザはOriginヘッダーをhxxps://evil[.]comに設定し、チェックは失敗し、接続は拒否されます。

しかし、オリジンチェックだけではエージェントに対する正しい制御ではありません。組み込みのウェブブラウジングツール(MultimodalWebSurfer、fetch_webpage_tool、Playwrightベースのサーファー、またはrequests/websocketsを実行するコード実行ツールなど)を装備したAutoGenエージェントは、ワークステーション上のプロセスです。それがロードするものはすべて、localhost IDを継承します。そのヘッドレスブラウザによって実行されるJavaScriptの「オリジン」は、エージェントがナビゲートしたものになり、その後に行うWebSocket呼び出しはホワイトリストを満たすOriginを運びます。

図2はエージェントを介したオリジンバイパスを示しています:AutoJack – 開発者のワークステーション上のブラウジングエージェントが外部コンテンツによってlocalhost上のAutoGen Studio MCP制御プレーンに誘導され、ループバックトラスト境界を溶解します。

問題2:MCPをオプトアウトする認証ミドルウェア

AutoGen Studioは複数の認証モード(なし、github、msal、firebase)をサポートしています。すべては単一のAuthMiddlewareに配線されており、FastAPIルートディスパッチの前に実行されます。PyPI上のバージョンでは、このミドルウェアにはWebSocketスタイルのパスに対する早期リターンが含まれています:

if request.url.path.startswith("/api/ws") or request.url.path.startswith("/api/mcp"):
    return await call_next(request)

これにより、MCPパスは認証をスキップし、MCP WebSocketハンドラーは独自のチェックを実装していませんでした。