Next.js 中间件鉴权绕过漏洞(CVE-2025-29927)
Next.js 中间件鉴权绕过漏洞(CVE-2025-29927)
描述
Next.js 是一个基于 React 的流行 Web 应用框架,提供服务器端渲染、静态网站生成和集成路由系统等功能。当使用中间件进行身份验证和授权时,Next.js 14.2.25 和 15.2.3 之前的版本存在授权绕过漏洞。
该漏洞允许攻击者通过操作 x-middleware-subrequest
请求头来绕过基于中间件的安全控制,从而可能获得对受保护资源和敏感数据的未授权访问。
目前受影响的NextJS版本:
11.1.4 < Next.js ≤ 13.5.6
14.0 < Next.js < 14.2.25
15.0 < Next.js < 15.2.3
环境搭建
这里使用Vulhub的环境即可
https://github.com/vulhub/vulhub/blob/master/next.js/CVE-2025-29927/README.zh-cn.md
漏洞复现
在没有登录之前,正常访问根目录是这样的,会跳转到登录界面
添加header
x-middleware-subrequest: middleware:middleware:middleware:middleware:middleware
发现绕过了登录验证,直接跳转到了登录后的界面
漏洞分析
Next.js 的中间件(Middleware)设计用于处理全局请求逻辑(如身份验证、请求拦截,假设开发者编写了一个身份验证中间件,其功能是:当用户访问受保护资源时,中间件需向校验 API 发送请求以验证用户权限(如查询数据库或调用外部服务)。
由于 Next.js 是「全栈框架」,所有请求(包括中间件内部发起的 API 请求)均会再次经过中间件本身。这导致以下递归流程:
用户请求 → 中间件A(身份验证) → 发起API请求 → 中间件A再次执行 → 再次发起API请求 → ...
最终引发无限递归,导致服务崩溃或响应超时。
为打破递归循环,Next.js 引入了两项机制:
- 请求标记:
中间件内部发起的请求会自动添加x-middleware-subrequest
头,其值按层级递增(如middleware:middleware:middleware
)。 - 递归终止条件:
当检测到x-middleware-subrequest
头中包含当前中间件标识(如middleware
)的次数超过阈值(默认5次),中间件直接返回空响应,终止递归
主要逻辑在这里
https://github.com/vercel/next.js/blob/v15.2.2/packages/next/src/server/web/sandbox/sandbox.ts
export const run = withTaggedErrors(async function runWithTaggedErrors(params) {
const runtime = await getRuntimeContext(params)
const subreq = params.request.headers[`x-middleware-subrequest`] //
const subrequests = typeof subreq === 'string' ? subreq.split(':') : []
const MAX_RECURSION_DEPTH = 5
const depth = subrequests.reduce(
(acc, curr) => (curr === params.name ? acc + 1 : acc),
0
)
if (depth >= MAX_RECURSION_DEPTH) {
return {
waitUntil: Promise.resolve(),
response: new runtime.context.Response(null, {
headers: {
'x-middleware-next': '1',
},
}),
}
}
当请求头中包含 x-middleware-subrequest
时,中间件会将其值按 :
分割为数组 subrequests
,并检查是否包含当前中间件的 name
(即中间件文件路径)
若 subrequests
中包含当前中间件名称,则 depth
自增。当 depth ≥ 5
时,中间件返回空响应并停止处理。
所以漏洞的利用思路是,只要在发送给next.js的请求中增加一个头**x-middleware-subrequest:**,让其循环5次中间件文件路径,就可以绕过next.js的中间件。如果开发者将校验用户身份的逻辑放在中间件里,就将导致认证绕过漏洞。
中间件文件路径是可以预测的
- 旧版本(≤12.2):中间件文件必须命名为
_middleware.ts
并放置在pages/
目录或其子目录下。例如,若中间件位于/pages/dashboard/_middleware.ts
,则middlewareInfo.name
为pages/dashboard/_middleware
,攻击者只需在请求头中设置x-middleware-subrequest: pages/dashboard/_middleware
即可绕过。 - 新版本(≥12.2):中间件文件更名为
middleware.ts
,位于src/
或根目录。此时,攻击者只需设置x-middleware-subrequest: middleware
或x-middleware-subrequest: src/middleware
即可绕过。
所以最终payload为
x-middleware-subrequest: middleware:middleware:middleware:middleware:middleware
或者
x-middleware-subrequest: src/middleware:src/middleware:src/middleware:src/middleware:src/middleware
修复方案
升级 Next.js 版本
- ≥15.2.3(15.x)
- ≥14.2.25(14.x)
next.js的官方修复如下: 将x-middleware-subrequest请求头删除
参考
https://github.com/vercel/next.js/commit/52a078da3884efe6501613c7834a3d02a91676d2
https://github.com/vulhub/vulhub/blob/master/next.js/CVE-2025-29927/README.zh-cn.md