PHP2Shell to dwie krytyczne luki w samym interpreterze PHP — CVE-2026-109618 i CVE-2026-109619, obie z oceną CVSS 9.2 — które pozwalają wykonać kod na serwerze bez logowania i odczytać pamięć procesu PHP z hasłami i kluczami API. Jedyną pełną naprawą jest aktualizacja PHP do 8.5.12, 8.4.27, 8.3.36 lub 8.2.35 (wydane 21 października 2026) i restart wszystkich procesów PHP; aktualizacja WordPressa czy wtyczek tej luki nie usuwa.
Co się stało 21 października 2026
21 października 2026 roku zespół PHP opublikował wersje 8.5.12, 8.4.27, 8.3.36 i 8.2.35, które łatają dwie krytyczne podatności w rdzeniu języka, nazwane przez odkrywców PHP2Shell. Luki znaleźli badacze Wiz Research, OpenAI Codex Security i Calif. Szczegóły wyciekły do sieci jeszcze przed planowaną publikacją, dlatego PHP wydało poprawki z jednodniowym wyprzedzeniem (około 15:50 czasu polskiego), a firmy bezpieczeństwa już tego samego dnia raportowały pierwsze próby wykorzystania.
CERT Polska wydał dwa komunikaty (195/2026 i 196/2026) z zaleceniem natychmiastowej aktualizacji i — tam, gdzie się nie da — tymczasowej zmiany ustawień php.ini albo nawet wyłączenia usług PHP dostępnych z internetu. Skala jest bezprecedensowa: PHP obsługuje około 70% stron internetowych, w tym WordPress, WooCommerce, Joomla, Drupal, Moodle, Nextcloud, Laravel, Symfony i MediaWiki.
To nie jest luka we wtyczce ani w motywie. Podatny jest sam PHP, więc atak działa nawet na stronie z jedną linijką „Hello World”. Aktualizacja WordPressa, Joomli czy sklepu niczego tu nie zmienia — trzeba zaktualizować PHP pod spodem.
Dwie luki prostym językiem
Obie podatności dotyczą zarządzania pamięcią w PHP i obie da się wywołać zwykłym żądaniem HTTP, bez konta w aplikacji. Różnią się mechanizmem:
| CVE-2026-109618 | CVE-2026-109619 | |
|---|---|---|
| Nazwa | RCE przez uszkodzenie przy braku pamięci (OOM) | RCE przez nieaktualny stan globalny |
| Co się psuje | Gdy PHP przekracza memory_limit w trakcie przetwarzania żądania, przerywa pracę w połowie inicjalizacji danych. Sprzątanie po żądaniu traktuje potem niedokończone dane jak poprawne. | Część stanu żądania (błędy, sesja, obiekty) przeżywa zwolnienie pamięci. Następne żądanie obsłużone przez ten sam proces korzysta z już zwolnionej pamięci (use-after-free). |
| Jak atakujący to wywołuje | Spreparowany formularz multipart: brak Content-Length, nieograniczone nagłówki części, puste pola plików, głęboko zagnieżdżone nazwy pól. | Wywołanie błędu krytycznego lub braku pamięci, a potem mechanizm, który czyta stary stan — np. postęp wysyłania plików w sesji (włączony domyślnie) albo fatal_error_backtraces w PHP 8.5. |
| Skutek | Wykonanie kodu jako użytkownik procesu PHP | Odczyt pamięci procesu albo wykonanie kodu |
| Ocena | CVSS 4.0: 9.2 (krytyczna) | CVSS 4.0: 9.2 (krytyczna) |
Najgroźniejsza jest druga konsekwencja, o której mówi się mniej: wyciek pamięci procesu. W pamięci PHP leżą hasła do bazy danych, tokeny sesji, klucze API bramek płatności i certyfikaty — także należące do innych żądań. Badacze pokazali odczyt takiej pamięci niezależnie od aplikacji, bez wykonywania żadnego złośliwego kodu, co jest trudne do wykrycia narzędziami szukającymi infekcji.
Kogo dotyczy: wersje i sposoby uruchamiania PHP
Podatne są praktycznie wszystkie wersje PHP od 5.4 wzwyż i każdy sposób uruchamiania PHP obsługujący ruch z sieci: Apache z mod_php, PHP-FPM, php-cgi, FrankenPHP i LiteSpeed (LSAPI). Zespół PHP uznaje ryzyko za największe przy mod_php, gdzie potwierdzono przejęcie serwera domyślną konfiguracją, zanim jakikolwiek kod aplikacji się uruchomi.
| Linia PHP | Podatne | Pierwsza bezpieczna wersja | Uwagi |
|---|---|---|---|
| 8.5 | < 8.5.12 | 8.5.12 | dodatkowo ustaw fatal_error_backtraces = 0, jeśli nie możesz zaktualizować |
| 8.4 | < 8.4.27 | 8.4.27 | wsparcie aktywne |
| 8.3 | < 8.3.36 | 8.3.36 | tylko poprawki bezpieczeństwa |
| 8.2 | < 8.2.35 | 8.2.35 | koniec wsparcia 31.12.2026 |
| 8.1, 8.0, 7.4 | wszystkie | brak wydania od PHP | tylko łatki dystrybucji/dostawcy LTS albo minimalne backporty źródeł |
| 5.x, 7.0–7.3 | wszystkie | brak wydania od PHP | jak wyżej — najlepiej przejść na 8.3 lub 8.4 |
Dystrybucje Linuksa (Debian, Ubuntu, RHEL, AlmaLinux, CloudLinux) często wstawiają łatkę do starszego numeru wersji. „PHP 8.1.2” z repozytorium Ubuntu może więc być bezpieczne, a „PHP 8.3.35” zbudowane ze źródeł — nie. Rozstrzyga lista zmian pakietu, a nie sam numer.
Jak sprawdzić, czy Twoja strona jest podatna
Ustal wersję PHP, na której działa strona.
W WordPressie: Narzędzia → Zdrowie witryny → Informacje → Serwer. W panelu hostingu: ustawienia PHP domeny. Z konsoli:
php -v(uwaga: wersja w konsoli bywa inna niż ta, która obsługuje stronę).Porównaj z tabelą powyżej.
Jeśli masz 8.2–8.5 poniżej wersji bezpiecznej — jesteś podatny. Jeśli masz 8.1 lub starsze, sprawdź u dostawcy, czy pakiet ma backport łatki.
Przy pakietach z dystrybucji sprawdź listę zmian.
RHEL, AlmaLinux, CloudLinux:
rpm -q --changelog php-common | grep -E "CVE-2026-10961[89]". Debian, Ubuntu:apt changelog php8.3-common | grep -E "CVE-2026-10961[89]". Pusta odpowiedź oznacza brak łatki.Zinwentaryzuj wszystko, co ma w sobie PHP.
Nie tylko strony: obrazy Dockera (np.
php:8.3-fpm), panele administracyjne, phpMyAdmin, Roundcube, systemy newsletterowe, urządzenia typu appliance. Każde z nich ma własne PHP i każde wymaga osobnej aktualizacji.
Co zrobić: aktualizacja krok po kroku
Aktualizacja PHP jest jedyną pełną naprawą — wszystkie poniższe łagodzenia tylko zawężają drogi ataku. Kolejność działań dla administratora serwera:
Zainstaluj poprawione PHP.
Ze źródeł php.net albo z pakietów dystrybucji:
dnf update php*/apt upgrade. CloudLinux:yum update "alt-php*"(iea-php*w cPanelu). Repozytorium Remi (rpms.remirepo.net) w dniu publikacji nie miało aktualizacji — zespół PHP zalecał przejście na pakiety dystrybucji albo kompilację ze źródeł.Zrestartuj wszystkie procesy PHP.
PHP-FPM (
systemctl restart php-fpmlubphp8.3-fpm), Apache z mod_php, procesylsphpLiteSpeed, długo działające workery (kolejki Laravel, Swoole, RoadRunner). Bez restartu w pamięci dalej działa stary, podatny kod.Zaktualizuj obrazy kontenerów.
Pobierz nowy obraz bazowy (
docker pull php:8.3-fpm), przebuduj własne obrazy i odtwórz kontenery. Przy gotowych aplikacjach w kontenerach poczekaj na nowe wydanie od producenta.PHP 8.1 i starsze: zaplanuj przesiadkę.
Projekt PHP nie wyda już dla nich poprawek. Na czas przejścia sprawdź, czy dostawca systemu (CloudLinux, TuxCare, Red Hat) ma backport — a potem przenieś stronę na PHP 8.3 lub 8.4.
Sprawdź po aktualizacji.
Wersja PHP widoczna dla strony (nie tylko w konsoli), logi błędów, działanie formularzy i wysyłania plików. Poprawka wprowadza nowy, twardy limit pamięci: proces, który go przekroczy, kończy się natychmiast, bez uruchamiania funkcji zamykających — sprawdź importy i eksporty, które zużywają dużo pamięci.
Gdy nie możesz zaktualizować od razu: łagodzenia w php.ini
Zespół PHP i CERT Polska podają zestaw ustawień, które blokują potwierdzone ścieżki ataku. Żadne z nich nie czyni instalacji bezpieczną — to most do czasu aktualizacji. Wpisz je w głównym php.ini albo w konfiguracji puli FPM (php_admin_value), nie przez ini_set() ani .user.ini, bo te działają za późno, już po przetworzeniu żądania.
; php2shell — tymczasowo, do czasu aktualizacji PHP session.upload_progress.enabled = 0 ; CVE-2026-109619, ścieżka potwierdzona fatal_error_backtraces = 0 ; tylko PHP 8.5 post_max_size = 32M ; 8M, jeśli strona nie przyjmuje plików upload_max_filesize = 24M ; zawsze mniej niż post_max_size max_input_nesting_level = 16 display_errors = 0 expose_php = 0
session.upload_progress.enabled = 0— blokuje potwierdzoną ścieżkę CVE-2026-109619. Funkcja jest włączona domyślnie, a prawie żadna strona z niej nie korzysta; zespół PHP radzi zostawić ją wyłączoną także po aktualizacji.fatal_error_backtraces = 0(PHP 8.5) — blokuje drugą potwierdzoną ścieżkę tej samej luki.- Niski limit
post_max_size— 8M dla stron bez wysyłania plików, 32M, gdy pliki są potrzebne. Ogranicza pamięć, którą atakujący może zająć jednym żądaniem (CVE-2026-109618). Podobny limit warto ustawić na serwerze WWW lub proxy, także dla żądań bez nagłówka Content-Length. memory_limit = -1— zalecenie CERT Polska i zespołu PHP dla CVE-2026-109618: usuwa limit pamięci, na którym opiera się atak, ale przerzuca kontrolę na system operacyjny. Stosuj tylko razem z limitem cgroup (kontener, LVE,memory.max) i ustawieniem, którego aplikacja nie może nadpisać. Po aktualizacji wróć do skończonego limitu.- Nie używaj
RLIMIT_ASaniRLIMIT_DATAjako zastępczego limitu pamięci — mogą wywołać dokładnie tę podatną ścieżkę. - Usuń przestarzałe dyrektywy ustawiane per katalog (np.
php_valuew.htaccesszauto_detect_line_endings, starymiassert.*,session.sid_lengthw PHP 8.4+ alboreport_memleaks=0w 8.5). Ostrzeżenia, które generują przed startem żądania, są jednym z wyzwalaczy CVE-2026-109619. Ukrycie ich przezerror_reportingczy@nie pomaga. - Niższe
pm.max_requestsw PHP-FPM — procesy częściej się odnawiają, więc uszkodzony stan krócej żyje. Kosztuje wydajność i nie chroni przed atakiem w jednym żądaniu.
CERT Polska w pierwszym komunikacie zalecał też rozważenie tymczasowego wyłączenia usług PHP dostępnych z internetu, jeśli nie zaburzy to działalności. Przy sklepie czy stronie firmowej zwykle się nie da — tym bardziej liczy się czas do aktualizacji.
Czy WAF, Cloudflare albo firewall hostingu wystarczą?
Nie. Dostawcy zapór aplikacyjnych (Cloudflare, Imperva, Akamai, Imunify360) w dniu publikacji wydali reguły blokujące znany kształt publicznego exploita. To tzw. wirtualna łatka: zatrzyma automatyczne skanery i pierwszą falę ataków, ale żądanie zbudowane trochę inaczej przez nią przejdzie. CloudLinux przyznał na przykład, że jego pierwsza wersja reguł na serwerach LiteSpeed tylko zapisywała próbę w logu, zamiast ją blokować.
WAF warto mieć włączony i zaktualizowany — to dodatkowa warstwa. Ale strona za Cloudflare z niezałatanym PHP nadal jest podatna, a wyciek pamięci w ogóle nie musi wyglądać podejrzanie dla reguł szukających złośliwego kodu.
Jak rozpoznać próbę ataku w logach
Nie istnieje jedna reguła, która wykryje każdy wariant, a podatny kod działa poniżej aplikacji, więc logi WordPressa czy sklepu zwykle niczego nie pokażą. Odkrywcy wskazują sygnały, od których warto zacząć analizę:
- nietypowo duże lub zniekształcone ciasteczka PHPSESSID w odpowiedziach serwera,
- nietypowe żądania multipart (formularze z plikami), po których pojawiają się błędy limitu pamięci albo serie odpowiedzi HTTP 500,
- niewyjaśnione awarie i restarty procesów PHP (
child exited on signalw logach FPM, padającelsphp).
# Odpowiedzi 500 na żądania multipart (formularze z plikami) — szukaj serii z jednego IP
grep -E '"POST [^"]*" 500 ' access_log | awk '{print $1}' | sort | uniq -c | sort -rn | head
# Błędy limitu pamięci i padające workery PHP
grep -E 'Allowed memory size of|Out of memory|exited on signal|child .* exited' error_log | tail -50
# Nietypowo długie ciasteczka PHPSESSID (w logach, które je zapisują)
grep -oE 'PHPSESSID=[^; "]{80,}' access_log | headBrak tych śladów nie dowodzi, że serwer jest czysty — część ataków odczytuje pamięć bez pozostawiania wyraźnego wpisu. Jeśli coś znajdziesz, zgłoś incydent do CERT Polska przez incydent.cert.pl.
Po aktualizacji: co jeszcze zabezpieczyć
Jeśli strona działała na podatnym PHP po 21 października 2026, a szczególnie jeśli w logach są podejrzane sygnały, załóż, że sekrety z pamięci procesu mogły wyciec. Lista działań po aktualizacji:
Zmień hasło do bazy danych
i wpisz nowe w
wp-config.php/.envaplikacji.Wygeneruj nowe klucze i sole WordPressa
(
AUTH_KEY,SECURE_AUTH_KEYi pozostałe) — to wyloguje wszystkich użytkowników i unieważni skradzione ciasteczka.Unieważnij klucze API
bramek płatności, kurierów, SMTP, systemów mailingowych, Google i innych integracji przechowywanych w konfiguracji.
Sprawdź konta administratorów
i ostatnio zmienione pliki PHP (np.
find . -name "*.php" -newermt 2026-10-20). Przeskanuj stronę skanerem złośliwego kodu.Uporządkuj ustawienia tymczasowe
przywróć skończony
memory_limit, zostawsession.upload_progress.enabled = 0, ustawexpose_php = 0, utrzymujpost_max_sizewyraźnie poniżej limitu pamięci.Zaplanuj aktualizacje na stałe
PHP 8.2 kończy wsparcie 31 grudnia 2026. Stały rytm aktualizacji PHP i spis wszystkich miejsc, gdzie PHP działa, skracają reakcję przy następnej takiej luce z dni do godzin.
Co zrobił Aderlo Cloud
Aderlo Cloud to polski hosting WordPress i WooCommerce na serwerach LiteSpeed z CloudLinuxem, na którym klienci wybierają wersję PHP od 7.4 do 8.5. Wieczorem 21 października 2026 roku zespół Aderlo Cloud wykonał na wszystkich serwerach z PHP następujące działania:
- Natywne PHP 8.3 serwera zaktualizowane do 8.3.36 — tego samego dnia, w którym ukazała się poprawka.
- Łagodzenia w php.ini dla wszystkich 14 wersji PHP dostępnych dla klientów (5.4–8.5): wyłączony
session.upload_progress, a w PHP 8.5fatal_error_backtraces. Ustawienia wpisane w głównyphp.ini, który obowiązuje przed przetworzeniem żądania — sprawdziliśmy je z wnętrza kont klientów, nie z konta administratora. - Audyt przestarzałych dyrektyw PHP w
.htaccess,.user.inii ustawieniach kont: żadna strona nie ustawia dyrektyw, które wyzwalają CVE-2026-109619 przed startem żądania. - Zapora aplikacyjna Imunify360 z regułami 8.85 z 21 października, które rozpoznają narzędzie PHP2Shell.
- Automatyczna instalacja łatek CloudLinux dla wersji PHP z selektora: serwer co 20 minut sprawdza repozytoria i instaluje poprawione pakiety, gdy tylko się ukażą, po czym restartuje procesy PHP i porównuje odpowiedzi próbki stron klientów na każdej wersji PHP sprzed i po aktualizacji. Gdy któraś strona zacznie zwracać błąd, aktualizacja cofa się sama, a zespół dostaje alarm.
- Aplikacje w kontenerach (np. NetSendo) dostały te same łagodzenia; obrazy aktualizujemy, gdy producent wyda wersję na poprawionym PHP.
Klienci Aderlo Cloud nie muszą niczego robić w sprawie samego PHP. Jeśli Twoja strona nadal działa na PHP 7.4 lub 8.0, to dobry moment, żeby przełączyć ją na 8.3 w panelu (Hosting → Twoja usługa → Domeny → Wersja PHP) — starsze wersje są łatane już tylko przez dostawcę systemu, a nie przez projekt PHP.
Hosting WordPress w Aderlo Cloud →Najczęstsze pytania
- Czy aktualizacja WordPressa lub wtyczek chroni przed PHP2Shell?
- Nie. Luka jest w interpreterze PHP, a nie w WordPressie. Badacze pokazali przejęcie najnowszych wersji WordPressa, Drupala i Joomli. Trzeba zaktualizować PHP do 8.5.12, 8.4.27, 8.3.36 lub 8.2.35 (albo pakietu z łatką od dostawcy) i zrestartować procesy PHP.
- Czy do ataku potrzebne jest konto na stronie?
- Nie. Pokazane ataki działały bez logowania, zwykłym żądaniem HTTP. Część wariantów wymaga określonych warunków (np. włączonej funkcji postępu wysyłania plików w sesji), dlatego ocena CVSS to 9.2, a nie 10.
- Czy PHP 7.4 i 8.1 dostaną poprawkę?
- Nie od projektu PHP — te wersje nie są już wspierane. Zespół PHP udostępnił jednak minimalne backporty źródeł dla 7.4, 8.0 i 8.1, a dystrybucje i dostawcy LTS (np. CloudLinux, TuxCare, Red Hat) wypuszczają własne pakiety z łatką pod starym numerem wersji. Docelowo stronę trzeba przenieść na PHP 8.3 lub 8.4.
- Czy trzeba zmieniać hasła po aktualizacji?
- Jeśli w logach są ślady prób ataku albo serwer był długo niezałatany — tak. CVE-2026-109619 pozwala odczytać pamięć procesu PHP, w której są hasła do bazy, klucze API i tokeny sesji. Zmień hasło bazy danych, klucze i sole WordPressa oraz klucze integracji.
- Czy wystarczy wyłączyć session.upload_progress?
- Nie. To blokuje jedną potwierdzoną ścieżkę CVE-2026-109619, ale nie dotyka CVE-2026-109618 ani innych wariantów. Wszystkie ustawienia w php.ini są mostem do czasu aktualizacji PHP, nie naprawą.
- Czy hosting współdzielony jest bardziej narażony?
- Luka dotyczy każdego PHP obsługującego ruch z sieci, niezależnie od rodzaju hostingu. Na dobrze zarządzanym hostingu współdzielonym aktualizację PHP i łagodzenia wdraża administrator dla wszystkich stron naraz, a izolacja kont (np. CageFS i LVE w CloudLinuksie) ogranicza skutki przejęcia jednej strony do jednego konta.
Źródła
- PHP — Security advisory: Critical remote code execution vulnerabilities (21.10.2026)
- PHP — GHSA-w8hw-w9fx-j79w: RCE via OOM corruption (CVE-2026-109618)
- PHP — GHSA-6wmf-4rv5-p3rp: RCE via stale global state (CVE-2026-109619)
- CERT Polska — komunikat 195/2026
- CERT Polska — komunikat 196/2026 (php2shell)
- PHP2Shell — strona odkrywców
- Wiz Research — PHP2Shell
- CloudLinux — PHP CVE-2026-109618 i CVE-2026-109619
- CERT Polska — zgłoszenie incydentu