CVE-2026-42945:潛伏 18 年的 NGINX 高危漏洞

今日披露的 NGINX Rift 漏洞,属于 ngx_http_rewrite_module 中的一個堆緩衝區溢出,自 2008 年起存在於程式碼庫中。攻擊者無需任何認證,只需發送一個構造好的 HTTP 請求,即可令 NGINX worker 程序崩潰(單一請求即可穩定觸發 DoS);若目標系統關閉了 ASLR,則可進一步實現遠端程式碼執行。

觸發條件須同時滿足以下三點:

  1. rewrite 替換字串中使用了無名捕獲組($1$2 等)
  2. 替換字串中包含 ?(即構造了查詢字串)
  3. rewrite 指令後方緊跟另一條 rewriteifset 指令

rewrite 規則在國內運用極為普遍,而 Discuz! X 官方推薦的偽靜態規則全部命中上述三個條件,大量 LNMP 面板、虛擬主機和 VPS 使用者沿用至今:

Note: AMH 面板已經發佈 NGINX 1.30.1。(https://amh.sh/bbs/post-11462-1-1.htm
rewrite ^([^\.]*)/topic-(.+)\.html$ $1/portal.php?mod=topic&topic=$2 last;
rewrite ^([^\.]*)/article-([0-9]+)-([0-9]+)\.html$ $1/portal.php?mod=view&aid=$2&page=$3 last;
rewrite ^([^\.]*)/forum-(\w+)-([0-9]+)\.html$ $1/forum.php?mod=forumdisplay&fid=$2&page=$3 last;
rewrite ^([^\.]*)/thread-([0-9]+)-([0-9]+)-([0-9]+)\.html$ $1/forum.php?mod=viewthread&tid=$2&extra=page%3D$4&page=$3 last;
rewrite ^([^\.]*)/group-([0-9]+)-([0-9]+)\.html$ $1/forum.php?mod=group&fid=$2&page=$3 last;
rewrite ^([^\.]*)/space-(username|uid)-(.+)\.html$ $1/home.php?mod=space&$2=$3 last;
rewrite ^([^\.]*)/blog-([0-9]+)-([0-9]+)\.html$ $1/home.php?mod=space&uid=$2&do=blog&id=$3 last;
rewrite ^([^\.]*)/archiver/(fid|tid)-([0-9]+)\.html$ $1/archiver/index.php?action=$2&value=$3 last;
rewrite ^([^\.]*)/([a-z]+[a-z0-9_]*)-([a-z0-9_\-]+)\.html$ $1/plugin.php?id=$2:$3 last;


9 條規則全部滿足觸發條件:

無名捕獲組($1$2 等)替換字串含 ?後跟 rewrite/if/set

溢出量的大小取決於捕獲變數的內容,漏洞路徑是 ngx_http_script_copy_capture_code 透過 ngx_escape_uriNGX_ESCAPE_ARGS 模式)對捕獲變數重新跳脫,+%& 各從 1 byte 膨脹為 3 bytes。捕獲組的正則越寬鬆,攻擊者能製造的溢出量就越大:

  • 最危險:topic-(.+)space-…-(.+) 的捕獲組是 .+,攻擊者可任意填入 +%&,溢出量完全可控
  • 相對難利用:thread-([0-9]+) 的捕獲組限定為純數字,無法觸發字元膨脹

臨時修復:將無名捕獲組改為具名捕獲組

無需修改任何業務邏輯,只需在每個捕獲組的括號內加上 ?<名稱>,並在替換字串中改用 $名稱 引用,即可繞過存在漏洞的程式碼路徑。以第一條規則為例:

修改前
rewrite ^([^.]*)/topic-(.+).html$ $1/portal.php?mod=topic&topic=$2 last;

修改後
rewrite ^(?<base>[^.]*)/topic-(?<slug>.+).html$ $base/portal.php?mod=topic&topic=$slug last;

Discuz! X 完整修復版本:

rewrite ^(?<base>[^\.]*)/topic-(?<slug>.+)\.html$                                        $base/portal.php?mod=topic&topic=$slug last;
rewrite ^(?<base>[^\.]*)/article-(?<aid>[0-9]+)-(?<page>[0-9]+)\.html$                  $base/portal.php?mod=view&aid=$aid&page=$page last;
rewrite ^(?<base>[^\.]*)/forum-(?<fid>\w+)-(?<page>[0-9]+)\.html$                       $base/forum.php?mod=forumdisplay&fid=$fid&page=$page last;
rewrite ^(?<base>[^\.]*)/thread-(?<tid>[0-9]+)-(?<page>[0-9]+)-(?<extra>[0-9]+)\.html$  $base/forum.php?mod=viewthread&tid=$tid&extra=page%3D$extra&page=$page last;
rewrite ^(?<base>[^\.]*)/group-(?<fid>[0-9]+)-(?<page>[0-9]+)\.html$                    $base/forum.php?mod=group&fid=$fid&page=$page last;
rewrite ^(?<base>[^\.]*)/space-(?<type>username|uid)-(?<val>.+)\.html$                  $base/home.php?mod=space&$type=$val last;
rewrite ^(?<base>[^\.]*)/blog-(?<uid>[0-9]+)-(?<id>[0-9]+)\.html$                       $base/home.php?mod=space&uid=$uid&do=blog&id=$id last;
rewrite ^(?<base>[^\.]*)/archiver/(?<action>fid|tid)-(?<value>[0-9]+)\.html$            $base/archiver/index.php?action=$action&value=$value last;
rewrite ^(?<base>[^\.]*)/(?<plug>[a-z]+[a-z0-9_]*)-(?<parg>[a-z0-9_\-]+)\.html$        $base/plugin.php?id=$plug:$parg last;

修改後驗證並重載:

nginx -t && nginx -s reload

受影響版本

NGINX Open Source 0.6.27 – 1.30.0(詳見 F5 官方公告
上述設定改法僅作為無法立即升級時的臨時緩解措施。PoC 已公開發布於 DepthFirstDisclosures/Nginx-Rift。

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

这个站点使用 Akismet 来减少垃圾评论。了解你的评论数据如何被处理