藏了 13 年的 NGINX “上古漏洞” 一个问号就能远程拿下你的服务器
NGINX中一个存在了13年的漏洞(CVE-2026-42945),攻击者只需要向暴露的 NGINX 服务器发送特定的 HTTP 请求就有可能远程拿下服务器,受影响版本从0.6.27到1.30.0(基本上去全覆盖了)

NGINX CVE-2026-42945 高危漏洞介绍
- NGINX官方原话是这样的
This vulnerability exists when the rewrite directive is followed by a rewrite, if, or set directive and an unnamed Perl-Compatible Regular Expression (PCRE) capture (for example, $1) with a replacement string that includes a question mark (?). An unauthenticated attacker along with conditions beyond its control can exploit this vulnerability by sending crafted HTTP requests.
- 翻译一下
NGINX Plus和NGINX开源版本的
ngx_http_rewrite_module模块存在安全漏洞。当rewrite指令后接另一条rewrite、if或set指令,且使用包含问号(?)的未命名Perl兼容正则表达式(PCRE)捕获组(例如$1)作为替换字符串时,可能触发此漏洞。未经身份验证的攻击者可通过发送特制HTTP请求,在满足特定外部条件时利用该漏洞,导致NGINX工作进程发生堆缓冲区溢出并引发服务重启。此外,在禁用地址空间布局随机化(ASLR)的系统中,攻击者可能实现代码执行。
三步排查你的服务器是否存在 NGINX CVE-2026-42945 漏洞
- 看下Nginx版本:
nginx -v如果返回的版本号低于1.30.1那基本就是带漏洞的版本了。 - 看下你的操作系统是否开启了地址空间布局随机化(ASLR):
cat /proc/sys/kernel/randomize_va_space如果结果是2就是开了内存空间随机化,这样遇到攻击 Nginx 会崩溃,而不是触发任意命令执行。 - 检查所有包含
?的rewrite指令,看看它们是否引用了$1,$2。
你可以用这个命令批量检索一下grep -rInP 'rewrite\s+.*\$[0-9].*\?|if\s+\(|set\s+\$' /etc/nginx/ /www/server/panel/vhost/nginx/ /usr/local/nginx/conf/ 2>/dev/null)
命令适配了系统原生,编译,宝塔面板的配置文件路径。

NGINX CVE-2026-42945 漏洞配置与攻击示例
漏洞背景
官方的漏洞说明有点绕口,说人话就是
当你的NGINX(以及基于NGINX的软件,比如NGINX WAF、F5 WAF)版本号在0.6.27~1.30.0之间。
满足以下条件时可能被触发:
- 配置里使用了
rewrite,且其后跟随另一个rewrite、if或set - 在替换字符串中使用未命名的
PCRE 捕获组(如 $1、$2) - 替换字符串中包含问号(
?)
攻击者可利用此漏洞通过特制 HTTP 请求触发堆缓冲区溢出,导致 NGINX 工作进程重启,如果没有 启用 ASLR 时则可能执行任意代码)。
示例配置(存在漏洞的配置段)
# 会触发 CVE-2026-42945 的高危配置
server {
listen 80;
server_name test.local;
location /vulnerable {
# 条件1: rewrite 指令,正则捕获路径部分,替换字符串包含 "?" 和 $1
rewrite ^/(\w+)/old$ /$1?new=1 break;
# 条件2: 紧跟另一个指令(这里用 if 示例,也可用 rewrite 或 set)
if ($arg_new = "1") {
set $flag "triggered";
}
return 200 "Config may be vulnerable";
}
}
- 正则
^/(\w+)/old$捕获了\w+作为$1。 - 替换字符串
/$1?new=1中同时包含$1和问号(?)。 - 后续紧跟了 if 指令。
攻击示例:
攻击者可能发送如下请求,通过精心构造的 $1值(如超长字符串)触发溢出:
GET /aaaaaaaa...(大量字符)...aaa/old HTTP/1.1
Host: test.local
如果系统关闭了 ASLR(地址空间布局随机化),攻击者只需要精心构造的 $1 内容,将恶意代码写入溢出的堆内存空间,就能实现执行任意命令。
如何修复 NGINX CVE-2026-42945 漏洞
升级版本
升级自然是最有效的解决方法。将 NGINX 升级到 1.31.0、1.30.1 或更高版本 (一般咱们用双数版本号的稳定版,当然单数的主线版也还行)
无法升级怎么办?
如果你因为这样那样的原因无法升级,比如你的系统版本很老了,新版Nginx无法安装等情况
那就想办法破坏漏洞触发的必要条件。修改一下逻辑(以上边的配置文件为例子):
方法 1:使用“命名捕获组”
因为漏洞仅针对 $1, $2 这种未命名变量。如果给捕获组起个名字,就规避溢出逻辑。
location /vulnerable {
# 将 (\w+) 改为 (?<my_path>\w+)
rewrite ^/(?<my_path>\w+)/old$ /$my_path?new=1 break;
if ($arg_new = "1") {
set $flag "triggered";
}
return 200 "Config is now safer";
}
方法 2:使用中间变量转存
也可以先通过 set 指令将捕获到的内容转存到一个自定义变量中。这样的话 rewrite 指令执行时,引用的就是一个命名后的普通的变量了。(不推荐啊,这样改工作量太大)
location /vulnerable {
# 1. 先用 if 或另一个 rewrite 捕获并存入自定义变量
if ($uri ~* "^/(?<temp_var>\w+)/old$") {
}
# 2. 引用的捕获组是 $temp_var,不是未命名的 $1 了
rewrite ^ /${temp_var}?new=1 break;
if ($arg_new = "1") {
set $flag "triggered";
}
return 200 "Config is now safer";
}
最后是个吐槽:其实最近本来是打算写一个关于个人博客运营的文章的,结果写的太久,在各种摸鱼中,反倒是写了两篇关于漏洞的资讯:joy:


obaby
2026-05-14 17:39
nginx -v
nginx version: openresty/1.27.1.2
啊,这,我的貌似都低于这个版本