
ルート登録における関数呼び出しが1つ欠落していただけで、MCPインターフェースが認証なしのRCEゲートウェイと化すのに十分だった。
nginx-ui の MCP 認証バイパスとして公に MCPwn として知られる脆弱性に対する非破壊的な検出ツールです。脆弱なバージョンが稼働している任意の nginx-ui インスタンスに対して、2 つの HTTP リクエストによる未認証の乗っ取りを実行します。
nginx-ui は Model Context Protocol (MCP) インターフェースを公開しており、認証されたオペレーターが JSON-RPC を通じて nginx 設定の編集、再起動コマンド、バックアップ操作などの破壊的なツールを操作できます。
/mcp エンドポイントは AuthRequired() ミドルウェアで保護されていますが、実際にツール呼び出しを受け取るペアとなる /mcp_message エンドポイントは、ミドルウェアなしでデプロイされていました。ネットワーク経由で UI に到達できるクライアントは、以下の操作が可能です:
/mcp への Server Sent Events (SSE) ストリームを開き、資格情報を提示せずに新しい sessionID を受け取る。sessionID を使用して、/mcp_message に POST することで登録済みの任意の MCP ツールを呼び出す。これも未認証のままです。攻撃者は nginx プロセスの完全な制御を獲得します: トラフィックをリダイレクトするためのサーバーブロックの編集、パス読み取りによる TLS 秘密鍵の抽出、nginx のリロードや停止、永続的なバックドアの埋め込みなどが可能です。
// 脆弱なバージョン (2.3.4 より前)
r.GET("/mcp", AuthRequired(), mcpHandler)
r.POST("/mcp_message", mcpMessageHandler) // ミドルウェアが欠落
// 2.3.4 で修正
r.GET("/mcp", AuthRequired(), mcpHandler)
r.POST("/mcp_message", AuthRequired(), mcpMessageHandler)
ルート登録における 1 つの関数呼び出しの欠落が、MCP インターフェースを未認証の RCE ゲートウェイに変えてしまいました。
攻撃者 nginx-ui (<2.3.4)
| 1) GET /mcp (認証なし) |
| --------------------------------------> |
| 2) event: endpoint data: /mcp_message?sessionID=XYZ
| <-------------------------------------- |
| 3) POST /mcp_message?sessionID=XYZ |
| body: JSON-RPC call_tool "nginx_reload" または
| "edit_config {...}" |
| --------------------------------------> |
| 4) 200 OK; ツールが完全な権限で実行される
| <-------------------------------------- |
このリポジトリは意図的に破壊的な操作を一切行いません。検出器は読み取り専用の MCP メソッド (tools/list) のみを使用します。ロジック:
> ステップ 1 nginx-ui をフィンガープリント
> GET / (HTML タイトル、JS バンドル)
> GET /api/settings (nginx-ui キーを参照する JSON)
> ヘッダー / ボディの正規表現でバージョンを抽出
> ステップ 2 /mcp への SSE ストリームを開く
> "endpoint" イベントから最初の sessionID を解析
> ステップ 3 POST /mcp_message?sessionID=<id>
> Body: {"jsonrpc":"2.0","method":"tools/list","params":{}}
> Authorization ヘッダーなし
> ステップ 4 ステータス 200 かつボディにツールマニフェストが含まれる場合: 脆弱
> ステータス 401 / 403 / 404 の場合: 修正済み
> それ以外: 判定不能
tools/list JSON-RPC メソッドは読み取り専用です。MCP サーバーが認識しているツールを列挙するだけで、いずれのツールも呼び出しません。このスクリプトは他のメソッドの POST を拒否し、破壊的なツールのペイロードを決して構築しません。
git clone https://github.com/your-org/CVE-2026-33032-detector.git
cd CVE-2026-33032-detector
python3 --version # 3.9 以降
# サードパーティのパッケージは不要です。
Nmap NSE コンポーネントの場合、nginx-ui-mcpwn.nse をローカルのスクリプトディレクトリにコピーし、スクリプトデータベースを更新します:
cp nginx-ui-mcpwn.nse /usr/share/nmap/scripts/
sudo nmap --script-updatedb
# 単一ターゲット
python3 detect_nginx_ui_mcpwn.py --target https://nginx-ui.internal
# ファイルからの一括スキャン
python3 detect_nginx_ui_mcpwn.py --targets targets.txt --workers 20
# jq へのパイプに適した JSON (NDJSON) 出力
python3 detect_nginx_ui_mcpwn.py --target 10.0.0.5:9000 --json | jq .
コマンドラインリファレンス:
nmap -p 80,443,9000 --script nginx-ui-mcpwn 10.0.0.0/24
nmap -p 443 --script nginx-ui-mcpwn --script-args "nginx-ui-mcpwn.timeout=8" host.example.com
_ _ _ _ _ ___ __ __ ____ ____
| \ | | __ _(_)_ __ __ __ | | | ||_ _| | \/ |/ ___| _ \__ ___ __
| \| |/ _` | | '_ \\ \/ /_____| | | | | | | |\/| | | | |_) \ \ /\ / / '_ \
| |\ | (_| | | | | |> <|_____| |__| | | | | | | | |___| __/ \ V V /| | | |
|_| \_|\__, |_|_| |_/_/\_\ |_____|_||___| |_| |_|\____|_| \_/\_/ |_| |_|
|___/
CVE-2026-33032 nginx-ui MCPwn 検出器 > 非破壊的
[!] 脆弱 https://nginx-ui.internal version=2.3.2 evidence=status=200; body_preview={"jsonrpc":"2.0","id":"...","result":{"tools":[{"name":"edit_config",...
[+] 修正済み https://nginx-ui-patched:9000 version=2.3.4 evidence=status=401; body_preview={"error":"unauthorized"}
[.] nginx-ui ではない https://example.com evidence=fingerprint negative
概要: 3 ターゲット中 1 が脆弱と判定
{"target":"https://nginx-ui.internal","reachable":true,"is_nginx_ui":true,"mcp_endpoint_present":true,"session_id_obtained":true,"mcp_message_unauthenticated":true,"vulnerable":true,"nginx_ui_version":"2.3.2","evidence":"status=200; body_preview=...","error":null}
PORT STATE SERVICE
9000/tcp open http
| nginx-ui-mcpwn:
| status: VULNERABLE
| version: 2.3.2
| session_id: abc123
|_ evidence: tools/list accepted without credentials
CVE-2026-27944 (X-Backup-Security ヘッダーで AES キーを漏洩させる未認証の /api/backup ダウンロード) は MCPwn とシームレスに連鎖します: バックアップアーカイブは node_secret を公開し、33032 の修正が適用された後でも、オペレーターがシークレットをローテーションするまで /mcp への認証に使用できます。
27944 用の併用検出器は、この研究プロジェクトの兄弟ディレクトリにあります。
node_secret、管理者パスワードハッシュ、および nginx-ui プロセスからアクセス可能だった TLS 秘密鍵をローテーションします。/mcp_message ルートに到達する前に認証を強制するリバースプロキシに制限します。このツールは、防御者が認可された環境内の未パッチのインスタンスを特定するのを支援するために公開されています。所有していないシステム、または評価する明示的な許可がないシステムに対して使用しないでください。著者は誤用に対する一切の責任を負いません。
MIT ライセンスの下で公開されています。ファイルごとの通知については、各スクリプトのヘッダーを参照してください。
| フィールド | 値 |
|---|
| CVE ID | CVE-2026-33032 |
| 別名 | MCPwn |
| CVSS 3.1 | 9.8 / Critical (AV:N / AC:L / PR:N / UI:N / S:U / C:H/I:H/A:H) |
| CWE | CWE-306 重要な機能に対する認証の欠如 |
| 影響を受ける製品 | nginx-ui (github.com/0xjacky/nginx-ui) |
| 影響を受けるバージョン | 2.3.4 より前のすべてのバージョン |
| 修正バージョン | 2.3.4 |
| 悪用状況 | 実環境で活発に悪用中 (Picus Security、Recorded Future) |
| Shodan での露出 | インターネットに公開された約 2,689 インスタンス |
| 公開日 | 2026-04-15 |
| MCP ツール | nginx サーバーへの影響 |
|---|
edit_config | 任意のサーバーブロックを書き換え、攻撃者の upstream を挿入 |
reload_nginx | 手動操作なしで攻撃者の設定を適用 |
stop_nginx | サービス拒否 (DoS) |
read_file | マウントされたパスから TLS 秘密鍵や資格情報を外部に持ち出す |
create_cert | 攻撃者の管理下で TLS 証明書を再発行 |
list_backups / download | node_secret とハッシュを含む nginx-ui バックアップ全体を取得 |
| フラグ | 目的 |
|---|
--target | 単一の URL または host[:port] |
--targets | 改行区切りのターゲットファイル |
--timeout | HTTP タイムアウト、デフォルト 10 秒 |
--workers | 一括スキャン用の並行ワーカー数、デフォルト 10 |
--verify-tls | TLS 証明書の検証を強制 (デフォルトではオフ) |
--json | NDJSON を出力、ターゲットごとに 1 レコード |
--no-banner | ASCII バナーを抑制 |