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

漏洞复现

在没有登录之前,正常访问根目录是这样的,会跳转到登录界面

image-20250324201836695

添加header

x-middleware-subrequest: middleware:middleware:middleware:middleware:middleware

发现绕过了登录验证,直接跳转到了登录后的界面

image-20250324202038199

漏洞分析

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.namepages/dashboard/_middleware,攻击者只需在请求头中设置 x-middleware-subrequest: pages/dashboard/_middleware 即可绕过。
  • 新版本(≥12.2):中间件文件更名为 middleware.ts,位于 src/ 或根目录。此时,攻击者只需设置 x-middleware-subrequest: middlewarex-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请求头删除

image-20250324211355033

参考

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

https://github.com/vulhub/vulhub/blob/master/next.js/CVE-2025-29927/README.zh-cn.md

https://nextjs.org/blog/cve-2025-29927