HOME > リナックスマスター.JP 公式ブログ > Linux情報・技術・セキュリティ > nginxに18年潜伏したCVE-2026-42945|Apache mod_rewrite世代のサーバー管理者が踏みやすい罠と設計レベルの回避策
この記事の監修:宮崎智広(Linux実務・教育歴20年以上・受講者3,100名超)
2008年(v0.6.27)から混入していたものを、depthfirst の自動コード解析が 6時間で掘り当てた、というのが事件の本筋です。
ただニュースの多くは「世界Webサーバーの3割が危険」「未認証RCE」というショッキングな見出しで止まっています。Apache mod_rewrite の時代から20年以上 Linux サーバーの現場を触ってきた立場から見ると、もっと根が深い問題がここにあります。
それは 「$1 / $2 思考のまま書いた rewrite が踏みやすい構造になっている」ということ。Apache mod_rewrite の発想で nginx.conf を書いた人が、知らないうちに地雷を設置していた可能性が高い。
この記事のポイント
- CVE-2026-42945 は ngx_http_rewrite_module のヒープバッファオーバーフロー。CVSS v3.1=8.1 HIGH、CVSS v4.0=9.2 CRITICAL。
- 発火条件は3つAND。「rewrite の置換文字列に ? を含む」「unnamed PCRE capture($1, $2 等)を使う」「続けて if / set / rewrite が同一スコープにある」。1つ欠けると発火しない。
- 影響は NGINX Open Source 0.6.27 ~ 1.30.0。修正は 1.30.1 / 1.31.0。NGINX Plus は R32 P6 / R36 P4。
- 暫定回避策は 「unnamed capture を named capture(?<name>...)に書換える」これだけ。F5公式と depthfirst の見解が一致。
- Apache mod_rewrite には named capture という発想がそもそもない。Apacheから nginx に移行した管理者ほどこの罠を踏みやすい構造的理由がある。
「このままじゃマズい」と感じていませんか?
参考書を開く気力もない、同年代に取り残される不安——
でも安心してください。プロのエンジニアはコマンドを暗記していません。
「現場で使える型」を効率よく使いこなしているだけです。
でも安心してください。プロのエンジニアはコマンドを暗記していません。
「現場で使える型」を効率よく使いこなしているだけです。
図解60P/登録10秒/解除も3秒 /
詳細はこちら
CVE-2026-42945 の正体(2パス処理の非対称性)
長さ計算とコピーで「?」の扱いが食い違う
NGINX Rift の核心は ngx_http_script.c の2パス処理にある非対称性です。nginx の rewrite エンジンは置換結果のバッファを確保する前に最終文字列長を計算します。この計算パスで使うローカルエンジンle の is_args フラグが 0 のまま。これが地雷の起点です。- 第1パス(長さ計算):
le.is_args = 0。置換文字列内の?の特別扱い(args 領域開始マーカー)が発火しない。エスケープなしの素のサイズで長さ算出。 - 第2パス(実コピー): 実行エンジン側は
e->is_args = 1。?以降を args 領域とみなし/や?を %2F や %3F に3バイト展開してコピー。 - 結果: 確保サイズ < 実書込みサイズ。ヒープが攻撃者制御のURI由来データで溢れる。
/ を仕込むだけでオーバーフロー幅をコントロールできてしまう。「unnamed capture」だけがなぜ危険なのか
ここが今回の記事で一番伝えたいところです。nginx の rewrite には2種類のキャプチャ参照があります。- unnamed capture:
(.*)+$1,$2の位置参照。 - named capture:
(?<path>.*)+$pathの名前付き参照。PCRE 拡張記法。
nginx.conf 内で
$1 を使っている rewrite が1つでも残っていたら、今回の脆弱性ラインに片足を突っ込んでいることになります。残り2条件(置換に ? + if/set/rewrite 連鎖)が揃えば即発火。3条件AND を実例で読む
発火する典型例
公開資料を元に、典型的な脆弱パターンを構造だけ書きます。実際の攻撃ペイロードは伏せます。脆弱な nginx.conf 例:
location /api/ {
rewrite ^/api/(.*)$ /internal?migrated=true;
set $original_endpoint $1;
}- 条件1:
rewriteの置換文字列に?がある(?migrated=true) - 条件2:
(.*)という unnamed capture を$1で参照 - 条件3: 同じ location スコープに
setが続く
安全パターン(named capture で書換える)
F5公式と depthfirst が共通で案内している暫定回避策が、unnamed capture を named capture に書換えるというシンプルな対応です。安全な書換え例:
location /api/ {
rewrite ^/api/(?<path>.*)$ /internal?migrated=true;
set $original_endpoint $path;
}変えたのは2箇所だけ。
(.*) を (?<path>.*) に、$1 を $path に。これで nginx 内部のキャプチャ参照テーブルが位置参照から名前付き変数に分岐し、is_args フラグの非対称性が露出しません。named capture は3ヶ月後の自分が読み直したときの可読性も明確に上がります。「
$1 って何だっけ」を毎回正規表現から辿り直さずに済む。
Apache mod_rewriteから来た管理者が踏みやすい理由
mod_rewrite には named capture の発想がない
Apache HTTP Server の mod_rewrite を長く触ってきた人なら気づくはずです。Apache のRewriteRule の後方参照は $1~$9 の位置参照しか存在しません。名前付きキャプチャを書く文法そのものが mod_rewrite には用意されていない。だから Apache 時代のクセで rewrite を書くと、自然と
$1 / $2 を選ぶ。これは好みではなく、Apache の文法がそうしか書かせなかった、という来歴の問題です。そのまま nginx に移行すると、
$1 思考のまま nginx.conf を書きます。nginx には named capture が用意されているのに、選択肢として頭に浮かばない。これが、Apache から nginx に移行したサーバーで CVE-2026-42945 のラインに乗りやすい構造的理由です。私自身、長く Apache 中心で動かしていた時期があって、初めて nginx を本番投入したときは
$1 ばかり書いていました。今回の脆弱性公開を受けて自分の管理サーバーを点検したら、案の定 $1 のオンパレード。設計上の地雷を方々に埋めていた、という反省があります。nginx の「If is Evil」と Apache の RewriteCond 文化
3条件のひとつ「同一スコープに if / set / rewrite が続く」も、来歴を知ると見方が変わります。nginx 公式 Wiki には 「If is Evil」という有名な記述があります。
location 以外で if を使うと予期しない挙動になりやすい、という長年知られた注意点。にもかかわらず Apache 出身者は .htaccess のノリで if を多用します。Apache では RewriteCond + RewriteRule の組み合わせが標準で、「条件分岐込みでURL書換えする」発想が体に染み付いているからです。今回の脆弱性条件はその習慣のド真ん中を撃ち抜いてきます。
影響バージョンとパッチ提供状況
影響範囲は 0.6.27 ~ 1.30.0
| 製品 | 影響バージョン | 修正バージョン |
|---|---|---|
| NGINX Open Source | 0.6.27 ~ 1.30.0 | 1.30.1 / 1.31.0 以降 |
| NGINX Plus | R36 P3 以前 / R32 P5 以前 | R36 P4 / R32 P6 |
2008年(v0.6.27)以降のすべてが影響対象、というのが異例な点です。18年分の歴史を丸ごと巻き込んでいます。
ディストロのパッケージ対応
| ディストロ | 対応状況 | 対応バージョン |
|---|---|---|
| AlmaLinux 8 | 提供済(5/14 22:41 UTC) | nginx-1.14.1-9.el8.10.alma.1 |
| AlmaLinux 9 | 提供済 | nginx-1.20.1-24.el9_7.2.alma.2 |
| AlmaLinux 10 | 提供済 | nginx-1.26.3-2.el10_1.1.alma.1 |
| Red Hat(RHEL) | 5/14時点で未提供 | - |
| NGINX 公式リポジトリ | 提供済 | 1.30.1 / 1.31.0 |
ディストロのパッケージ版 nginx はバージョン番号が古いままパッチだけバックポートされる運用です。
nginx -v で 1.14.1 と出ても、パッケージのリビジョン番号(-9.el8.10.alma.1 部分)が上がっていれば塞がっています。バージョン番号だけで「うちは関係ない」と判断するのは誤り。
運用者がいま打つべき手順
該当 rewrite を grep で炙り出す
商用サイトで再起動の調整が必要な場合は、まず該当 rewrite が自分の nginx.conf にあるかを確認するのが先です。近似検出は次の grep でできます。grep -rn "rewrite.*\\\$[0-9]" /etc/nginx/unnamed capture を参照している rewrite 行を全部拾います。ヒットした行の置換文字列に
? が含まれ、同じ location/server スコープに if / set / rewrite が続いていれば、3条件AND成立候補です。ヒットゼロなら今回の脆弱性に対する実害はありません。パッチを当てる(AlmaLinux 例)
sudo dnf clean metadata
sudo dnf upgrade nginx
sudo systemctl restart nginxRHEL は 5/14時点で公式リポジトリ提供を待つ形。NGINX 公式リポジトリ利用環境は
1.31.0 または 1.30.1 以降に上げてください。パッチ後も「unnamed capture 撲滅」をやる価値
ここが今回の記事で最後に伝えたい部分です。パッチを当てれば CVE-2026-42945 単体は塞がります。ですが unnamed capture を多用する rewrite 設計そのものは見直す価値があります。- 今回の
is_args フラグ非対称性は18年見つかりませんでした。同種の境界条件バグが他の rewrite 関連モジュールに潜んでいる可能性はゼロではない。
- named capture は変数名で意味がわかるため、保守コストが下がる。
- F5 公式の暫定回避策が named capture 書換えという事実は、ベンダーが「named は当面安全」と判断している証拠。20年以上 Linux サーバーの現場にいますが、「ベンダー回避策が設計レベルの書き直し」という出方をした脆弱性は珍しいです。多くは「特定モジュール無効化」「特定ヘッダを弾く」のような外科的対応で済む。今回の named capture 推奨は、F5 が rewrite の歴史的な設計負債を一緒に整理しに来ている、と読むのが筋がいい。
週末1日かけて自分の nginx.conf を grep して、
$1 / $2 を $path / $slug のような意味のある名前に書換える。これは脆弱性対応というより、10年後も読める nginx.conf に育てる作業です。Linux サーバー運用の現場感覚を、もっと体系的に学びたい方へ。
リナックスマスター.JP では、現役の Linux 管理者向けに 実務で詰まりやすい設計判断を扱うメール教育とセミナーを開催しています。今回の rewrite 設計のような「公式ドキュメントに書かれていない、現場の判断軸」を、20年以上の運用経験を元にお伝えしています。
暗記不要・1時間後にはサーバーが動く
3,100名以上が実践した「型」を無料で公開中
プロのエンジニアはコマンドを暗記していません。
「現場で使える型」を効率よく使いこなしているだけです。
その「型」を図解60Pにまとめた入門マニュアルを、完全無料でプレゼントしています。
登録10秒/合わなければ解除3秒 / 詳細はこちら
Linux無料マニュアル(図解60P)
名前とメールで30秒登録
- 前のページへ:Ubuntu運用者が今日実行するapt自動更新とPro Livepatchの判断----22.04 / 24.04 / 26.04の差分整理
- この記事の属するカテゴリ:Linux情報・技術・セキュリティへ戻る

無料メルマガで学習を続ける
Linuxの実践スキルをメールで毎週お届け。
登録は1分、解除もいつでも可。
登録無料・いつでも解除できます