Bezpieczeństwo Orientacyjny czas czytania: 12 min ·

PHP2Shell: krytyczna podatność PHP — czy Państwa strona jest zagrożona?

21 października PHP wydało awaryjne poprawki zabezpieczeń dwóch krytycznych podatności, które pozwalają wykonać kod na serwerze bez hasła. Jak w kilka minut ustalić, czy dotyczy to Państwa witryny, co robić najpierw i co robić, gdy nie da się zaktualizować od razu.

Okno przeglądarki z nawiasami kodu i znakiem ostrzeżenia — krytyczna podatność PHP PHP2Shell

21 października PHP wydało awaryjne poprawki zabezpieczeń dwóch krytycznych podatności, które pozwalają wykonać kod na serwerze bez hasła. Jak w kilka minut ustalić, czy dotyczy to Państwa witryny, co robić najpierw i co robić, gdy nie da się zaktualizować od razu.

Podatne są wszystkie wersje PHP, które w swojej gałęzi są starsze niż 8.5.12, 8.4.27, 8.3.36 i 8.2.35, a to oznacza prawie każdą stronę internetową na PHP, której w tym tygodniu nikt nie zaktualizował. Dziś pierwsza rzecz to ustalić, która wersja obsługuje Państwa witrynę, i ją zaktualizować — pełnego obejścia nie ma, a samo ogłoszenie PHP mówi, że aktualizacja jest jedynym bezpiecznym wyborem.

W środę, 21 października, zespół PHP wydał jednocześnie cztery wersje awaryjne; para podatności, które te wersje naprawiają, dostała nazwę PHP2Shell, i nazwa opisuje rezultat precyzyjnie: od żądania sieciowego do wykonania kodu na serwerze. Ten artykuł jest o tym, co dokładnie znaleziono, jak rozpoznać, czy dotyczy to Państwa, i w jakiej kolejności działać — także wtedy, gdy nie da się zaktualizować od razu.

Czym jest PHP2Shell i co stało się 21 października

W oficjalnym ogłoszeniu jest powiedziane, że 8.5.12, 8.4.27, 8.3.36 i 8.2.35 naprawiają dwie krytyczne podatności, które mogą pozwolić nieuwierzytelnionemu atakującemu zdalnie wykonać kod, i że wszystkim użytkownikom PHP zdecydowanie zaleca się natychmiastową aktualizację. Tam też jest zdanie, które rozstrzyga całą resztę treści tego artykułu: pełnego obejścia nie ma, a aktualizacja jest jedynym bezpiecznym wyborem.

Obu podatnościom PHP nadało ocenę 9,2 na 10 według CVSS v4.0, ale są to dwie osobne wady, o różnym mechanizmie i, jak widać niżej, także o różnym stopniu potwierdzenia — i właśnie ta druga różnica w praktyce rozstrzyga, od którego serwera zacząć.

CVE-2026-109618 — uszkodzona pamięć po błędzie out-of-memory (OOM) — gdy PHP zabraknie pamięci, używa longjmp(), żeby przerwać obsługę żądania. Oficjalny opis wskazuje, że w niektórych momentach pamięć żądania jest osiągalna, zanim zostanie w pełni zainicjowana; jeżeli właśnie wtedy alokacja pamięci się nie uda, przerwanie nie jest obsłużone poprawnie i zostaje nieważna pamięć, którą kod zamykający wciąż odczytuje albo na której podstawie podejmuje decyzję.

Ważny szczegół, który zmienia to, kogo ten problem dotyczy: out-of-memory osiąga się specjalnie przygotowanym żądaniem multipart, i nie musi w nim być żadnego przesłanego pliku. Oficjalny opis wymienia kilka problemów obsługi multipart — żądanie bez użytecznej zadeklarowanej długości, część z nieograniczoną liczbą nagłówków, puste pola plików, które nie wliczają się do limitów. To znaczy, że żądanie może być całkiem małe i zmieścić się w zwykłych granicach post_max_size i memory_limit.

CVE-2026-109619 — nieaktualny stan globalny — w procesie PHP między żądaniami zostaje stan globalny: dane błędów, sesji, obiektów i rozszerzeń. Oficjalny opis mówi, że ten stan trzeba zresetować, zanim pamięć żądania zostanie zwolniona; jeżeli reset przerwie błąd krytyczny albo diagnostyka wypełni stan na nowo w chwili zamknięcia, pamięć zostaje zwolniona, ale wskaźnik do niej pozostaje; tę klasę błędów międzynarodowo nazywa się use-after-free — użycie pamięci po jej zwolnieniu.

Dalej jest warunek, który czyni tę podatność trudniejszą, niż brzmi: nieaktualnego wskaźnika może użyć tylko operacja, która dzieje się przed zwykłą inicjalizacją żądania, a oficjalny opis nazywa dwa potwierdzone takie przypadki — diagnostykę INI i obsługę postępu przesyłania w sesji. Do tego późniejsze żądanie atakującego musi trafić dokładnie w ten sam proces, w którym powstał uszkodzony stan, dlatego pojedyncza próba udaje się rzadko, a opis wprost wskazuje, że wiele procesów i ich wymiana zmniejszają szanse, ale samego warunku nie usuwają.

Jak łatwo to wykorzystać i w jakich konfiguracjach jest to potwierdzone

Tu warto być precyzyjnym, bo właśnie w tym miejscu większość artykułów w internecie przesadza w jedną albo w drugą stronę.

Hasło nie jest potrzebne i nie jest też potrzebne, żeby ktoś coś na witrynie kliknął — w wektorze CVSS widać to jako PR:N i UI:N. W tym samym wektorze są jednak AC:H i AT:P: złożoność ataku oceniono jako wysoką i atak ma dodatkowe warunki wstępne. W praktyce oznacza to powtarzane próby, a powodzenie zależy od buildu PHP, rozszerzeń, zachowania frontendu i układu pamięci. A więc nie — jedno zwykłe żądanie nie wystarczy; atakującemu nic to jednak nie kosztuje, bo liczby prób nie ogranicza nic.

Stopień dowodu jest dla obu wad różny i ta różnica ma znaczenie, gdy wybiera się, jak bardzo się spieszyć. W przypadku CVE-2026-109618 pełne zdalne wykonanie kodu (RCE) jest potwierdzone wobec mod_php przy domyślnych limitach wejścia i pamięci; o PHP-FPM ten sam opis mówi, że analiza kodu źródłowego uznaje je za podatne, ale pełny atak na PHP-FPM nie został zademonstrowany. FrankenPHP jest tam wymieniony jako analog mod_php, a LSAPI jako analog PHP-FPM, w obu przypadkach bez sprawdzonego ataku.

W przypadku CVE-2026-109619 ścieżka cyklu życia sesji jest sprawdzona zarówno wobec mod_php, jak i PHP-FPM, natomiast druga ścieżka, która idzie przez ślad błędu krytycznego, jest potwierdzona tylko wobec mod_php.

Wynika z tego praktyczna kolejność: jeżeli Państwa witryna działa na mod_php, są Państwo pierwsi w kolejce, bo tam obie wady są potwierdzone; w przypadku PHP-FPM i LiteSpeed ryzyko jest realne, ale na razie potwierdzone częściowo; w żadnym z tych przypadków nie jest to powód, żeby czekać — to powód, żeby wiedzieć, od którego serwera zacząć.

Jak ten tydzień wyglądał godzina po godzinie

Chronologia nie jest ciekawostką — wyjaśnia, dlaczego zalecenia z pierwszych godzin różniły się od tych, które obowiązują teraz, i dlaczego część artykułów w internecie wciąż jest przestarzała.

Wieczorem 20 października było wiadomo, że coś nadchodzi, ale nie było wiadomo co: PHP ogłosiło nadchodzące wydanie awaryjne, a strona statusu CloudLinux tego samego wieczoru odnotowuje, że dane techniczne i dotknięte wersje są planowane do publikacji przy wydaniu następnego dnia; opis techniczny nie był wtedy jeszcze publiczny.

Do następnego dnia sytuacja zmieniła się, i nie na lepsze: rankiem 21 października CloudLinux odnotowuje, że w publicznym obiegu jest już próbka ataku, i o 9:08 UTC rozsyła zestaw reguł zapory, który blokuje znany wzorzec żądania wykorzystującego podatność. Osiemnaście minut później na tej samej stronie pojawia się zdanie, które ten tydzień opisuje najlepiej — próby zgodne z tym wzorcem są już obserwowane, a więc ktoś już szukał serwerów, które jeszcze nie mają poprawki.

Poprawki zabezpieczeń PHP wyszły o 14:00 UTC, co znaczy, że między publicznie dostępną próbką ataku a publicznie dostępną poprawką minęło kilka godzin i w tych godzinach próby ataku już trwały.

Jedno zastrzeżenie warto tu powiedzieć uczciwie: świat nie był całkiem bez poprawki, bo w ogłoszeniu PHP jest powiedziane, że dystrybucje Linuksa i dostawcy wsparcia długoterminowego (LTS) dostali poprawki wcześniej, dlatego dla części serwerów aktualizacja była dostępna wcześniej niż dla pozostałych — publicznie dostępna nie była jednak dla nikogo.

Potem zaczęła się dłuższa część, która trwa nadal: dystrybucja pakietów; opiekunowie systemów operacyjnych i platformy hostingowe budują swoje pakiety osobno i pojawiają się one w ciągu godzin albo dni, każdy we własnym tempie. Na tym etapie jest duża część użytkowników hostingu współdzielonego i dlatego pytanie „czy poprawka już wyszła” i pytanie „czy poprawka jest na moim serwerze” są w tym tygodniu dwoma różnymi pytaniami, z różnymi odpowiedziami.

Czy Państwa strona jest zagrożona

W oficjalnych ostrzeżeniach zakresy dotkniętych wersji są zapisane tak: wszystko starsze niż 8.2.35, wszystko starsze niż 8.3.36, wszystko starsze niż 8.4.27 i wszystko starsze niż 8.5.12 — każde w swojej gałęzi.

Ważny szczegół, który sprzyja pomyłce: liczba, którą pokazuje php -v, nie zawsze mówi wszystko. Dystrybucje Linuksa i platformy hostingowe często przenoszą poprawkę na starszą wersję, nie zmieniając jej numeru — zmienia się tylko numer wydania pakietu. W takim razie 8.4.26 może już mieć poprawkę, ale może też jej nie mieć. Jedyny sposób, żeby to wiedzieć, to zajrzeć do opisu pakietu albo zapytać dostawcę; sam numer wersji na to pytanie nie odpowiada.

Osobno o starszych wersjach: PHP 8.1 i starsze nie dostają już od projektu PHP regularnych aktualizacji, ale ze względu na wagę zespół bezpieczeństwa przygotował minimalne poprawki kodu źródłowego dla wersji 7.4, 8.0 i 8.1 — dla tych, którzy budują ze źródeł albo nie mają dostępu do wsparcia opiekuna. Ogłoszenie w tym samym miejscu zaleca kontakt z własnym dostawcą, bo część dystrybucji i dostawców wsparcia długoterminowego poprawki przenosi. Jeżeli Państwa witryna działa na PHP 7.x, prawdziwym problemem nie jest ten tydzień — prawdziwy problem jest taki, że następnym razem poprawki może też nie być. A PHP 8.2, które tym razem poprawkę dostało, osiąga koniec wsparcia 31 grudnia 2026 roku.

Jak sprawdzić wersję, zależnie od tego, gdzie strona działa

Sprawdzenie zajmuje minuty i warto zrobić je dla każdej witryny osobno, a nie dla każdego serwera: na jednym serwerze często działają witryny na różnych wersjach PHP, i zwykle właśnie ta najstarsza, o której wszyscy zapomnieli, jest publicznie osiągalna.

Hosting współdzielony z cPanelem — wersję pokazuje dział MultiPHP Manager, w którym każda domena ma własny wiersz; Plesk do tego samego używa PHP Settings wewnątrz każdej subskrypcji. W obu przypadkach warto upewnić się, że patrzą Państwo na tę domenę, o którą chodzi, a nie na domyślne ustawienie serwera.

Własny serwer albo VPS (wirtualny serwer prywatny) — w wierszu poleceń pokazuje to php -v, ale z jednym istotnym zastrzeżeniem: PHP w wierszu poleceń często jest zupełnie inną wersją niż to, które obsługuje żądania WWW. Najpewniejszą odpowiedź daje ta sama droga, którą działa witryna — plik wykonywalny wskazany w sekcji pool konfiguracji PHP-FPM.

Kontenery — jeżeli witryna działa w Dockerze, wersję wyznacza obraz, a nie maszyna hosta, dlatego są dwa kroki: przebudować obraz na zaktualizowanym obrazie bazowym i potem zrestartować kontenery. Obraz zbudowany przed 21 października poprawki nie zawiera, niezależnie od tego, jak często kontener był restartowany.

Jeżeli nie mają Państwo dostępu do żadnego z nich — wtedy pytanie jest do dostawcy hostingu i w tym tygodniu jest to zupełnie zwykłe pytanie, na które odpowiedź już mają przygotowaną. Sformułowanie, które oszczędza wymianę wiadomości: „Która wersja PHP obsługuje moją domenę, czy jest w niej poprawka zabezpieczeń na PHP2Shell i, jeżeli jeszcze jej nie ma, w jakim dniu będzie?”

Co robić dziś

Dzisiejsza kolejność jest taka: najpierw zaktualizować PHP i zrestartować wszystko, co je wykonuje, potem upewnić się, że odwiedzających naprawdę obsługuje nowa wersja, następnie sprawdzić, czy używane repozytorium pakietów w ogóle wydało poprawkę, i dopiero potem szukać śladów. Pierwszy krok zajmuje minuty, ostatni może zająć dni i właśnie dlatego nie warto zamieniać ich miejscami.

Po pierwsze, proszę zaktualizować — w Managed Hostingu (hostingu zarządzanym) robi to dostawca, a Państwa zadaniem jest zadać pytanie i dostać datę. Jeżeli serwerem zarządzają Państwo sami, po aktualizacji pakietów trzeba zrestartować to, co wykonuje PHP: Apache, PHP-FPM albo LSAPI. Ten krok jest pomijany zaskakująco często — pakiet jest wymieniony, ale stare procesy dalej pracują na starym kodzie, więc sprawdzenie pokazuje nową wersję, podczas gdy odwiedzających obsługuje stara.

Po drugie, proszę sprawdzić, że aktualizacja naprawdę została zastosowana — tą samą drogą, którą działa witryna, a nie przez wiersz poleceń.

Po trzecie, jeżeli korzystają Państwo z repozytorium pakietów utrzymywanego przez ochotników, proszę sprawdzić, czy wydało ono poprawkę. W ogłoszeniu PHP jest osobne ostrzeżenie o rpms.remirepo.net: jego użytkownikom zaleca się przejście na pakiety dystrybucji albo budowanie ze źródeł.

Po czwarte, i dopiero potem proszę sprawdzić, czy na witrynie nie ma śladów; aktualizacja zamyka drzwi, ale nie odpowiada na pytanie, czy ktoś już nimi wszedł.

Jeżeli nie da się zaktualizować od razu

Tę część warto czytać ze świadomością, że żaden z wymienionych tu kroków nie zastępuje aktualizacji — ogłoszenie PHP mówi to wprost.

Wobec CVE-2026-109618 ogłoszenie wymienia zdjęcie limitu pamięci: memory_limit=-1, i to tak, żeby aplikacja nie mogła go nadpisać — na przykład przez php_admin_value w konfiguracji PHP-FPM albo Apache, po upewnieniu się, że żadne inne ustawienie nie przywraca skończonego limitu. Trzeba rozumieć, ile ten wybór kosztuje: na serwerze współdzielonym zamienia jedno ryzyko na drugie, bo jedno żądanie może teraz zjeść całą dostępną pamięć. W opisie podatności jest też ostrzeżenie, żeby nie używać RLIMIT_AS i RLIMIT_DATA, bo mogą sprawić, że alokacja pamięci się nie uda, i w ten sposób doprowadzić właśnie do podatnej ścieżki.

Wobec CVE-2026-109619 ogłoszenie wymienia session.upload_progress.enabled=0 i, w przypadku PHP 8.5, fatal_error_backtraces=0 — w obu przypadkach ze wskazaniem, żeby potem zrestartować wszystkie procesy. W samym opisie podatności jest też pm.max_requests=1, które każe PHP-FPM po każdym żądaniu wymienić worker PHP-FPM; to ustawienie puli PHP-FPM, i tam jest podane z zastrzeżeniem „jeżeli wydajność nie jest czynnikiem”. W tym samym miejscu jest też powiedziane to, co trzyma ten środek we właściwych granicach: wymiana procesów zmniejsza szanse na jedno żądanie, ale samego warunku nie usuwa.

Przydatne jest też to, co nie jest obejściem, ale zmniejsza powierzchnię ataku: zachowawczy post_max_size, rozsądna głębokość zagnieżdżenia danych wejściowych i ograniczona wielkość przesyłania; to są dobre wartości w każdym tygodniu, nie tylko w tym.

Jak rozpoznać, czy są już Państwo dotknięci

Po aktualizacji warto przejrzeć logi serwera WWW z ostatnich dni: szukać należy nietypowo dużej liczby żądań multipart pod ten sam adres — i tu łatwo szukać źle: zwykle są małe i mieszczą się w zwykłych limitach, więc po rozmiarze się ich nie znajdzie. Wymowniejsze są nagłe serie błędów 500, które zaczynają się i kończą bez widocznej przyczyny: atak oparty na out-of-memory nie udaje się znacznie częściej, niż się udaje, i każda nieudana próba zostawia błąd.

W systemie plików liczą się czasy zmian: plik PHP zmieniony w nocy, kiedy nikt nie pracował, trzeba wyjaśnić. Warto sprawdzić też zaplanowane zadania i wpisy, które zapewniają automatyczne uruchomienie po restarcie — atakujący z wykonaniem kodu najpierw utrwala dostęp, żeby przetrwał tę aktualizację, którą Państwo właśnie zainstalowali.

Osobno warto sprawdzić listę kont administratorów oraz hasła i klucze aplikacji; jeżeli wykonanie kodu nastąpiło, wszystko, co serwer wie, trzeba uznać za odczytane — także dane logowania do bazy i klucze API w pliku konfiguracyjnym.

Jeżeli coś z tego nie wygląda prawidłowo, czyszczenie jest osobną pracą, z własną kolejnością, i warto robić je metodycznie, a nie kasując podejrzane pliki po jednym. Opisaliśmy to osobno — jak przebiega odzyskiwanie zhakowanej witryny, a jeżeli chcą Państwo, żeby zrobił to ktoś inny, odzyskiwanie zaatakowanych stron internetowych jest osobną usługą o stałej kolejności: izolacja, czyszczenie, usunięcie przyczyny i sprawdzenie, że witryna została zdjęta z list ostrzeżeń wyszukiwarek.

Kiedy zdarzenie staje się incydentem, który trzeba zgłosić

Jeżeli jest powód sądzić, że atakujący uzyskał dostęp do danych osobowych, pytanie techniczne staje się także prawne. RODO przewiduje termin, który liczy się nie od ataku, lecz od chwili, w której administrator stwierdza naruszenie ochrony danych osobowych: w miarę możliwości nie później niż w terminie 72 godzin od tej chwili zgłasza się je organowi nadzorczemu — w Polsce Prezesowi UODO. Obowiązek nie powstaje, gdy jest mało prawdopodobne, by naruszenie skutkowało ryzykiem naruszenia praw lub wolności osób fizycznych, a gdy ryzyko jest wysokie, trzeba poinformować także same osoby — ten obowiązek ma w rozporządzeniu własne wyjątki.

Praktyczne znaczenie tej części jest jedno: chwila, w której w logach znajduje się coś podejrzanego, nie jest chwilą, w której zaczynają biec 72 godziny — to chwila, w której trzeba ustalić, czy naruszenie ochrony danych osobowych w ogóle nastąpiło. Pojedyncza seria błędów 500, która, jak opisano wyżej, najczęściej jest nieudaną próbą, sama w sobie nie jest naruszeniem ochrony danych osobowych. Właśnie dlatego tego ustalenia nie warto odkładać na „kiedy będzie mniej pracy”, i właśnie dlatego logi trzeba zachować, zanim nadpisze je rotacja: są jedynym dowodem zarówno na to, co się stało, jak i na to, co się nie stało.

Jeżeli pod Państwa opieką jest kilka stron internetowych

Dla agencji i firm z kilkoma witrynami ten tydzień jest mniej zadaniem technicznym, a bardziej organizacyjnym, i kolejność, która działa, jest prosta: najpierw lista, potem wersje, potem aktualizacja według priorytetu.

Priorytetu nie wyznacza ważność witryny, lecz osiągalność i to, co ją obsługuje. Na górze są publicznie dostępne witryny na mod_php, bo tam obie podatności są potwierdzone; potem reszta tego, co publiczne, i dopiero następnie systemy wewnętrzne za zaporą. Środowiska testowe i deweloperskie, o których wszyscy zapominają, trzeba na listę wpisać obowiązkowo — często działają na starszej wersji PHP i często są osiągalne z internetu, bo kiedyś tak było wygodniej.

Witryny, którymi zarządza ktoś inny, na liście zostają, ale z inną kolumną: komu wysłano pytanie i którego dnia przyszła odpowiedź. Ta kolumna później okazuje się cenniejsza od pozostałych, bo ona pokazuje, który dostawca odpowiada, a który nie.

Co w tym przypadku znaczył Managed Hosting

Ten tydzień dobrze pokazuje, gdzie przebiega granica między platformą a aplikacją, dlatego uczciwie jest powiedzieć, jak to wyglądało z naszej strony.

Nasze serwery działają na CloudLinuxie i mają wbudowany Imunify360. Gdy próbka ataku zaczęła krążyć publicznie, CloudLinux na swojej stronie statusu odnotował, że zestaw reguł zapory blokujący znany wzorzec wykorzystania został rozesłany o 9:08 UTC — kilka godzin przed tym, jak PHP wydało samą poprawkę o 14:00, i zanim na tej samej stronie pojawił się wpis, że próby są już obserwowane. W ciągu dnia poszły jeszcze dwa uzupełnienia, z których drugie blokuje już publicznie dostępne narzędzie do wykorzystania podatności. Wszystko to stało się automatycznie, bez udziału klienta; w branży taki środek nazywa się virtual patching: reguła zapory aplikacji internetowych (WAF) blokuje wykorzystanie podatności, nie zmieniając samego podatnego kodu.

A teraz to, czego takie zdanie nie znaczy, bo właśnie w tym miejscu branża sprzedała w tym tygodniu najwięcej przesady; reguła zapory blokuje znane wzorce ataku — tego samego słowa używa CloudLinux; ta sama strona nazywa ten środek rozwiązaniem tymczasowym, a nie pełną poprawką; to nie jest niepodatność i sam CloudLinux nadal zaleca zaktualizować PHP, gdy tylko pakiety będą dostępne. Różnica między „chroniona” a „naprawiona” jest w tym tygodniu całkiem konkretna, i sprzedawanie jednego jako drugiego byłoby nieuczciwe.

To, jak wygląda sama poprawka, dobrze ilustruje to, przed czym ostrzegaliśmy wyżej: nasze serwery dostały nowy build ea-php84 wieczorem tego samego dnia, kilka godzin po wydaniu PHP, a numer wersji się nie zmienił — php -v nadal wypisuje 8.4.26, a nie 8.4.27, i jedyne, co z zewnątrz świadczy o zmianie, to data buildu, która przeskoczyła z 9 na 21 października. Właśnie tak wygląda przeniesiona poprawka, i właśnie dlatego pytanie do dostawcy hostingu jest więcej warte niż liczba na ekranie.

Dlatego wartość, którą kupił tu Managed Hosting, to nie niewrażliwość, lecz węższe okno: godziny, w których próbka ataku już krążyła i próby już trwały, zostały przykryte blokowaniem znanego wzorca, a nie przeczekane; potem to, że ktoś śledzi pakiety i restartuje procesy, zamiast czekać, aż klient zauważy; nasz Managed Hosting zaczyna się od 45 € miesięcznie, i właśnie takie tygodnie są tym, za co w tej kwocie się płaci.

Jeżeli Państwa witryna działa teraz tam, gdzie na pytanie o wersję PHP i datę aktualizacji odpowiedzi dostać się nie udaje, to samo w sobie jest odpowiedzią; porozmawiajmy o migracji — migrację zwykle da się zrobić bez przestoju.

Po aktualizacji trzeba zrestartować więcej, niż się wydaje

Proces, który zostaje żywy między żądaniami, nie jest żadną egzotyką — właśnie tak działa zwykła pula PHP-FPM i mod_php, i właśnie wobec nich wykonanie kodu jest potwierdzone, dlatego CVE-2026-109619 nie jest zagrożeniem szczególnych konfiguracji; to problem zwykłej konfiguracji.

Wynika z tego krok, który pomija się najczęściej: wymiana pakietu nie wpływa na proces, który już działa. Po aktualizacji trzeba zrestartować każdy proces, który wykonuje PHP, i dotyczy to także tych, których zwykle nikt nie rusza. Długo działające procesy PHP często nie są restartowane przez tygodnie, dlatego po aktualizacji warto wypisać je osobno i upewnić się, że każdy z nich został podniesiony na nowo.

Właściwe pytanie kontrolne nie brzmi więc „co pokazuje php -v”, tylko „czy każdy proces, który wykonuje PHP, został uruchomiony po tym, jak pakiet został wymieniony”.

Dlaczego nie wystarczy „przecież nic nie przesyłamy”

Częsty zarzut brzmi mniej więcej tak: nasza witryna to wizytówka, nie ma na niej ani formularza przesyłania, ani kont użytkowników, więc to nas nie dotyczy. Niestety dotyczy, a powód jest dokładnie ten, który opisano wyżej: atak nie potrzebuje przesłanego pliku, wystarczy odpowiednio przygotowane żądanie multipart i można je wysłać pod dowolny adres obsługiwany przez PHP. Obecność formularza na stronie nie jest warunkiem wstępnym, bo atakujący formularza nie wypełnia.

Tak samo nie ma znaczenia, czy witryna jest mała: ataki na takie podatności idą szeroką siecią i automatycznie, i wyboru według liczby odwiedzających nikt nie robi. Jednostka Unit 42 Palo Alto Networks w dniu ujawnienia poinformowała o ponad 22,6 miliona instancji PHP osiągalnych z internetu, które potencjalnie są dotknięte; żadna z nich nie została wybrana specjalnie.

Drugi zarzut dotyczy WordPressa i wtyczek; ten też tym razem nie wytrzymuje, tylko w przeciwną stronę: podatność jest w samym PHP, a nie w WordPressie, na Laravelu albo w jakiejś wtyczce. To znaczy, że aktualizacja wtyczek tego problemu nie rozwiązuje, i jednocześnie — że dotknięta jest każda witryna na PHP, niezależnie od tego, na czym jest zbudowana.

Co z tego tygodnia warto zachować

Tym, u których wszystko było w porządku, pomogła nie szybka reakcja, lecz trzy rzeczy ułożone wcześniej: było wiadomo, która witryna działa na której wersji PHP, było wiadomo, kto odpowiada za aktualizację, i były kopie zapasowe, z których naprawdę sprawdzono, że witrynę da się przywrócić. Żadnej z nich nie da się zrobić w dniu, w którym ostrzeżenie jest już opublikowane, i właśnie dlatego ten tydzień dla jednych zespołów był półgodziną pracy, a dla innych dwoma dniami.

Jeżeli z tego tygodnia trzeba wziąć jedno zadanie, żeby następnym razem było łatwiej, to jest nim lista: każda witryna, jej wersja PHP, sposób, w jaki jest wykonywana, jej dostawca hostingu i osoba, która może nacisnąć „aktualizuj”. Następne takie ostrzeżenie nadejdzie, i jedyne pytanie jest takie, ile wtedy zajmie odpowiedź na pytanie „czy nas to dotyczy”.

FAQ

Często zadawane pytania.

Co to jest PHP2Shell?

PHP2Shell to nazwa, którą dostały dwie krytyczne podatności PHP (CVE-2026-109618 i CVE-2026-109619), ujawnione 21 października 2026 roku. Obie mogą pozwolić nieuwierzytelnionemu atakującemu uzyskać wykonanie kodu na serwerze, a obu PHP nadało ocenę 9,2 na 10 według CVSS v4.0. Nazwa opisuje rezultat: od żądania sieciowego do webshella na serwerze.

Która wersja PHP jest bezpieczna?

Bezpieczne są 8.5.12, 8.4.27, 8.3.36 i 8.2.35 albo nowsze. Wszystko, co w swojej gałęzi jest starsze od tych wersji, jest dotknięte. Trzeba pamiętać, że platformy hostingowe często przenoszą poprawkę na starszą wersję, nie zmieniając jej numeru, więc na hostingu współdzielonym sam numer nie zawsze odpowiada na pytanie — wtedy potwierdza to dostawca.

Mam PHP 8.1. Co robić?

PHP 8.1 i starsze wersje nie dostają już regularnych aktualizacji od projektu PHP. Ze względu na wagę zespół bezpieczeństwa przygotował minimalne poprawki kodu źródłowego dla wersji 7.4, 8.0 i 8.1, dla tych, którzy budują ze źródeł albo nie mają dostępu do wsparcia opiekuna. W praktyce są dwie drogi: zapytać dostawcę hostingu, czy poprawkę przeniósł, albo przejść na wersję objętą wsparciem. Druga droga jest jedyną, która rozwiązuje także następnym razem.

Czy zapora chroni mnie, kiedy aktualizuję?

Częściowo i tylko przez pewien czas. Zapora aplikacji internetowych (WAF) blokuje znane wzorce ataku, a w tym przypadku kilku dostawców rozesłało takie reguły przed samą poprawką zabezpieczeń. To jest przydatne, ale to nie jest poprawka zabezpieczeń, a sami dostawcy nazywają to rozwiązaniem tymczasowym. W ogłoszeniu PHP jest powiedziane, że pełnego obejścia nie ma i że aktualizacja jest jedynym bezpiecznym wyborem.

Czy moją witrynę już zhakowano?

Tego nie rozstrzyga numer wersji. Po aktualizacji warto przejrzeć logi serwera WWW z ostatnich dni, zwracając uwagę na nietypowo wiele żądań multipart pod jeden adres i na nagłe serie błędów 500, sprawdzić czasy zmian plików PHP i obejrzeć zaplanowane zadania. Jeżeli coś nie wygląda prawidłowo, czyszczenie jest osobną, metodyczną pracą.

Czy wystarczy zaktualizować WordPressa i wtyczki?

Nie. Podatność jest w samym PHP, a nie w WordPressie ani we wtyczce, dlatego aktualizacja wtyczek jej nie usuwa. Ten sam powód znaczy, że dotknięta jest każda witryna na PHP, niezależnie od tego, czy jest zbudowana na WordPressie, na Laravelu, czy na czymś innym.

Na naszej witrynie nie ma formularza przesyłania. Czy to nas chroni?

Nie. Atak nie potrzebuje przesłanego pliku — wystarczy odpowiednio przygotowane żądanie multipart i można je wysłać pod dowolny adres obsługiwany przez PHP. Obecność formularza na stronie nie jest warunkiem wstępnym. Liczba odwiedzin też nie jest ochroną: takie podatności wykorzystuje się automatycznie i w szerokiej sieci.

Czy po aktualizacji PHP witryna może przestać działać?

Poprawki wyszły jako aktualizacje wewnątrz gałęzi, na przykład z 8.4.26 na 8.4.27. Takie zwykle nie zmieniają zachowania języka na poziomie aplikacji. Sama naprawa CVE-2026-109618 zmienia jednak to, jak PHP zachowuje się przy out-of-memory. Większe ryzyko powstaje wtedy, gdy jednocześnie przechodzi się na inną gałąź, na przykład z 8.1 na 8.3 — warto to najpierw sprawdzić w środowisku testowym. Odkładanie aktualizacji z powodu tego ryzyka nie jest jednak wyborem wyważonym: niezaktualizowana witryna jest wystawiona na znaną, publicznie opisaną podatność.

POWIĄZANA USŁUGA
Odzyskiwanie zaatakowanych stron internetowych

Zaatakowana strona na WordPressie albo Laravelu? Trzeba ją odzyskać po włamaniu? Odzyskujemy ją, czyścimy i utwardzamy konfigurację — zwykle w ciągu 8–72 godzin, z ustaloną przyczyną i usuniętym ostrzeżeniem Google'a.

Więcej informacji