Bezpłatne Dni Otwarte Sekurak Academy! Hackowanie na żywo, szkolenia, ebooki, …

Kiedy podatność przypomina backdoora – Next.js CVE-2025-29927 i obejście logiki middleware

25 marca 2025, 14:28 | W biegu | 0 komentarzy

Krytyczna podatność (CVSS3.1 na poziomie 9.1) we frameworku JS ściąganym niemal 10 milionów razy w tygodniu, która pozwala na obejście uwierzytelniania? Brzmi jak idealna piątkowa publikacja. Tak też się stało 21.03.2025, kiedy światło dzienne ujrzała podatność zgłoszona niemal miesiąc wcześniej przez dwóch badaczy – @zhero___ oraz @inzo___. Przyjrzeli się oni frameworkowi Next.js, który pozwala na tworzenie reactowych stron internetowych z renderowaniem po stronie serwera. Rozwiązanie kojarzy się przede wszystkim z szybkim rozwijaniem aplikacji webowych oraz licznymi integracjami.

TLDR:

  • Podatność pozwalająca na obejście logiki middleware (w tym autoryzację) została odkryta w popularnym frameworku Next.js.
  • Podatne są wersje Next.js 15.x  < 15.2.3, 15.x < 14.2.25 oraz 13.x  < 13.5.9
  • Zalecaną formą obrony jest oczywiście aktualizacja do wersji 15.2.3, 14.2.25 i 13.5.9 oraz odpowiednio wyższych lub – jeśli to nie jest możliwe – należy usunąć odpowiednie nagłówki z zapytania HTTP zanim dotrze ono do middleware.

W opublikowanym raporcie badacze opisują dokładne powody wystąpienia podatności określonej jako CVE-2025-29927. Źródło problemu leży w kodzie implementującym tzw. middleware, czyli element pośredniczący w przetwarzaniu przychodzących zapytań HTTP. Zgodnie z dokumentacją, middleware umożliwia wprowadzanie zmian do zapytania, zanim zostanie ono zakończone – tzn. zanim zostanie ono obsłużone przez odpowiedni element kodu. 

Middleware allows you to run code before a request is completed. Then, based on the incoming request, you can modify the response by rewriting, redirecting, modifying the request or response headers, or responding directly.

Middleware runs before cached content and routes are matched.

Dzięki temu możliwe jest zaimplementowanie np. przekierowań lub analizy nagłówków. Umieszczenie middleware pozwala na wykorzystanie go do przeprowadzania procesu uwierzytelniania i autoryzacji np. poprzez walidację tokenów sesyjnych czy ciasteczek. To powoduje, że jest to krytyczny – z punktu widzenia bezpieczeństwa – komponent aplikacji webowej. 

Autorzy badania spojrzeli dokładnie w kod implementujący middleware i odnaleźli tam sporo ciekawych zapisów, jak np. taki jak przedstawiono na listingu 1. 

Listing 1. Fragment implementacji funkcji runMiddleware (źródło listingu: zhero-web-sec.github.io, kod źródłowy)

Omawiana funkcja dokonuje ekstrakcji wartości nagłówka x-middleware-subrequest. Po podzieleniu wartości nagłówka na znaku dwukropka “:” dokonywane jest sprawdzenie, czy nowo powstała lista zawiera wartość middlewareInfo.name. Jeśli tak jest, to zapytanie przekazywane jest dalej, bez dalszej obsługi – np. weryfikacji tokenu JWT użytkownika.

Aby mieć możliwość “wyskoczenia” ze ścieżki obsługi żądania należy więc podać w nagłówku x-middle-subrequest pewną wartość. Jednak okazuje się, że jest ona bardzo prosta do odgadnięcia – jest to ścieżka, w której umieszczona została implementacja middleware. Przed wersją 12.2, plik ten musiał nazywać się _middleware.ts i znajdować się w określonym miejscu – był to katalog (lub jego podkatalog) pages/.

Oznacza to, że w najprostszej konfiguracji do pominięcia przetwarzania zapytania w middleware wystarczyło dodanie nagłówka: x-middleware-subrequest: pages/_middleware

Oczywiście możliwość zagnieżdżania middleware wymaga dostosowania kodu “eksploitu”.

Rysunek 1. Fragment dokumentacji odnaleziony w archiwum Internetu przez badaczy (źródło: zhero-web-sec.github.io)

Autorzy podają prosty przykład pozwalający zrozumieć potrzebne elementy:

Dla ścieżki do panelu administracyjnego /dashboard/panel/admin należy sprawdzić następujące możliwości:

  • pages/_middleware
  • pages/dashboard/_middleware
  • pages/dashboard/panel/_middleware

Co jednak z późniejszymi wersjami Next.js? Okazuje się, że problem też ich dotyka, a kosmetyczne zmiany w zasadach umieszczenia kodu pośredniczącego (middleware? :D) powodują, że atak może być jeszcze prostszy. Nowsze wersje (od 12.2) wymagają, aby nazwa pliku nie rozpoczynała się od podkreślenia (czyli po prostu: middleware.ts). Zmieniła się też lokalizacja, która nie musi już prowadzić do katalogu pages/. Struktura projektu Next.js dopuszcza umieszczenie kodu źródłowego wewnątrz src/, co też powinno być brane pod uwagę podczas testowania tej podatności. Oznacza to, że nagłówki mogące posłużyć do nadużycia tej podatności mają następującą postać: 

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

To znacznie upraszcza eksploitację. Ale to nie koniec! Okazuje się, że kolejne wersje Next.js również mogą być podatne za sprawą trochę innego elementu implementacji. 

Listing 2. Fragment kodu zapobiegający nieskończonej pętli przekierowań (źródło listingu: zhero-web-sec.github.io, kod źródłowy)

Aby zapobiec wielokrotnym przekierowaniom, wprowadzono ograniczenie do zapisanej na sztywno wartości MAX_RECURSION_DEPTH=5. Jeśli zliczona liczba wystąpień ścieżki do middleware w nagłówku x-middleware-subrequest będzie większa lub równa 5, to wtedy ponownie dalsze przetwarzanie zapytania jest przerywane i jest ono przekazywane dalej. A to oznacza, że do obejścia middleware w nowszych wersjach możliwe jest wykorzystanie następujących form nagłówka:

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

Prawda, że urocze? 

Badacze wskazali, że luka prowadzić może nie tylko do obejścia mechanizmów autoryzacji, ale też np. może ograniczyć zwracane nagłówki, w tym CSP (Content-Security-Policy), jeśli jest ono ustawione przez middleware. Warto zaznaczyć, że potrzebny jest do tego szczególny nagłówek, którego przeglądarka automatycznie nie ustawi, więc nie jest to obejście mechanizmu CSP prowadzące do łatwiejszej eksploitacji np. XSS. 

Nawet jeśli aplikacja nie implementuje krytycznych mechanizmów wykorzystując middleware, to wciąż może być możliwe jej nadużycie – przez DoS wykorzystujący zatruwanie cache. 

Rysunek 2. Przykład z prawdziwego programu bug bounty, w którym udało się doprowadzić do zapisania w cache strony 404, która będzie serwowana w momencie odwołania do głównej ścieżki /. (źródło:  zhero-web-sec.github.io)

Podatność, chociaż może wywołać uśmiech i niedowierzanie, niesie za sobą poważne konsekwencje nie tylko dla poufności czy integralności systemu, ale także jego dostępności. 

Mamy wrażenie, że dokładny powód jej wystąpienia oraz wpływ na bezpieczeństwo aplikacji nie został powszechnie dobrze zrozumiany, co spowodowało, że autorzy postanowili doprecyzować opis podatności.

Since the security advisory was released, we’ve received a few inquiries from people concerned about their applications and not understanding the scope of the attack. To be clear, the vulnerable element is the middleware. If it isn’t used (or at least isn’t used for sensitive purposes), there’s nothing to worry about (check the DoS aspect above, though), since bypassing the middleware won’t bypass any security mechanisms.

Otherwise, the consequences can be catastrophic, and we encourage you to quickly implement the security advisory’s instructions.

Inni badacze również przyjrzeli się materiałom źródłowym, które wskazywały na błędne zrozumienie tematyki, co skutkowało np. błędną implementacją szablonów nuclei, które ograniczały skuteczność wykrycia niektórych wariantów wystąpienia podatności.

Opis dramy pomiędzy CEO Cloudflare a CEO Vercela Wam podarujemy :) 

Nie pozostaje nic innego, jak zastosować wydane łatki, lub jeśli nie jest to możliwe – usunąć nagłówek x-middleware-subrequest w zapytaniach pochodzących od użytkownika. Advisory podatności można znaleźć tutaj.

~Big Hat Logan

Spodobał Ci się wpis? Podziel się nim ze znajomymi:



Komentarze

Odpowiedz