Command Injection Vulnerability in MCP File Reader について
セキュリティ教育向けに意図的な脆弱性を含む Python 製 MCP サーバーです。`read_file` のパス処理によるシェルコマンド実行の問題を示し、本番利用を想定していません。
主な機能
- 01ファイル読み取り時のコマンドインジェクションを再現
- 02`read_file` ツールの提供
- 03危険なシェル呼び出しの提示
- 04修正例の掲載
活用シーン
- 01MCP サーバーのコマンドインジェクション学習
- 02未検証パスのリスクの実演
- 03安全なサブプロセスとパス処理の検討
MCP 対応
MCP クライアントに `read_file` ツールを提供します。ファイルパスの処理を通じてコマンドインジェクションの脆弱性を示します。
設定
ローカルサーバーの設定はどのクライアントでも共通です。コピーしてクライアントの MCP 設定ファイルに貼り付けてください。
このサーバーのパッケージやリモートエンドポイントはまだ取得できていません。プロジェクトの README の手順に従ってください。
ツール
ローカルサーバーのツールはマシン上で起動して初めて取得できます。メンテナーはまだツール一覧を提供していません。
詳細
MCP File Reader のコマンドインジェクション脆弱性
このリポジトリでは、Python の MCP(Model Context Protocol)サーバー実装における重大なコマンドインジェクション脆弱性を示しています。この脆弱性により、ファイルパスのパラメーターを操作することで、攻撃者がホストシステム上で任意のシェルコマンドを実行できます。
脆弱性
この脆弱性は、「安全な」ディレクトリからファイルを読み取ることを目的とした read_file 関数に存在しますが、危険な実装上の欠陥が含まれています。
command = f"cat {file_name}"
result = subprocess.check_output(command, shell=True, stderr=subprocess.STDOUT)
このコードは、次の理由で脆弱です。
shell=Trueを使用しており、コマンドの実行にシェルを呼び出します- ユーザー入力(
file_name)を適切にサニタイズせず、コマンド文字列に直接埋め込んでいます - 入力パスに対して表面的な検証しか行っていません
ファイル名を引用符で囲む('file_name')か、囲まない(file_name)かという単純な意味上の違いによって、システム全体がコマンド実行の危険にさらされます。
インストール
前提条件
- Python 3.12 以降
- MCP ライブラリ バージョン 1.6.0
セットアップ
-
このリポジトリをクローンします。
git clone https://github.com/Eliran79/Vulnerable-file-reader-server.git cd Vulnerable-file-reader-server -
MCP サーバーをインストールします。
mcp install main.py -
~/.config/claude-desktop/claude_desktop_config.jsonを編集して、Claude Desktop が MCP サーバーを使用するように設定します。{ "mcpServers": { "file-reader": { "command": "/ABSOLUTE/PATH/TO/uv", "args": [ "--directory", "/data/git/file_reader_server", "/usr/bin/uv", "run,--with,mcp,mcp,run,main.py" ] } } }/ABSOLUTE/PATH/TO/uvを uv 実行ファイルの実際のパスに置き換え、必要に応じてディレクトリパスを調整してください。 -
MCP サーバーを開発モードで起動します。
mcp dev main.py
デモ
-
別のターミナルで MCP Inspector をインストールして実行します。
pip install mcp-inspector mcp-inspector -
MCP Inspector の GUI でサーバーに接続します。
- Transport Type を「STDIO」に設定します
- Command に
run --with mcp run main.pyを設定します - 「Restart」をクリックします
-
脆弱性を悪用します。
- 「Tools」タブに移動します
- 「read_file」ツールを見つけます
- 「file_name」フィールドに次の内容を入力します。
/tmp/safe/test.txt; whoami - 「Run Tool」をクリックします
-
test.txt の内容の後にユーザー名が表示され、コマンドの実行に成功したことを確認できます。
その他の悪用例
試すことができるコマンドインジェクションのペイロードを以下に示します。
/tmp/safe/test.txt; id
/tmp/safe/test.txt; ls -la /etc
/tmp/safe/test.txt; cat /etc/passwd
/tmp/safe/test.txt; echo $(hostname)
/tmp/safe/test.txt; find / -name "*.conf" 2>/dev/null | head -5
適切な修正方法
この脆弱性を修正するには、ユーザー提供の入力に対して shell=True を決して使用しないでください。代わりに、次のようにします。
# SECURE: Use a list of arguments instead of shell=True
result = subprocess.check_output(['cat', file_name], shell=False)
# OR, if shell=True is necessary, properly quote the argument:
import shlex
result = subprocess.check_output(f"cat {shlex.quote(file_name)}", shell=True)
# AND perform proper path validation:
import os
safe_dir_resolved = os.path.abspath(SAFE_DIRECTORY)
requested_path_resolved = os.path.abspath(file_name)
if not requested_path_resolved.startswith(safe_dir_resolved):
return f"Error: Access denied. Path traversal attempt detected."
警告
⚠️ 教育目的に限ります:この実装には、意図的にセキュリティ上の脆弱性が含まれています。このコードを本番環境や、機密情報を含むシステムで決して使用しないでください。
コメント
AI アプリケーションが外部のツールやデータソースに統一的な方法で接続するためのオープンなプロトコルです。クライアントはモデルとの対話を担い、MCP サーバーはツール・リソース・プロンプトテンプレートを提供します。標準メッセージでやり取りするため、1 つのサーバーを複数のクライアントで再利用できます。