Next.js 與中間件漏洞:失效的授權機制

Techub News
REACT-7.78%

撰文:Rachid.A

翻譯:Yewlne

01 譯文正文

最近,我與化名為 inzo_ 的 Yasser Allam 決定聯手開展研究。在討論了多個潛在目標後,我們決定將焦點放在 Next.js 上(在 GitHub 上擁有 13 萬 Stars,目前每週下載量超過 940 萬次)。這是一個我非常熟悉的框架,與它有美好的創作經歷,正如我之前的研究成果所證明的那樣。因此,本文中的「我們」自然指代我們兩人。

Next.js 是一個基於 React 的全功能 JavaScript 框架,擁有豐富的特性——是深入研究細節的理想場所。懷著信念、好奇與韌性,我們踏上旅程,探索那些鮮為人知的角落,尋找藏匿其中的寶藏。

不久之後,我們就在中間件中發現了一個重大問題。其影響範圍廣泛,所有版本均受影響,且利用此漏洞無需任何前置條件——我們將很快進行詳細展示。

目錄

Next.js 中間件

授權神器:寶藏級老代碼

執行順序與 middlewareInfo.name

授權神器:昨日已成詩,今朝更值得

/src 目錄

最大遞歸深度

漏洞利用

繞過授權/重寫

繞過 CSP

通過緩存投毒實現 DoS(What?)

澄清

安全公告 - CVE-2025-29927

免責聲明

結語

Next.js 中間件

中間件允許你在請求完成之前執行代碼。然後,你可以根據傳入的請求,通過重寫、重定向、修改請求或響應頭,或直接返回響應的方式來修改響應內容(摘自 Next.js 文檔)。

作為一個完整的框架,Next.js 擁有自己的中間件(middleware)——這是一個重要且被廣泛使用的特性。它的應用場景眾多,其中最重要的包括:

路徑重寫(Path rewriting)

服務器端重定向(Server-side redirects)

向響應添加頭信息(如 CSP 等)元素

最重要的是:身份驗證(Authentication)和授權(Authorization)

中間件的一個常見用途是進行授權,這涉及基於特定條件來保護特定路徑。

身份驗證和授權:在授予對特定頁面或 API 路由的訪問權限之前,確保用戶身份並檢查會話 Cookie(Next.js 文檔)。

示例:當用戶嘗試訪問 /dashboard/admin 時,請求首先會通過中間件,中間件會檢查用戶的會話 cookie 是否有效以及是否具有必要的權限。如果驗證通過,中間件便轉發請求;否則,中間件會將用戶重定向到登錄頁面:

授權神器:寶藏級老代碼

正如一位偉人曾經說過的,「talk is cheap, show me the bug」,讓我們避免過多的敘述,直接切入主題;我們在瀏覽框架的舊版本(v12.0.7)時,我們發現了這段代碼:

當 Next.js 應用程序使用中間件時,會調用 runMiddleware 函數。除了其主要功能外,該函數還會獲取 x-middleware-subrequest 頭部的值,並用它來判斷是否應該應用中間件。該頭部值會使用冒號(:)作為分隔符被拆分成列表,然後檢查這個列表是否包含 middlewareInfo.name 值。這意味著,如果我們在請求中添加帶有正確值的 x-middleware-subrequest 頭部,那麼中間件——無論其用途如何——將被完全忽略,請求將通過 NextResponse.next() 被轉發,並且將完成到原始目的地的路徑,而不受中間件的任何影響。這個頭部及其值就像一把「萬能鑰匙」,可以繞過所有規則。此時我們已經意識到發現了一個驚人的問題,接下來需要完成最後幾個拼圖。

要讓我們的「萬能鑰匙」生效,它的值必須包含 middlewareInfo.name,但這個值究竟是什麼呢?

執行順序與 middlewareInfo.name

middlewareInfo.name 的值非常容易推測,它僅僅是中間件所在的路徑。要了解這一點,我們需要簡單瞭解一下中間件在舊版本中的配置方式。

首先,在 12.2 版本之前——這個版本中中間件約定發生了變化——文件必須命名為 _middleware.ts。此外,app 路由器(router)僅在 Next.js 的版本 13 中才引入。當時存在的唯一路由器是 pages 路由器,因此該文件必須放在 pages 文件夾內(特定於路由器)。

有了這些信息,我們就能推斷出中間件的確切路徑,從而猜測 x-middleware-subrequest 頭部的值。這個值只是由目錄名稱(即當時存在的唯一路由器名稱)和文件名組成,遵循當時以下劃線開頭的命名約定:

x-middleware-subrequest: pages/_middleware

當我們嘗試繞過那些被配置為系統性地將訪問嘗試從 /dashboard/team/admin 重定向到 /dashboard 的中間件時:

成功了,我們侵入了 ⚔️

我們現在可以完全繞過中間件,從而繞過任何基於它的保護系統,最典型的就是授權,就像我們上面的例子。這個發現相當驚人,但還有其他需要考慮的點。

12.2 之前的版本允許嵌套路由在目錄樹的任何位置(從pages文件夾開始)放置一個或多個_middleware文件,並且它們有執行順序,正如我們在從Web Archive中檢索到的舊文檔截圖中所看到的:

的,這對我們的漏洞利用意味著什麼?

可能性 = 路徑中的層級數量

因此,要訪問/dashboard/panel/admin(受中間件保護),middlewareInfo.name的值有三種可能性,相應地x-middleware-subrequest的值也有三種可能性:

pages/_middleware

pages/dashboard/_middleware

pages/dashboard/panel/_middleware

授權神器:昨日已成詩,今朝更值得

到目前為止,我們認為只有版本 13 之前的版本容易受到攻擊,因為中間件已在源代碼中被移動,並且我們還沒有覆蓋它的所有方面。我們推測維護者一定已經注意到了這個漏洞,並在版本 13 的重大更改之前修復了它,所以我們向框架維護者報告了這個漏洞並繼續了我們的研究。

令我們大為驚訝的是,在最初發現後兩天,我們發現所有版本的 Next.js——從版本 11.1.4 開始——都存在漏洞! 代碼不再位於同一位置,漏洞利用的邏輯也略有變化。

如前所述,從版本 12.2 開始,文件不再包含下劃線,必須簡單命名為 middleware.ts。此外,它不再位於 pages 文件夾中(這對我們來說很方便,因為從版本 13 開始,引入了 app 路由器,這本會使可能性加倍)。

With that in mind, the payload for the first versions starting with version 12.2 is very simple:

考慮到這一點,從版本 12.2 開始的第一個版本的有效負載非常簡單:

x-middleware-subrequest: middleware

/src 目錄

還需要考慮到 Next.js 提供了創建 /src 目錄的可能性:

(Next.js documentation) 作為在項目根目錄中擁有特殊 Next.js app 或 pages 目錄的替代方法,Next.js 還支持將應用程序代碼放在 src 目錄下的常見模式。(Next.js 文檔)

在這種情況下,payload 將是:

x-middleware-subrequest: src/middleware

因此,無論路徑中有多少層級,總共只有兩種可能性。這簡化了針對相關版本的漏洞利用難度。

在最新版本中,它又有了一點變化(我們保證,最後一次)。

最大遞歸深度

在更新的版本中,邏輯又略有變化,請看這段代碼:

v15.1.7

和之前一樣,系統會檢索 x-middleware-subrequest 頭部的值,並使用冒號作為分隔符形成一個列表。但這次,請求直接轉發的條件——即忽略中間件規則——有所不同:

常量depth的值必須大於或等於常量 MAX_RECURSION_DEPTH 的值(即 5)。在賦值過程中,每當列表 subrequests(即由:分隔的頭部值)中的某個值等於 params.name(即中間件的路徑)時,常量depth就會增加 1。如前所述,這裡只有兩種可能性:middleware 或 src/middleware。

因此,為了繞過中間件,我們只需要在請求中添加以下頭部/值:

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

x-middleware-subrequest: src/middleware:src/middleware:src/middleware:src/middleware:src/middleware

這段代碼最初是用來做什麼的?

這段代碼似乎是為了防止遞歸請求陷入無限循環。

漏洞利用

既然我們知道您喜歡這類內容,這裡有一些來自 Bug Bounty Program 的真實案例。

繞過授權/重寫

在這個例子中,當我們嘗試訪問/admin/login時,收到404響應。從響應頭中可以看出,中間件執行了路徑重寫,以防止未經授權或不適當的用戶訪問:

但使用我們的授權神器 :

我們可以毫無障礙地訪問該端點,中間件被完全忽略。目標 Next.js 版本:15.1.7

繞過 CSP

這次網站使用中間件來設置——除了其他功能外——CSP和cookie:

讓我們繞過它:

Target next.js version: 15.0.3Target next.js 版本:15.0.3

注意: 請留意兩個目標的payload差異,其中一個使用了src/目錄,而另一個沒有。

通過緩存投毒實現 DoS(What?)

是的,通過這個漏洞也可能實現緩存投毒 DoS 攻擊。這顯然不是我們首先要尋找的,但如果沒有敏感路徑受到保護,且沒有更有趣的可利用點,那麼某些情況可能會導致緩存投毒拒絕服務(CPDoS):

假設一個網站根據用戶地理位置重寫用戶路徑,添加(/en、/fr等),且沒有在根路徑(/)上提供頁面或資源。如果我們繞過中間件,就會避開重寫,最終到達根頁面。由於開發者並未打算讓用戶訪問根頁面,因此沒有提供相應頁面,我們會得到404(或根據重寫配置/類型不同,可能是500)。

如果該網站使用了緩存/CDN 系統,可能會強制緩存404響應,導致頁面不可用,嚴重影響站點可用性。

澄清

自安全公告發布以來,我們收到了一些人的諮詢,他們擔心自己的應用程序安全,並且不太理解攻擊的範圍。需要明確的是,易受攻擊的元素是中間件。如果您沒有使用中間件(或至少沒有將其用於敏感目的),那麼無需擔心(不過,請檢查上面提到的 DoS 方面),因為繞過中間件不會繞過任何實際的安全機制。

否則,後果可能是災難性的,我們建議您迅速實施安全公告中的指導措施。

安全公告 - CVE-2025-29927

補丁

對於 Next.js 15.x,此問題已在 15.2.3 中修復

對於 Next.js 14.x,此問題已在 14.2.25 中修復

對於 Next.js 版本 11.1.4 到 13.5.6,我們建議查閱以下解決方法。

解決方案

如果無法升級到安全版本,我們建議你阻止包含 x-middleware-subrequest 請求頭的外部用戶請求訪問你的 Next.js 應用。

嚴重性

CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:N(嚴重程度:9.1/10,臨界級)

更多信息

在撰寫本文時,部署在 Vercel 和 Netlify 上的應用顯然已不再受此漏洞影響(更新:由於存在大量誤報,Cloudflare 已將該規則調整為僅在用戶主動啟用時生效——這些誤報未能有效區分來自合法用戶的請求與潛在攻擊者的請求)。

免責聲明

本研究發佈僅用於教育目的,旨在幫助開發者理解問題的根本原因,或為研究人員 / 漏洞獵人在未來的研究工作中提供啟發。本文作為安全公告的補充材料,提供了有關漏洞本質的進一步說明和澄清——因為公告中已公開了導致該漏洞的請求頭(以及相關的提交差異)。

我們明確聲明不支持對本文進行任何不道德的使用。

結語

正如本文所強調的,這個漏洞在 Next.js 源代碼中已經存在了數年,隨著中間件及其版本的演變而變化。任何軟件都可能出現嚴重漏洞,但當它影響到最流行的框架之一時,就變得特別危險,可能對更廣泛的生態系統造成嚴重後果。如前所述,在撰寫本文時,Next.js 每週下載量接近 1000 萬次。它廣泛應用於從銀行服務到區塊鏈等關鍵領域。當漏洞影響到用戶依賴的成熟功能(如授權和身份驗證)時,風險就更大了。

Vercel團隊花了幾天時間來解決這個漏洞,但值得注意的是,一旦他們意識到問題,修復就被提交、合併到幾小時內實現到新版本中(包括向後移植)。

時間線 :

2025 年 2 月 27 日:向維護者報告了漏洞(當時我們認為僅 12.0.0 至 12.0.7 版本受影響,並在報告中註明了這一點)。

2025 年 3 月 1 日:發送了第二封郵件,說明實際上所有版本都存在漏洞,包括最新穩定版本。

2025 年 3 月 5 日:收到 Vercel 團隊的初步回覆,表示 12.x 版本已不再維護(可能尚未閱讀我們在第二封郵件中附帶的安全公告模板,未注意到所有版本均受影響的情況)。

2025 年 3 月 5 日:再次發送郵件,請團隊儘快查閱第二封郵件及安全公告模板。

2025 年 3 月 11 日:再次發送郵件,確認新信息是否已被採納。

2025 年 3 月 17 日:收到 Vercel 團隊的回覆,確認已採納相關信息。

2025 年 3 月 18 日:收到 Vercel 團隊的郵件,表示報告已被接受,修復補丁已完成。數小時後發佈了包含修復的版本 15.2.3(幷包含回溯修復)。

2025 年 3 月 21 日:安全公告正式發佈。

總的來說,尋找零日漏洞的過程,只有在發現線索的那一刻才令人興奮、腎上腺素飆升;其餘時間則像是一段充滿不確定性的旅程——對好奇者而言,它能帶來知識上的收穫;對缺乏耐心的人來說,這段旅程則顯得格外漫長。別猶豫,組隊行動總比獨自穿越沙漠要輕鬆得多。

查看原文
免責聲明:本頁面資訊可能來自第三方,不代表 Gate 的觀點或意見。頁面顯示的內容僅供參考,不構成任何財務、投資或法律建議。Gate 對資訊的準確性、完整性不作保證,對因使用本資訊而產生的任何損失不承擔責任。虛擬資產投資屬高風險行為,價格波動劇烈,您可能損失全部投資本金。請充分了解相關風險,並根據自身財務狀況和風險承受能力謹慎決策。具體內容詳見聲明
留言
0/400
暫無留言