- PHP
- PHP
- Bezpieczeństwo
- Hosting
- Poradnik
php2shell: zaktualizuj PHP, zanim zrobi to ktoś inny
21 października 2026 w PHP zamknięto dwie krytyczne luki. Aktualny framework ich nie zamyka. Zamyka je nowa wersja interpretera i restart procesów, które serwują stronę.
Sygnał z produkcji
-
Problem
Framework jest aktualny, a PHP na serwerze jest sprzed łatki z 21 października 2026.
-
Decyzja
Najpierw wersja interpretera i restart procesów PHP. Przegląd aplikacji dopiero potem.
-
Efekt
Pula, która serwuje stronę, zgłasza wersję z poprawką. Obejścia w php.ini nie zostają jako zabezpieczenie.
Co ogłoszono 21 października
21 października 2026 projekt PHP wydał wersje 8.5.12, 8.4.27, 8.3.36 i 8.2.35. Zamykają dwie luki: CVE-2026-109618 i CVE-2026-109619. Obie mają ocenę 9.2. Potocznie mówi się o nich php2shell.
Obie pozwalają osobie bez logowania na zdalne wykonanie kodu, czyli uruchomienie własnych poleceń na serwerze ze stroną. Tego samego dnia do aktualizacji wezwały CISA, CERT-EU i ENISA. W pierwszej kolejności dotyczy to serwisów wystawionych do internetu.
Przepisu, jak lukę wywołać, tu nie ma. Taki opis już krąży. Dalej jest to, co sprawdzam, zanim uznaję stronę za zabezpieczoną.
To nie jest błąd Twojego kodu
Luki siedzą w interpreterze, nie w szablonie i nie w pluginie. Jedna dotyczy przerwania żądania w momencie, gdy PHP pilnuje limitu pamięci i zostawia niedokończone dane tego żądania. Druga dotyczy stanu poprzedniego żądania, który potrafi zostać w tym samym procesie po błędzie fatalnym. Kolejne żądanie na tym procesie widzi wtedy pamięć, która do niego nie należy.
Przy Apache z mod_php (PHP wbudowane w serwer WWW) pokazano, że wystarczy żądanie z internetu, zanim wystartuje kod aplikacji. Przy PHP-FPM (osobne procesy PHP za serwerem WWW) potwierdzono wejście od strony kodu aplikacji.
Aktualny WordPress, PrestaShop, Laravel albo Symfony tej dziury nie zamyka. Atakujący obchodzi się bez hasła do panelu i bez błędu w kontrolerze. Wystarczy stare PHP, które odpowiada za stronę.
Kogo to dotyczy
Każdej instalacji, która serwuje żądania HTTP: PHP-FPM, mod_php, php-cgi, FrankenPHP, LiteSpeed. Zespół PHP za najwyższe ryzyko uznaje mod_php.
W firmie jest to zwykle strona, sklep, panel klienta albo stare narzędzie wewnętrzne, o którym nikt nie pamięta, że stoi na PHP. Osobna grupa to programy z PHP wbudowanym w środek. Zestawienie takich produktów prowadzi NCSC-NL.
Gałęzie 8.1 i starsze nie dostają już wydań od projektu PHP. Część dystrybucji przenosi łatę we własnych paczkach. Dla osób, które budują PHP ze źródeł i nie mają takiego dostawcy, zespół bezpieczeństwa opublikował minimalne poprawki dla 7.4, 8.0 i 8.1.
Wersje, które domykają lukę
| Gałąź | Wersja z poprawką |
|---|---|
| 8.5 | 8.5.12 |
| 8.4 | 8.4.27 |
| 8.3 | 8.3.36 |
| 8.2 | 8.2.35 |
Poniżej 8.2 zostają dwie drogi: paczka dystrybucji z przeniesioną łatą albo przejście na wspieraną gałąź. Zostawienie 7.4 „bo strona działa” po tym wydaniu jest zgodą na ryzyko przejęcia serwera.
Dystrybucje dostały poprawki przed publicznym ogłoszeniem, więc patrzę na numer paczki, nie na datę komunikatu. Zespół PHP ostrzegł, że repozytorium Remi w dniu wydania aktualizacji nie miało. Tam biorę paczkę dystrybucyjną albo buduję ze źródeł.
Po instalacji restartuję proces, który obsługuje ruch: pulę PHP-FPM albo Apache, gdy PHP jest jego modułem. Konsola potrafi pokazać już nową wersję, a stary proces nadal odpowiada na żądania.
Jak sprawdzić wersję strony
Na własnym serwerze porównuję trzy odczyty:
php -vw konsoli,- wersję puli przypisanej do tej domeny,
- godzinę startu procesu po restarcie.
Na hostingu współdzielonym konsola bywa niedostępna albo pokazuje inną binarkę niż strona. Zostaje panel operatora albo krótki phpinfo(), który ściągam z katalogu strony od razu po odczycie.
Gdy wersji nie widać, proszę operatora o konkret: czy strona jest obsługiwana przez 8.2.35, 8.3.36, 8.4.27 albo 8.5.12, czy przez starszą gałąź z poprawką CVE-2026-109618 i CVE-2026-109619, oraz o której godzinie zrestartowano procesy PHP.
Gdy dziś nie da się zaktualizować
Pełna poprawka jest jedna: nowa wersja i restart. Tak pisze php.net. Obejścia jej nie zastępują.
Do czasu łatki odcinam aplikację od publicznego internetu. Filtr przed aplikacją (WAF) część ruchu odrzuci i instalacji nie uzdrawia.
W komunikacie PHP są ustawienia, które zwężają opisane ścieżki i nadal zostawiają serwer podatnym: brak skończonego memory_limit w miejscu, którego aplikacja nie nadpisze, niższy post_max_size, wyłączenie session.upload_progress.enabled w konfiguracji serwera. ini_set() w skrypcie tego ostatniego nie załatwia, bo ścieżka jest wcześniejsza. Na PHP 8.5 dochodzi fatal_error_backtraces=0. Po zmianie restartuję procesy. Traktuję to jako most na godziny.
Co zostawiam po łatce
Zaczynam od listy: domena, pula, wersja przed i po. Potem paczka, restart i ponowny odczyt z puli, która serwuje stronę.
Po aktualizacji patrzę, czy proces PHP uruchamiał powłokę albo ściągał narzędzia. Na taki ślad wskazuje CISA. Jeśli był, sama łatka jest spóźniona: na serwerze mógł zostać obcy kod i trzeba go oddzielić od zwykłego ruchu aplikacji.
Jeśli nie wiesz, która wersja odpowiada za Twoją stronę, napisz. Najpierw sprawdzę interpreter.
Źródła
Masz podobny problem w swojej firmie?
Porozmawiajmy o możliwych rozwiązaniach. Przeanalizuję Twój system i zaproponuję najlepszą ścieżkę modernizacji.