Konferencja Mega Sekurak Hacking Party w Krakowie – 26-27 października!

Świąteczne promocje z sekurakiem!

Podatności w React Server Components zbierają żniwa… i pojawiają się kolejne

22 grudnia 2025, 05:14 | Aktualności | 0 komentarzy

Wciąż nie milkną echa krytycznej (CVSS 10/10) podatności w React Server Components. Co ważne, aplikacja jest podatna nawet wtedy, gdy nie implementuje bezpośrednio tych komponentów. Wystarczy, że zainstalowane są zależności w podatnych wersjach (m.in. 19.0, 19.1.0, 19.1.1, 19.2.0 i nie tylko – czytaj do końca!). Dodatkowo podatny jest np. wykorzystujący Reacta framework Next.js, i także o nim będzie dziś mowa.
TLDR:

  • Przeprowadzenie ataku jest stosunkowo proste – RCE i DoS wymagają jednego żądania HTTP(S), a wyciek kodu – osadzenia zmiennej definiowanej przez użytkownika w odpowiedzi serwera.
  • Krytyczna podatność w React Server Components (CVE-2025-55182) wciąż jest wykorzystywana, a oprócz niej wykryto 3 nowe luki.
  • Dodatkowe podatności (CVE-2025-55183, CVE-2025-55184, CVE-2025-67779) prowadzą do Denial of Service (DoS) i ujawnienia kodu źródłowego.
  • Podatne są wersje 19.0.0-19.2.2 pakietów react-server-dom-webpack, react-server-dom-parcel, react-server-dom-turbopack. Poprawki wdrożono od wersji 19.0.3, 19.1.4, 19.2.3.
  • Dodatkowo podatne są korzystające z komponentów serwerowych React frameworki takie jak Next.js.
  • Podatność RCE wykorzystywano m.in. w aplikacji Umami (Next.js, self-hosted) – atakujący uruchamiali koparki kryptowalut na niezaktualizowanych instancjach.

Choć pierwszy Proof of Concept – opublikowany ~30 godzin od zgłoszenia podatności – może wyglądać na skomplikowany, samo przeprowadzenie ataku sprowadza się de facto do wykonania jednego żądania HTTP(S). Warto podkreślić również, że możliwość jego wykorzystania nie jest w żaden sposób ograniczona dla specyficznych adresów URL – jeśli zależności są w podatnej wersji, podatna jest cała aplikacja.

Nawet jeśli nie korzystaliśmy z React Server Components (ani frameworka wykorzystującego te komponenty) przy tworzeniu aplikacji, mogą korzystać z nich inne aplikacje działające w naszej infrastrukturze (self-hosted/on-premise).

Jedną z takich aplikacji jest Umami. To otwartoźródłowe narzędzie do analityki ruchu na stronach internetowych, a od niedawna także do zarządzania pixelami śledzącymi i linkami. Backend Umami wykorzystuje framework Next.js, a więc także React Server Components.

Aplikacja działa jako SaaS hostowany przez jej autorów, gdzie za niewielką opłatą można korzystać z usługi podobnie jak np. Google Analytics. Można jednak korzystać z niej także w modelu self-hosted, budując aplikację na serwerze lub korzystając z obrazu dockera dostarczanego przez twórców.

Po upublicznieniu podatności i zgłoszeniach w GitHub Issues, twórcy Umami wyłączyli publiczną instancję, zaktualizowali zależności do załatanych wersji i wydali aktualizację samej aplikacji zalecając jak najszybszą instalację i sprawdzenie m.in. logów pod kątem nietypowej aktywności.

Rys. 1 – informacja od twórców Umami, źródło: github.com

Niestety pomimo reakcji twórców, wciąż pozostało sporo aktywnych instancji, których administratorzy nie zdążyli wdrożyć aktualizacji. Jednym z użytkowników Umami, którego dotknął atak był STFN, który podzielił się swoją historią na blogu.

Zauważył on w panelu Grafana utrzymujące się wykorzystanie CPU na poziomie 100%. Po połączeniu z serwerem ustalił, że zasoby były używane przez kilka instancji procesu /tmp/fghgf. Zakończenie procesu nie pomagało, gdyż po chwili wracał znowu.

Po chwili dostrzegł drugi proces – xmrig. Wtedy stało się jasne, że ktoś używał zasobów VPS-a do kopania kryptowalut.

Rys. 2 – procesy na VPS, źródło: stfn.pl

Procesy były uruchamiane przez użytkownika prometheus, więc autor zablokował na firewallu port 9090, pod którym działała usługa. Finalnie całkowicie usunął Prometheusa z systemu.

To pomogło pozbyć się niepożądanych procesów, a obciążenie VPS-a wróciło do normalnych wartości. Ale to jeszcze nie było źródło problemu. Przyczyną okazała się być właśnie aplikacja Umami w wersji 2.19 która korzystała z podatnej wersji frameworka Next.js. Jak wskazywali inni użytkownicy na GitHubie, podatność była wykorzystywana do uruchamiania crypto minerów na instancjach korzystających z niezałatanych wersji Umami. Aby uniemożliwić dalsze ataki wystarczyło zaktualizować aplikację do v2.20.02 lub v3.0.2.

Po pełny opis sytuacji odsyłamy do oryginalnego wpisu na blogu STFN. Ale to nie koniec historii, bo 11 grudnia 2025 w React Server Components (a więc też w Next.js) znaleziono kolejną podatność. Dotknęła ona także Umami.

Podczas testowania poprawek do pierwszej wspomnianej podatności (CVE-2025-55182) badacze RyotaK, Shinsaku Nomura i Andrew MacPherson odkryli dwie dodatkowe luki w React Server Components. Nie pozwalają one na zdalne wykonanie kodu, więc mowa o nowych podatnościach a nie ominięciu zabezpieczeń w załatanych wersjach. Chodzi o Denial of Service (CVE-2025-55184 i CVE-2025-67779) oraz ujawnieniu kodu źródłowego (CVE-2025-55183).

Oznacza to, że wydane w reakcji na podatność RCE wersje 19.0.2, 19.1.3 i 19.2.2 nie są w pełni załatane. Nie udostępniono na ten moment szczegółów dotyczących wykorzystania podatności. Poprawki zostały wprowadzone w wersjach 19.0.3, 19.1.4 i 19.2.3. Jeśli używasz któregokolwiek z powyższych pakietów, natychmiast zaktualizuj do najnowszej wersji.

W przypadku omawianej aplikacji Umami, twórcy również wypuścili łatkę aktualizującą zależności – wystarczy skorzystać z wersji v3.0.3.

Badacze RyotaK i Shinsaku Nomura odkryli, że możliwe jest wysłanie do endpointu Server Functions żądania HTTP(S), które po deserializacji przez React może spowodować nieskończoną pętlę, która zawiesza proces serwera i zużywa CPU. Nawet jeśli Twoja aplikacja nie implementuje żadnych endpointów React Server Function, może nadal być podatna, jeśli aplikacja korzysta z pakietów React Server Components.

Andrew MacPherson odkrył, że złośliwe żądanie wysłane do podatnego Server Function może zwrócić kod źródłowy dowolnej Server Function. Eksploatacja wymaga istnienia endpointu, który w odpowiedzi wstawia wartość definiowaną przez użytkownika:

'use server';

export async function serverFunction(name) {
 const conn = db.createConnection('SECRET KEY');
 const user = await conn.createUser(name); // implicitly stringified, leaked in db

 return {
  id: user.id,
  message: `Hello, ${name}!` // explicitly stringified, leaked in reply
 }}

Listing 1 – podatny fragment Server Function, źródło: react.dev

Atakujący może uzyskać przykładowo:

0:{"a":"$@1","f":"","b":"Wy43RxUKdxmr5iuBzJ1pN"}
1:{"id":"tva1sfodwq","message":"Hello, async function(a){console.log(\"serverFunction\");let b=i.createConnection(\"SECRET KEY\");return{id:(await b.createUser(a)).id,message:`Hello, ${a}!`}}!"}

Listing 2 – dane uzyskane w odpowiedzi, źródło: react.dev

Przykładowe wykorzystanie dla opublikowanego Proof of Concept:

Rys. 3, 4 – złośliwe żądanie do podatnej aplikacji

Podatność pozwala na ujawnienie np. sekretów, ale tylko jeśli są zahardkodowane w kodzie źródłowym (TLDR: nie warto ich tam przechowywać). Zmienne środowiskowe nie są dotknięte tą podatnością.

Pełny timeline:

  • 3 grudnia: Andrew MacPherson zgłasza podatność (wyciek kodu) do Vercel i Meta Bug Bounty
  • 4 grudnia: RyotaK zgłasza pierwszy DoS do Meta Bug Bounty
  • 6 grudnia: zespół React potwierdza występowanie obu podatności
  • 7 grudnia: początkowe poprawki
  • 8 grudnia: zawiadomienie dostawców hostingu i projektów open source
  • 10 grudnia: wdrożenie mitygacji u dostawców hostingu i testy poprawek
  • 11 grudnia: Shinsaku Nomura zgłasza kolejny DoS do Meta Bug Bounty
  • 11 grudnia: publikacja poprawek i podatności – CVE-2025-55183 i CVE-2025-55184
  • 11 grudnia: dodatkowe poprawki i ujawnienie kolejnej podatności DoS – CVE-2025-67779

Wspomniane podatności wywołały niemałe zamieszanie, ponieważ wielu użytkowników Umami self-hostuje tę aplikację u siebie. Nie sposób nawet przywołać wszystkich zgłoszeń, bo pojawiały się one nie tylko w repozytorium aplikacji, ale też narzędzi do zarządzania takimi usługami jak chociażby Coolify czy YunoHost.

W tym artykule pokazaliśmy podatności na przykładzie Umami, ale odnoszą się one do wszystkich aplikacji korzystających z React Server Components i zależnych od nich frameworków. Zalecamy pilną aktualizację tych zależności i aplikacji je wykorzystujących. Umami jest tu jedynie przykładem – nie twierdzimy, że sama aplikacja jest niebezpieczna, po prostu (jak wiele innych) wykorzystywała podatne zależności.

Jeśli używacie takich narzędzi tylko na własny/wewnętrzny użytek, warto rozważyć czy potrzebujecie by były wystawione do Internetu. Hostowanie aplikacji pod nieprzewidywalną subdomeną niewiele pomoże, bo potencjalni atakujący często mogą ją znaleźć korzystając z Certificate Transparency (wystarczy, że subdomena jest wymieniona przy wystawionym dla głównej domeny certyfikacie SSL).

Podatne zależności – wersje 19.0.0, 19.0.1, 19.0.2, 19.1.0, 19.1.1, 19.1.2, 19.1.3, 19.2.0, 19.2.1 i 19.2.2

pakietów:

react-server-dom-webpack

react-server-dom-parcel

react-server-dom-turbopack

Podatne są również aplikacje korzystające m.in. z Next.js w następujących wersjach:

WersjaDoS (CVE-2025-55184)Ujawnienie kodu źródłowego (CVE-2025-55183)Wersja z wdrożonymi poprawkami
>=13.3Podatna14.2.35
14.xPodatna14.2.35
15.0.xPodatnaPodatna15.0.7
15.1.xPodatnaPodatna15.1.11
15.2.xPodatnaPodatna15.2.8
15.3.xPodatnaPodatna15.3.8
15.4.xPodatnaPodatna15.4.10
15.5.xPodatnaPodatna15.5.9
15.x canaryPodatnaPodatna15.6.0-canary.60
16.0.xPodatnaPodatna16.0.10
16.x canaryPodatnaPodatna16.1.0-canary.19

Źródła:

~Tymoteusz Jóźwiak

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



Komentarze

Odpowiedz