Przejdź do treści
INDEKS ANALIZ BREACHROAD / NOTA TECHNICZNA

Apache Struts CVE-2026-73634 i 73635: dwa wejścia, ten sam heap DoS

Raporty CSP bez limitu i nieograniczony cache lokalizacji pozwalają zapełnić stertę Javy. Analizujemy S2-073, S2-074, obejścia i aktualizacje.

MATERIAŁ PUBLICZNY
AUTOR
/ CEO Breachroad · OSCP · PNPT
PUBLIKACJA
15 sierpnia 2026
CZAS CZYTANIA
15 min czytania
TEMAT
Podatności i CVE
Apache Struts CVE-2026-73634 i 73635: dwa wejścia, ten sam heap DoS

15 sierpnia 2026 roku opublikowano rekordy CVE-2026-73634 i CVE-2026-73635 dla Apache Struts. Obie podatności prowadzą do zdalnego wyczerpania pamięci procesu Java, ale wykorzystują inne zasoby. Pierwsza pozwala przesłać nieograniczony raport naruszenia Content Security Policy, który aplikacja wczytuje do pamięci. Druga powoduje nieograniczony wzrost cache tekstów lokalizowanych za pomocą wartości locale kontrolowanej przez żądanie.

Apache opisuje problemy w biuletynach S2-073 i S2-074. Oba mają ocenę 7,5 w CVSS 3.1 w rekordach CVE. Poprawki znajdują się w Struts 6.11.0 oraz 7.3.0. Choć producent klasyfikuje maksymalną wagę jako moderate, z perspektywy operatora publicznej aplikacji pojedynczy nieuwierzytelniony klient może zakłócić dostępność całej usługi.

CVE-2026-73634: raport CSP bez granicy

Content Security Policy pozwala przeglądarce raportować naruszenia, na przykład próbę załadowania skryptu z niedozwolonej domeny. Struts udostępnia opcjonalny mechanizm zbierania takich raportów. Endpoint jest zwykle publiczny, ponieważ żądanie wysyła automatycznie przeglądarka użytkownika, a nie zalogowany administrator.

W podatnych wersjach raport był odczytywany do pamięci bez limitu. Rozmiar alokacji rósł więc wraz z treścią żądania. Klient mógł wysłać wyjątkowo duże ciało i zmusić JVM do zużycia sterty, kosztownego garbage collection, a ostatecznie błędu OutOfMemoryError lub utraty responsywności.

Ważne ograniczenie ekspozycji: rdzeń Struts nie mapuje endpointu raportów domyślnie. Samo włączenie wsparcia CSP również go nie publikuje. Podatne są aplikacje, które jawnie skonfigurowały trasę zbierającą raporty. Administrator nie powinien więc zakładać ryzyka tylko na podstawie wersji, ale też nie może uznać braku widocznego formularza za dowód bezpieczeństwa. Mapowanie może znajdować się w konfiguracji wdrożenia.

Poprawione wersje odczytują raport do limitu. Domyślnie jest to 8192 znaków, a wartość można zmienić przez struts.csp.report.maxSize w zakresie od 1 do 1048576. Raport większy niż limit jest odrzucany i logowany jako ostrzeżenie. To istotne, ponieważ ograniczenie powstaje w warstwie, która rozumie semantykę funkcji, a nie dopiero po alokacji.

CVE-2026-73635: cache sterowany przez locale

Druga luka nie wymaga dużego pojedynczego żądania. Struts wykonuje wyszukiwanie tekstów lokalizowanych dla komunikatów walidacji, konwersji typów i innych elementów. Jeżeli aplikacja nie ustawi stałego locale, framework może przyjąć lokalizację z żądania klienta.

W podatnych wersjach wewnętrzne cache nie miały skutecznej granicy liczby wpisów. Atakujący może generować wiele różnych wartości locale i powodować tworzenie kolejnych kombinacji cache. Każde żądanie może być małe, lecz pamięć rośnie kumulacyjnie. To inny profil DoS: zamiast jednego ogromnego body mamy serię tanich bodźców, które pozostawiają trwały ślad w stercie.

Problem obejmuje szeroki zakres: Struts 2.0.0–2.3.37, 2.5.0–2.5.33, 6.0.0–6.10.0 i 7.0.0–7.2.1. Linie 2.3 i 2.5 są niewspierane, więc organizacja nie powinna traktować konfiguracji obejścia jako długoterminowego rozwiązania.

W 6.11.0 i 7.3.0 cache są ograniczone, a maksymalny rozmiar można skonfigurować przez struts.i18n.cacheMaxSize. Opcja struts.locale.validateRequestLocale może dodatkowo ograniczać lokalizacje z żądania do zestawu dostępnego w runtime. Walidacja locale jest domyślnie wyłączona, dlatego zespół powinien świadomie dobrać ustawienia.

Dwa różne modele wyczerpania zasobów

Pierwsza podatność jest proporcjonalna do rozmiaru wejścia: napastnik wysyła dużo bajtów, serwer alokuje dużo pamięci. Reverse proxy z limitem body może skutecznie zmniejszyć ryzyko, o ile limit obowiązuje na właściwej trasie i żądanie nie omija proxy.

Druga jest proporcjonalna do różnorodności wejścia. Każdy request może mieścić się w małym limicie, ale nowa wartość tworzy nowy stan w cache. Ograniczenie rozmiaru body nie pomoże. Potrzebne są limity kardynalności, walidacja do znanego zbioru, limit cache lub stała lokalizacja.

To rozróżnienie ma znaczenie w threat modelingu. Rate limiting ogranicza tempo obu ataków, ale nie usuwa przyczyny. Duży burst można odciąć na przepustowości, natomiast powolne zapełnianie cache może zmieścić się w normalnym profilu żądań i ujawnić dopiero po wielu godzinach.

Kto powinien reagować najpierw

Każdy zespół używający Apache Struts powinien ustalić dokładną wersję w artefakcie produkcyjnym. Dla CVE-2026-73634 sprawdź mapowania akcji związanych z raportami CSP i publiczną osiągalność endpointu. Dla CVE-2026-73635 sprawdź, czy ustawiono struts.locale na stałą, wspieraną wartość.

Najwyższy priorytet mają aplikacje dostępne z Internetu, działające z małym limitem heap, współdzielące JVM z innymi komponentami albo restartowane automatycznie bez mechanizmu ograniczającego pętlę awarii. W klastrze atak może być powtarzany na kolejnych podach, a autoscaling może jedynie zwiększyć koszt incydentu.

Nie polegaj wyłącznie na nagłówku Server ani skanerze zewnętrznym. Struts bywa spakowany w WAR i ukryty za proxy. Przejrzyj SBOM, zależności Maven/Gradle, zawartość obrazu oraz klasy faktycznie załadowane podczas uruchomienia.

Aktualizacja i obejścia

Użytkownicy linii 6.x powinni przejść co najmniej do 6.11.0, a użytkownicy 7.x do 7.3.0. Stare linie EOL wymagają migracji do wspieranej wersji. Przed produkcją przetestuj walidację, lokalizację komunikatów, raporty CSP i niestandardowe klasy rozszerzające akcję raportową.

Jeżeli aktualizacja CVE-2026-73634 musi poczekać, usuń mapowanie endpointu raportów CSP. Gdy funkcja jest wymagana, ustaw limit body w reverse proxy lub kontenerze servletów. Apache zaznacza, że struts.csp.report.maxSize istnieje dopiero w wersji poprawionej, więc nie jest obejściem na starym frameworku.

Dla CVE-2026-73635 ustaw stałe struts.locale. Wtedy lookup nie używa locale z żądania i podatna ścieżka znika. To dobre ograniczenie tymczasowe, jeżeli aplikacja naprawdę obsługuje jeden język. System wielojęzyczny powinien przejść na wersję z ograniczonym cache i walidować tylko potrzebne lokalizacje.

Obserwowalność i wykrywanie

Dla raportów CSP monitoruj rozmiar żądań, czas odczytu body, odpowiedzi 413/500 i wzrost pamięci bez odpowiadającego wzrostu ruchu biznesowego. Nietypowo duże POST-y do endpointu raportowego są silnym wskaźnikiem. Logowanie pełnej treści może jednak podwoić zużycie i ujawnić dane, więc zapisuj metadane, nie całe body.

Dla locale analizuj liczbę unikalnych wartości w krótkim oknie, rozmiar cache i tempo alokacji. Warto odróżnić wspierane wartości, takie jak pl-PL czy en-US, od losowych kombinacji. Wskaźniki JVM — occupancy old generation, częstotliwość full GC, czas pauz i liczba restartów — powinny być skorelowane z trasami i parametrami wejściowymi.

Alarm dopiero na OutOfMemoryError jest spóźniony. Wcześniejsze sygnały to rosnący baseline heap po kolejnych cyklach GC, pogarszający się czas odpowiedzi oraz brak powrotu pamięci do wcześniejszego poziomu. W Kubernetes sprawdzaj OOMKilled, ale pamiętaj, że limit kontenera może zadziałać przed diagnostyką JVM.

Inżynierska lekcja: budżet dla każdego wejścia

Każde niezaufane wejście zużywa zasób: bajty w pamięci, wpisy cache, wątki, deskryptory lub czas CPU. Bezpieczny projekt definiuje maksymalny koszt pojedynczego żądania oraz maksymalny stan pozostający po wielu żądaniach. Te CVE pokazują oba wymiary jednocześnie.

Cache musi mieć limit, politykę eviction i ograniczony zbiór kluczy. Parser body musi zakończyć odczyt po przekroczeniu granicy, a nie najpierw przyjąć całość i dopiero sprawdzić długość. Limity powinny obowiązywać w kilku warstwach: edge chroni pojemność platformy, a framework chroni semantykę konkretnej funkcji.

Testy wydajnościowe powinny zawierać wejścia wrogie, ale bezpieczne dla środowiska testowego: rosnący body, wiele unikalnych kluczy, rozłączanie klientów i powolne żądania. Celem nie jest tylko pomiar średniego latency, lecz potwierdzenie, że koszt ma twardą górną granicę.

Fakty i wnioski Breachroad

Faktem jest, że CVE-2026-73634 dotyczy wyłącznie aplikacji mapujących endpoint raportów CSP i wersji Struts 6.0.0–6.10.0 oraz 7.0.0–7.2.1. CVE-2026-73635 ma szerszy zakres, ale aplikacje ze stałym locale nie są dotknięte. Poprawki są dostępne w 6.11.0 i 7.3.0. Biuletyny nie dowodzą masowego wykorzystania.

Wnioskiem Breachroad jest potraktowanie problemów jako audytu zarządzania zasobami, a nie dwóch sygnatur WAF. Jeśli endpoint może bez granicy powiększać body lub cache, podobne błędy mogą istnieć w uploadach, parserach, sesjach i telemetrii. Aktualizacja zamyka znane ścieżki, a przegląd budżetów usuwa całą klasę ryzyka.

Jeśli chcesz zweryfikować odporność aplikacji i API na nadużycia zasobów, zobacz testy penetracyjne aplikacji webowych i API. Dla zespołów Java, platform i utrzymania przygotowujemy również szkolenia cyberbezpieczeństwa dla organizacji o bezpiecznych limitach i detekcji degradacji.

UDOSTĘPNIJ / KOPIUJ