Next.js 中间件鉴权绕过漏洞 (CVE-2025-29927)
真爱和自由 历史精选 1652浏览 · 2025-03-25 05:23

Next.js 中间件鉴权绕过漏洞 (CVE-2025-29927)

前言

最近 next.js 也是爆出了一个非常严重的漏洞,正好 p 神知识星球通知已经给了更方便搭建的环境,有了环境就可用来分析分析这个漏洞,看看怎么个事了



image.png
图片加载失败


漏洞描述

CVE-2025-29927 是 Next.js 框架中发现的一个严重授权绕过漏洞。该漏洞允许攻击者通过伪造特定的 HTTP 请求头,绕过中间件中的授权检查,从而未经授权地访问受保护的资源。此问题影响了使用“next start”命令并设置“output: 'standalone'”的自托管 Next.js 应用程序。

Next.js 使用内部头字段“x-middleware-subrequest”来防止递归请求导致的无限循环。攻击者可以通过在请求中伪造该头字段,跳过中间件的执行,从而绕过关键的安全检查,例如授权 Cookie 验证。

受影响的版本

Next.js 15.x < 15.2.3 Next.js 14.x < 14.2.25 Next.js 13.x < 13.5.9

影响范围

使用中间件的自托管 Next.js 应用程序(next start with output: standalone) 依赖 Middleware 进行身份验证或安全检查的应用程序,稍后不会在应用程序中进行验证

环境搭建

使用 p 神的https://github.com/vulhub/vulhub/blob/master/next.js/CVE-2025-29927/README.zh-cn.md

拉取镜像即可

还可用参考https://github.com/aydinnyunus/CVE-2025-29927

克隆此存储库 安装依赖项:npm install 构建应用程序:npm run build 在生产模式下启动应用程序: node .next/standalone/server.js 测试漏洞:node exploit-test.js

漏洞复现

其实漏洞复现其实就是非常的简单了

首先我们正常访问我们一个页面

图片加载失败


是一个需要登录的页面

但是如果我们加入 x-middleware-subrequest 请求头

value 为 middleware:middleware:middleware:middleware:middleware

五个

图片加载失败


可用看到已经成功绕过了权限鉴定,来到了登录后的页面

成功的payload

漏洞分析

我们重点分析就是根据我们的 paylaod,聚焦于我们的请求头了

在 Next.js 中,中间件(Middleware)是一种强大的工具,可以用于在请求到达 API 路由或页面组件之前执行全局逻辑,比如身份验证、请求拦截、重定向等。

参考https://github.com/aydinnyunus/CVE-2025-29927



而我们的x-middleware-subrequest 是 Next.js 框架内部使用的一个特殊 HTTP 请求头,主要用于标识和处理内部子请求,防止中间件的递归调用。



Next.js 的中间件(Middleware)可以重写(rewrite)、重定向(redirect)或修改请求。

当中间件重写请求路径(例如 /api/protected 被重写为 /api/auth-check),Next.js 服务器会重新触发新的请求,这个请求仍然会经过中间件。

如果没有 x-middleware-subrequest 进行标识,新的请求会再次触发相同的中间件,导致无限递归调用,最终造成服务器崩溃或请求死循环。

比如

用户请求 https://example.com/protected

中间件发现用户未登录,重写到 https://example.com/api/auth-check

服务器接收到新请求 https://example.com/api/auth-check,但它又会触发相同的中间件

中间件继续重写,导致死循环(无限递归)💀

如果我们使用了 x-middleware-subrequest 请求头

用户请求 https://example.com/protected

中间件重写请求到 https://example.com/api/auth-check

Next.js 自动在新请求上添加 x-middleware-subrequest

中间件检测到 x-middleware-subrequest 存在,跳过处理,避免递归

api/auth-check 正常执行,返回结果



老版本

在老版本(如 12.2 以下)时

next.js/packages/next/server/next-server.ts 如果我们有中间件,那么就会调用 runMiddleware 函数

处理的主要逻辑也是在这里

匹配 URL,查找相应的中间件(Middleware)。

防止递归调用,通过 x-middleware-subrequest 标记已经执行的中间件,避免无限循环。

执行匹配的中间件,并收集其响应。

根据执行结果处理请求,决定是继续执行下一个中间件,还是返回最终的 HTTP 响应。

我们观察解析我们的 header 部分

这里 x-middleware-subrequest 的值是一个字符串,通过 : 进行拆分,得到已执行中间件的列表。

我们观察对列表的处理

如果 subrequests 数组中已经包含 middlewareInfo.name,那么这个中间件直接跳过,返回 NextResponse.next(),请求会继续前进,完全绕过该中间件的执行。

所以我们的绕过思路就出来了

伪造的 x-middleware-subrequest 头部,并让它包含目标中间件的名称,从而欺骗 runMiddleware 认为该中间件已经执行过,导致其被跳过。



当然如何知道中间件的名称也是非常重要的

首先中间件必须命名为 ` _middleware.ts

必须位于 pages/ 目录下(因为 App Router 在 13 版本才推出)

所以我们可用轻易推测出我们的中间件名称为

图片加载失败


高版本绕过

在 cve 版本中

我们看到代码

为了防止中间件被反复调用导致无限循环

加入了上面代码的逻辑 首先还是一样解析它的值

subrequests 数组存储了所有子请求的名称,subreq.split(':') 将 x-middleware-subrequest 请求头中的值拆分成一个数组。

然后开始计算中间件出现的次数,depth 计算出当前中间件在请求头中的出现次数

如果递归深度超过了 MAX_RECURSION_DEPTH(5),中间件就会停止执行,返回一个包含 x-middleware-next: 1 头部的响应,允许请求继续执行并绕过当前中间件。

那么目前就是寻找中间件名称了

而在高版本,对中间件的文件又要了要求

中间件文件更名为 middleware.ts

可以参考复现 cve 的各种环境

https://github.com/lem0n817/CVE-2025-29927

图片加载失败




所以我们可以使用如下 payload

连续五个 middleware 名称

当然参考https://nextjs.org/docs/app/building-your-application/configuring/src-directory

除了在项目的根目录中拥有特殊的 Next.js app 或 pages 目录外,Next.js 还支持将应用程序代码放在 src 目录下的常见模式。

这将应用程序代码与项目配置文件分开,后者主要位于项目的根目录中,而某些个人和团队更喜欢这样做。

要使用 src 目录,请将 app Router 文件夹或 pages Router 文件夹分别移动到 src/app 或 src/pages 目录下。

可以使用如下 payload

图片加载失败


漏洞修复

其实漏洞修复官方非常的暴力

https://github.com/vercel/next.js/commit/52a078da3884efe6501613c7834a3d02a91676d2

图片加载失败


直接删除了

参考https://github.com/lem0n817/CVE-2025-29927

https://zhero-web-sec.github.io/research-and-things/nextjs-and-the-corrupt-middleware

https://github.com/vulhub/vulhub/blob/master/next.js/CVE-2025-29927

1 条评论
某人
表情
可输入 255
Endlessparadox
2025-03-27 02:23 0 回复
666,学习了