Next.js 极高危漏洞分析以及解决方案(CVE-2025-29927)

4 分钟
grok-3-fast-beta Logo

AI 摘要 (由 grok-3-fast-beta 生成)

本文分析了Next.js框架中的一个严重漏洞(CVE-2025-29927),攻击者可通过伪造x-middleware-subrequest头部绕过授权检查。漏洞影响版本为11.1.4至15.2.3,已在14.2.25和15.2.3修复。官方通过唯一ID验证增强了中间件安全性,文章还提供了临时修复方案,并强调中间件不应作为唯一防线,需定期测试和最小权限设计。

2.83s
~5041 tokens

早上在逛推的时候突然发现几个暴躁老哥又在怒喷 nextjs,怒喷前端写后端,哈哈哈... 我真是x了 🤣 (围观的我真的害怕极了😱)


研究下这个漏洞产生的原因

1. 漏洞背景

Next.js是一款基于React构建全栈应用的框架,广泛应用于Web开发中。2025年3月,GitHub Advisory Database和NVD等安全机构均发布了漏洞报告,指出在Next.js中如果授权检查流程在中间件中执行,那么当请求中包含特殊HTTP头部(x-middleware-subrequest)时,攻击者可能绕过预定的授权检查,从而实现未授权访问。

Next.js在处理中间件生成的内部请求(如重定向、路由重写)时自动添加该标头,用于区分原始外部请求框架内部生成的子请求
-x-middleware-subrequest是Next.js中一个内部使用的HTTP请求头,用于防止递归请求触发无限循环,

漏洞基本信息:

漏洞名称/编号: GHSA-f82v-jwr5-mffw / CVE-2025-29927

影响版本:

Next.js 版本:≥ 11.1.4, ≤ 13.5.6

Next.js 14.x:≥ 14.0, < 14.2.25

Next.js 15.x:≥ 15.0, < 15.2.3

修复版本:

Next.js 14.x:修复于14.2.25

Next.js 15.x:修复于15.2.3

2. 漏洞成因与技术细节

2.1 漏洞成因

Next.js漏洞的根本成因在于对请求头部数据验证不严密。具体来说:

请求头未经严格验证:

中间件逻辑在处理HTTP请求时,对诸如“x-middleware-subrequest”这一头部参数的校验不够严谨,允许恶意请求利用该头部值来绕过正常的授权检查流程。

授权检查流程缺陷:

攻击者通过在HTTP请求中添加或修改“x-middleware-subrequest”头,跳过预定的中间件验证,从而使验证步骤未能执行,进而实现对受保护资源的访问。

2.2 攻击原理与利用方式

攻击者构造恶意负载的基本步骤如下:

构造恶意请求:
攻击者需要构造一个HTTP请求,在请求头中添加“x-middleware-subrequest: true”。例如:

shell
GET /protected-route HTTP/1.1
Host: target-app.com
x-middleware-subrequest: true

通过这种方式,恶意请求将触发Next.js中未经严格验证的中间件流程,并绕过正常的授权检查。网站图标GitHub Advisory Database, 网站图标Hacker News

漏洞利用实质:
由于Next.js中负责身份验证和授权的中间件未能对“x-middleware-subrequest”头进行足够校验,恶意请求会被错误地视作合法请求。任何依赖这些中间件进行授权保护的API和路由都可能因此暴露在攻击者面前。网站图标VulDB

3. 代码补丁及修复措施分析

为了解决该漏洞,Next.js官方在版本中进行了补丁提交(15 版本和 14 版本)(对应GitHub提交记录网站图标52a078d网站图标5fd3ae8)。

3.1 增强请求和响应校验

1. 在 src/server/lib/router-server.ts 文件中

添加了生成随机字节的代码,并将其转换为十六进制字符串作为 middlewareSubrequestId

将这个 ID 存储在全局对象中 (globalThis)。

这些更改确保每个中间件子请求都有一个唯一的 ID。

2. 在 src/server/lib/server-ipc/utils.ts 文件中

增加了对 x-middleware-subrequest 请求头的检查。

如果请求头的 ID 与当前会话的 ID 不匹配,则删除 x-middleware-subrequest 请求头。

这一改动确保了只有来自当前会话的中间件请求被正确处理,避免错误地跳过中间件。

3. 在 src/server/web/sandbox/context.ts 文件中

将 x-middleware-subrequest-id 请求头添加到中间件请求中。

这些改动确保每个中间件请求都包含唯一的子请求 ID,从而可以在后续请求中进行验证。

4. 在 test/e2e/middleware-general/test/index.test.ts 文件中

增加了一个测试用例来验证请求头的正确过滤。

这个测试用例检查了当 x-middleware-subrequest 请求头被设置时,是否能够正确过滤并返回预期的重定向状态和位置。


这些改动的主要目的是确保中间件请求的唯一性和安全性。通过为每个中间件请求生成唯一的 ID,可以有效防止请求头被滥用或被错误地跳过中间件逻辑,算是简单修复了这个 bug 吧,后期估计官方还是会继续进一步优化吧...

3.2 临时修复代码

如果nextjs 版本跨度过大,一时半会来不及升级大版本,请先在中间件简单先修复一下

javascript
export function middleware(request) {
  // 当检测到非法的 'x-middleware-subrequest' header 时,立即拒绝请求
  if (request.headers.has('x-middleware-subrequest')) {
    return new Response('Unauthorized', { status: 401 });
  }
  return NextResponse.next();
}

如果暂时不能发布新版请赶紧在 web服务端下手(前提套了 web转发,下面 nginx示例)

yaml
location / {
    proxy_set_header x-middleware-subrequest "";
    if ($http_x_middleware_subrequest) {
        return 403;
    }
}

该示例实现了基本的保护措施,对于防止攻击者利用该头部触发漏洞发挥了临时缓解作用,后续还是要进行版本升级方才完全解决问题,不过 nextjs 最近的破坏性更新是在太多了...

4. 总结

1. 中间件不应作为唯一安全防线,需配合服务端验证

2. 框架级安全机制需要定期进行渗透测试

3. 子请求处理逻辑应默认采用最小权限原则