705 字
4 分钟
鉴权漏洞

一, CVE-2023-27524 superset#

1.背景:

2.环境搭建:

直接从 vulhub 上拉个 docker

确认环境正确

3.复现步骤

1.抓包登陆数据

使用 session 作为验证

漏洞为使用弱默认密钥,查找 superset 的默认密钥

存在以下默认密钥:SECRET_KEYS = [

b’\x02\x01thisismyscretkey\x01\x02\e\y\y\h’, # version < 1.4.1

b’CHANGE_ME_TO_A_COMPLEX_RANDOM_SECRET’, # version >= 1.4.1

b’thisISaSECRET_1234’, # deployment template

b’YOUR_OWN_RANDOM_GENERATED_SECRET_KEY’, # documentation

b’TEST_NON_DEV_SECRET’ # docker compose

]

2.使用工具对抓包中的 cookie 进行解码:

解码成功说明默认密钥为

3.使用拿到的密钥进行签名,伪造管理员身份

二,CVE-2025-29927 NEXT.JS 中间件漏洞#

1.背景

2.环境搭建:

依旧拉 docker,复现版本 14.2.0

3.复现步骤

先跟着 poc 跑一下,添加x-middleware-subrequest: middleware:middleware:middleware:middleware 请求头后绕过验证

在源码中搜索关键字x-middleware-subrequest

定位漏洞出现位置

init.headers = new Headers(init.headers ?? {})
// Forward subrequest header from incoming request to outgoing request
const store = requestStore.getStore()
if (
store?.headers.has('x-middleware-subrequest') &&
!init.headers.has('x-middleware-subrequest')
) {
init.headers.set(
'x-middleware-subrequest',
store.headers.get('x-middleware-subrequest') ?? ''
)
}
const prevs =
init.headers.get(`x-middleware-subrequest`)?.split(':') || []
const value = prevs.concat(options.moduleName).join(':')
init.headers.set('x-middleware-subrequest', value)
if (!init.headers.has('user-agent')) {
init.headers.set(`user-agent`, `Next.js Middleware`)
}

这段代码表明 x-middleware-subrequest 请求头用来表示子请求,代码并没有对请求的来源进行严格的认证,导致攻击者外部修改请求头实行攻击的可能

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',
},
}),
}
}

代码中显示首先用 suberp 变量提取了 x-middleware-subrequest 请求头的值并通过: 分割成列表,同时和将列表中的值和 params.name 作比较,每有一个值相等 deepth 深度就+1,同时定义了最大深度为 5,防止中间件无限递归,当大于等于最大深度时中间件据直接转发请求

回到 payload:x-middleware-subrequest: middleware:middleware:middleware:middleware

x-middleware-subrequest 也就是我们伪造的请求头,本来是用于中间件内部的子请求标识,被标识的子请求不用再完整的走一遍鉴权的流程,如果能伪造就给了我们绕过的可能

middleware 是中间件的所在的文件路径,对应代码中的 params,在当前版本中中间件的文件路径有两种可能 middleware 或 src/middleware,连续写 5 个也就是为了达到最大深度 5 后直接转发请求绕过验证

4.思考:

避免对请求头的过度信任,中间件将 x-…请求头标识为为合法请求却没有做严格的来源验证,给了攻击者伪造的机会,单纯只依赖请求头来标识是否合法也不够安全,对中间件的每个环节都应该进行是适当的验证

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

鉴权漏洞
https://lab404.cn/posts/framework-auth-vulns/
作者
见山
发布于
2025-11-26
许可协议
CC BY-NC-SA 4.0