为什么写这篇
最近在写 Next.js 应用, 聊到某个中间件实现的时候, 想到可能存在越权问题
AI 提到了 CVE-2025-29927 这个漏洞, 讲的是 Next.js middleware 授权绕过.
很多 Next.js 应用会在 middLeware 做前置访问控制, 这层如果被跳过, 后面的 page.route handler.api 就可能直接暴露风险
这个漏洞的本质是, 某个本该内部的控制信号, 被外部输入影响了, 且因为未与上下文强绑定, 导致越权绕过.
CVE-2023-48309, CVE-2022-24858, CVE-2023-27490 这几个洞的切入点也差不多,
因为 AI 的发展, 未来大家都会想手搓一些自己的网站或者应用, 一般就是能跑就行, 自然容易出现这些漏洞, 如果不怎么在意容易资损.
上下文
1) CVE-2025-29927 , Next.js middleware authorization bypass
- 场景: 应用把访问控制放在 middleware, 直接通过某个请求头判断内部的访问控制;
- 攻击链路: 外部请求注入可影响内部语义的信号, 使得 middleware 跳过.
- 风险: 前置授权层被绕过后, 后续路由直接暴露.
外部输入控制内部 flag -> 可能绕过
2) CVE-2023-48309 , NextAuth possible user mocking
- 场景: 默认 middleware + 授权判断过弱.
- 攻击链路: 拿到流程中产生的 token 后, 系统只用
if (token)判断通过.
存在即合理, 有点搞
3) CVE-2022-24858 , NextAuth open redirect
- 场景: 登录回调接受用户可控
callbackUrl. - 攻击链路: 配合钓鱼, 信任链被用来做
trust laundering.
redirect 没有做绑定校验
4) CVE-2023-27490 , OAuth checks missing(state/pkce/nonce)
- 场景: OAuth 登录不是一次请求就结束, 中间会跳好几次, 包括浏览器跳转, 第三方授权, 服务端回调. 只要
state/pkce/nonce有一项没校验好, 整条链路就可能绑错. - 3 个字段:
state: 用来确认 "这次回调是不是我刚刚发起的那次登录", 防别人塞一条假的回调进来.pkce: 用来确认"拿到 code 的人"和"去换 token 的人"是同一个客户端, 防 code 被偷走后被别人拿去用.nonce: 用来确认"回来的 token"确实对应这次登录, 防旧 token 重放或账号对错人.
- 攻击链路可以理解成 5 步:
- 攻击者先改授权入口参数, 诱导用户点一条被动过手脚的 OAuth 链接.
- 用户在 IdP 侧正常登录, 平台按流程返回
code和相关参数. - 受影响实现对
state/pkce/nonce的检查不完整, 或者检查失败了也没停下来. - 某些失败分支没有彻底中止和清理, 中间产物还能被继续利用.
- 最后系统可能把登录态绑错人, 轻则账号状态混乱, 重则身份被冒用.
- 风险: 它不一定每次都表现成"秒被接管账号", 但会让身份边界变模糊. 对认证系统来说, 这就是高危信号.
- 防守要点: 校验要 mandatory, 流程要 atomic, 失败要 fail-closed, 并且严格先校验再做副作用.
- 我抓到的本质: 不只是有这几个字段就行, 还要保证检查不可跳过, 不可降级, 失败即终止.
记录
对于攻击者:
- 这次授权依赖哪些输入
- 哪些输入是我能控制的
- 是否能在过程中操作, 测试其绑定关系, 获得中间态
对于代码编写者:
- 这次授权依赖哪些输入.
- 这个输入是否可能被客户端影响.
- 失败路径是否真正 fail-closed.
- 修复是否恢复了不变量, 而不是只挡住已知 payload.
只要任何一层把 "不可信输入" 当成了"可信控制信号", 系统就会漏.
优化
在我的 Next.js 项目中, 进行如下更新
- middleware 层: 前置访问控制与早期拒绝, 确保使用体验不卡顿.
- page/api 层: 即使前置层通过, 仍要做身份与权限真相校验.
- 数据层: 绑定真实查询.
参考
- NVD: CVE-2025-29927
- GHSA: Next.js advisory
- Patch:
- CVE refs:
- Research writeup: zhero