免责声明
本文所述漏洞复现方法仅供安全研究及授权测试使用;
任何个人/组织须在合法合规前提下实施,严禁用于非法目的;
作者不对任何滥用行为及后果负责,如发现新漏洞请及时联系厂商并遵循漏洞披露规则。
漏洞原理
Next.js 是一个基于 React 的流行 Web 应用框架,提供服务器端渲染、静态网站生成和集成路由系统等功能,它有自己的中间件(middleware)。当使用中间件进行身份验证和授权时,Next.js 14.2.25 和 15.2.3 之前的版本存在授权绕过漏洞。
该漏洞允许攻击者通过操作 x-middleware-subrequest
请求头来绕过基于中间件的安全控制,从而可能获得对受保护资源和敏感数据的未授权访问。
进一步的漏洞原理分析见后文。
影响版本
- 对于 Next.js 15.x,version < 15.2.3
- 对于 Next.js 14.x,version < 14.2.25
- 对于 Next.js 13.x,version < 13.5.9
- 对于 Next.js 12.x,version < 12.3.5
漏洞利用
一、FOFA
fofa语法:
app="next.js"
找一个真实的网站进行测试,如果不知道测试网站的什么路径,可以尝试先找进入就跳转登录界面的网站,尝试访问他的根路径或者/dashboard路径
二、漏洞利用
找到一个网站,直接访问根目录会重定向到登陆界面,直接访问注册功能也会重定向到登陆界面,未授权不允许注册

而加上x-middleware-subrequest
头,并将Value设置为middleware:middleware:middleware:middleware:middleware
之后,再次访问注册功能

成功绕过授权,访问到注册界面
漏洞复现
vulhub已有环境,也可以通过vulhub进行复现
一、环境搭建
git clone https://github.com/vulhub/vulhub.git
- 进入到漏洞目录下
cd /path/to/vulhub/next.js/CVE-2025-29927
- 执行命令启动一个基于 Next.js 15.2.2 的存在漏洞的应用:
docker compose up -d
- 访问3000端口,可以看到环境搭建成功,输入默认凭据
admin:password
,可以登录成功并访问仪表盘

二、漏洞复现
仪表盘在根路径下,如果在没有合法凭据的情况下直接访问根路径,将会被重定向到登录页面

在请求中添加 x-middleware-subrequest
请求头,其值为
middleware:middleware:middleware:middleware:middleware
- 或
src/middleware:src/middleware:src/middleware:src/middleware:src/middleware

成功绕过身份验证检查,注意右上角,与之前直接登录是有区别的,现在并不是 admin 的身份
漏洞原理深入分析
漏洞代码分析
(一) 旧版本代码 - 12.2之前

该框架的旧版本(v12.0.7)存在一段代码
- 当 next.js 应用程序使用中间件时,将使用
runMiddleware
函数 runMiddleware
函数会检索x-middleware-subrequest
头的Value- 使用Value来判断是否需要应用中间件
- 具体而言:
x-middleware-subrequest
头的Value被拆分并使用:
作为分隔符创建一个列表- 检查此列表是否包含
middlewareInfo.name
值
- 检查此列表是否包含
这意味着,如果我们将有正确Value的x-middleware-subrequest
头添加到请求中,中间件将被完全忽略,并且请求将通过转发NextResponse.next()
并成功访问路径,而中间件不会对其产生任何影响。
为了成功未授权访问,x-middleware-subrequest
的Value必须包含middlewareInfo.name
,但它是什么呢?
1. middlewareInfo.name
middlewareInfo.name
的值完全可以猜测,它只是中间件所在的路径。要知道这一点,有必要快速了解一下旧版本中中间件的配置方式。
首先,在版本 12.2之前,该文件必须命名为 _middleware.ts
。
此外,app
router 仅在 Next.js 版本 13 中发布。此前唯一存在的 router 就是 pages
router ,因此该文件必须放在pages
文件夹中(router specific)。
这些信息使我们能够推断出中间件的确切路径,从而猜测出x-middleware-subrequest
头的值,后者仅由目录名称和文件名称组成,遵循当时的约定,以下划线开头:
x-middleware-subrequest: pages/_middleware
这样便可以完全绕过中间件,从而绕过任何基于它的保护系统
但还需要考虑执行顺序问题
2. 执行顺序
12.2 之前的版本允许嵌套路由将一个或多个_middleware
文件放置在树中的任何位置(从pages
文件夹开始),并且具有执行顺序

因此,要获得对/dashboard/panel/admin
(受中间件保护的)的访问权限,关于middlewareInfo.name
的值有三种可能性,因此 x-middleware-subrequest
的值也有三种可能性:
pages/_middleware
pages/dashboard/_middleware
pages/dashboard/panel/_middleware
(二) 新版本代码 - 12.2之后
1. Payload
从版本 12.2 开始,该文件不再包含下划线,而必须简单地命名为middleware.ts
此外,它不能再位于 pages
文件夹中
考虑到这一点,从版本 12.2 开始的第一个版本的有效Payload非常简单
x-middleware-subrequest: middleware
2. /src 目录
还应该考虑到 Next.js 提供了创建/src
目录的可能性
除了在项目根目录中放置特殊的 Next.js 应用程序或页面目录外,Next.js 还支持将应用程序代码放置在 src 目录下的常见模式。Next.js文档
在这种情况下,有效Payload将是:
x-middleware-subrequest: src/middleware
因此,无论路径有多少层,总共只有两种可能性
(三) 新版本逻辑变动代码
1. 代码分析
在较新的版本(v15.1.7)中,逻辑又略有改变,看一下这段代码

常量depth的值必须大于或等于常量MAX_RECURSION_DEPTH
的值 (即5
)
每当subrequests
(即用:
分隔的Value的列表)中的其中一个Value等于中间件路径即params.name
时,常量depth就会加 1
而params.name
跟之前一样,只有两种可能性:middleware
/src/middleware
因此,我们只需要在请求中添加以下标头/值即可绕过中间件:
x-middleware-subrequest: middleware:middleware:middleware:middleware:middleware
或者
x-middleware-subrequest: src/middleware:src/middleware:src/middleware:src/middleware:src/middleware
2. 这段代码原本是用来做什么的?
这是为了防止递归请求陷入无限循环。
修复代码分析
漏洞已修复,分析一下官方修改了哪些内容
(一) 新增x-middleware-subrequest-id头
packages/next/src/server/lib/router-server.ts

packages/next/src/server/web/sandbox/context.ts

(二) 对x-middleware-subrequest-id
进行校验
packages/next/src/server/lib/server-ipc/utils.ts

防御措施
升级到不受影响版本
- CVE-2025-29927 - GitHub Advisory Database
- Next.js and the corrupt middleware: the authorizing artifact
- NVD - CVE-2025-29927
- CVE 2025 29927 Nextjs Auth Bypass - chestnut's blog
- 漏洞通告 | Next.js middleware 权限绕过漏洞
- Update middleware request header by ijjk · Pull Request #77201 · vercel/next.js
- CVE-2025-29927 Next.js 中间件权限绕过漏洞复现 - CVE-柠檬i - 博客园