CVE-2025-29927 漏洞複現
目錄
目錄
- 結論
- 漏洞簡介
- 漏洞原理和利用方法
- 漏洞復現步驟
4.1 下載 Node.js
4.2 建立漏洞專案
4.3 製作 middleware.js 腳本
4.4 建立 run.js
4.5 啟動 server 並執行 payload - patch ( Workaround )
結論
Next.js 在 v11~v15.2.2 中對 x-middleware-subrequest header 採取信任策略,
然而缺乏來源驗證,導致攻擊者可偽造該 header 來繞過授權邏輯,構成嚴重的權限繞過漏洞(CVE-2025-29927)。
自 v15.2.3 起,官方改為建立唯一的 middleware session ID,並比對該 ID 來判斷是否為內部請求,有效解決此問題。
漏洞簡介
- 漏洞編號:CVE-2025-29927
- 漏洞類型:授權繞過
- 影響範圍:Next.js v11.1.4 ~ v15.2.2(含)
- CVSS 3.X 分數:9.1(Critical)
| Exploitability Metric | Impact Metric |
|---|---|
| AV : Network | S : Unchanged |
| AC : Low | C : High |
| PR : None | I : High |
| UI : None | A : None |
描述:
當 Next.js 使用 Middleware 處理授權邏輯時,攻擊者可通過特殊標頭X-Middleware-Subrequest繞過中介軟體的授權邏輯,進而未經授權訪問受保護的頁面。發現者: 由資安公司 Akamai 的研究人員所發現。
回報時間:
於2025 年 3 月 14 日 首度通報給 Next.js 官方開發團隊。該團隊隨後在 2025 年 4 月 10 日釋出修補版本,並於 2025 年 4 月 16 日公告此漏洞細節與 CVE 編號。
漏洞原理和利用方法
Next.js 使用內部特殊標頭 x-middleware-subrequest 來識別內部請求,如 React Server Components(RSC)或 App Router 中的子請求。若攻擊者在外部請求中加入此標頭,Next.js 錯誤地認定其為內部請求,跳過了 middleware 的驗證邏輯。
而會發生此漏洞的最根本原因是Next.js在處理子請求中間件機制的設計缺陷:
內部子請求識別方式:當中間件需要向內部路由發送請求(如抓取資料或執行驗證)時,Next.js 會自動加入 x-middleware-subrequest 標頭,用來標示這是內部請求,以避免中間件重複執行造成無限循環。
缺乏來源驗證:漏洞的關鍵在於 Next.js 並未對這個標頭的來源進行嚴格驗證。這導致外部請求如果攜帶這個標頭,也會被誤認為是內部子請求。
中間件邏輯問題:只要 Next.js 偵測到請求中有 x-middleware-subrequest 標頭,就會略過對該請求的中間件處理,直接將其導向對應的路由或 API。
繞過授權檢查:攻擊者只需手動添加這個特殊的標頭,即可繞過原本由中間件執行的授權驗證,直接存取應該受保護的資源。
漏洞復現步驟
系統環境:
- Windows 10
- Node.js v22.14.0
- Next.js v15.2.2
具體步驟:
- 下載 Node.js
- 建立漏洞專案
- 製作 middleware 腳本
- 設定 next.config.mjs
- 建立 run.js
- 啟動 server
- 傳送 payload 並 bypass 開啟 calc.exe
下載 Node.js
進入 Node.js 官網並下載Node.js(v22.14.0)
完成後可至cmd驗證是否成功
1 | node -v |

建立漏洞專案
建立專門針對「漏洞 PoC 的最小環境」(vuln_nextjs_calc)在桌面並展示專案目錄
1 | cd C:\Users\testUser\Desktop |


設定執行環境使用有漏洞的next.js@15.2.2
1 | cd vuln_nextjs_calc |

看到的Critical就是指我們這個 CVE-2025-29927 了,
- next@15.2.2 -> 內含 CVE-2025-29927 漏洞
- react、react-dom 為執行 js 必要 package
製作 middleware.js 腳本
建立 vuln_nextjs_calc/middleware.js,此程式用於在「請求到達頁面前」先做一些檢查,例如:
- 是否已登入?
- 是否有權限訪問某頁?
- 是否來自內部來源?
1 | import { NextResponse } from 'next/server' |

簡單講解程式碼
如果有抓到 x-middleware-subrequest 則通行請求;否則拒絕授權請求。最後設定要經過protect的請求要先被中介層攔截。
為什麼是 x-middleware-subrequest?
因為這個標頭是 Next.js 自己「內部」產生的,一般的用戶端並不會產生。
Next.js 在處理以下「內部子請求」時會自動才加上這個標頭,又因為這些請求其實是來自 Next.js 自己的核心模組,所以 Next.js 預設信任這個標頭,漏洞也因此產生。
那既然我們知道他會依有無這個Header進行判斷,那就在curl時加上這個Header即可bypass
1 | curl http://localhost:3000/protected/run?cmd=calc -H "X-Middleware-Subrequest: 1" |
為什麼是/protected?
- 更貼近「實務部署中的半公開資源」
- 在滲透測試中較易誘導開發者疏忽
- 可用性與示範性強
本次 PoC 將漏洞入口放置於 /protected/,模擬現實系統中將內部功能藏於「看似有授權但實際驗證不足」的路徑下。
相較於高敏感度 /admin/,此類路徑往往因為開發者認為「不容易猜中」而疏於設防,是授權繞過的熱門目標。
為什麼不選admin
因為一看就是敏感資源,通常防禦最嚴(多層保護、非公開、二次驗證、IP 限制)
建立 run.js
新建 run.js 於 pages/protested/,模擬了真實系統中「僅供內部或管理員操作的命令執行功能」,
1 | import { exec } from 'child_process' |
啟動 server 並執行payload
啟動 server
1 | npm run dev |

執行payload
先下載curl –
choco install curl
執行
curl加上 header
1 | curl "http://localhost:3000/protected/run?cmd=calc" -H |

整個攻擊就完成啦!!!
也可以更換payload
curl “http://localhost:3000/protected/run?cmd=notepad“ -H “X-Middleware-Subrequest: 1”
curl “http://localhost:3000/protected/run?cmd=mspaint“ -H “X-Middleware-Subrequest: 1”
patch ( Workaround )
問題本質 Recap
JS 錯誤地信任 header,導致攻擊者只要加上這個 header,就能繞過 middleware 的驗證
官方修復
根據 Next.js GitHub 官方提交紀錄:Update middleware request header (#77201)
官方在 commit 中將對 x-middleware-subrequest 的信任邏輯,改為使用 isInternalRequest() 進行判斷,從而防止外部請求偽造 header 繞過中介層驗證(CVE-2025-29927)。
統整更動
| 分析項目 | 原本的做法 | 導致的問題 | 修補後的做法 |
|---|---|---|---|
| 是否為內部請求 | 只要請求帶有標頭 x-middleware-subrequest 就視為「內部請求」 | 攻擊者可以用 curl 加上這個標頭就騙過 middleware,繞過授權 | 驗證該請求是否帶有 正確 session 的唯一 ID,才信任它是內部請求 |
| 判斷邏輯位置 | 沒有驗證來源,只靠單一 header 判斷 | 外部使用者可偽造 header,跳過中間件邏輯、執行敏感操作 | 在核心程式碼中加入 session 追蹤與 header 過濾,清除不合法的 header |
| 繞過途徑 | curl "http://host" **-H "X-Middleware-Subrequest: 1"** |
沒有比對內部 request session 的 ID,任何人都可以成功繞過驗證! | 必須同時帶有 Next.js 內部塞入的 x-middleware-subrequest-id 並且與 global session 一致,否則直接刪除 header |
資料來源
- Title: CVE-2025-29927 漏洞複現
- Author: Mike
- Created at : 2025-04-23 12:24:56
- Updated at : 2025-04-30 12:30:39
- Link: https://happymike0103.github.io/2025/04/23/CVE-2025-29927/
- License: This work is licensed under CC BY-NC-SA 4.0.