PHP2Shell to para krytycznych podatności w samym silniku PHP, CVE-2026-109618 i CVE-2026-109619, opublikowanych 21 października 2026 r. z oceną CVSS 9.2. W niezałatanym środowisku uruchomieniowym atakujący bez konta może wykonać kod jako proces roboczy PHP lub odczytać pamięć procesu, w której znajdują się hasła, tokeny sesji, klucze API i certyfikaty. Kod Państwa aplikacji nie musi zawierać błędu: według badaczy narażona może być nawet strona „Hello World” działająca na podatnej wersji PHP. Jedyną prawdziwą poprawką jest poprawione wydanie PHP, a po nim ponowne uruchomienie każdego procesu, który wykonuje PHP. Ten przewodnik zawiera potrzebne polecenia.
Które wersje zostały poprawione
| Gałąź | Podatne | Poprawione w |
|---|---|---|
| 8.2 | poniżej 8.2.35 | 8.2.35 |
| 8.3 | poniżej 8.3.36 | 8.3.36 |
| 8.4 | poniżej 8.4.27 | 8.4.27 |
| 8.5 | poniżej 8.5.12 | 8.5.12 |
PHP 8.1, 8.0 i 7.x nie są już wspierane i nie otrzymają poprawki. Jeśli nadal Państwo z nich korzystają, łatką jest przejście na wspieraną gałąź.
Dystrybucje Linuksa często przenoszą poprawki bezpieczeństwa do własnych pakietów (backport), nie zmieniając numeru wersji na zgodny z upstreamem. W takich systemach sam numer wersji nie mówi wystarczająco dużo: należy sprawdzić, czy changelog pakietu zawiera oba numery CVE (krok 2).
Krok 1: odszukanie każdego środowiska PHP
Warto zacząć od inwentaryzacji, bo atakowane jest zwykle to środowisko, o którym nikt nie pamiętał. Na każdym serwerze:
php -v
systemctl list-units --type=service --all 'php*' 'apache2*' 'httpd*'
ls /usr/sbin/php-fpm* /usr/bin/php[0-9]* 2>/dev/null
Pierwsza linia pokazuje wersję CLI, druga działające pule PHP-FPM i serwery WWW, a trzecia każdą wersję PHP zainstalowaną równolegle (częste źródło zapomnianych środowisk). Należy też wyświetlić zainstalowane pakiety:
dpkg -l 'php*' | grep '^ii' # Debian, Ubuntu
rpm -qa 'php*' 'ea-php*' # RHEL, AlmaLinux, Rocky, cPanel
W przypadku kontenerów trzeba sprawdzić wersję PHP w każdym uruchomionym obrazie:
docker ps --format '{{.Names}}' | while read c; do printf '%s: ' "$c"; docker exec "$c" php -r 'echo PHP_VERSION, PHP_EOL;' 2>/dev/null || echo 'no php'; done
Proszę nie zapominać o serwerach testowych (staging), serwerach cron i kolejek, agentach buildów oraz planach hostingu zarządzanego. W przypadku hostingu warto zapytać dostawcę na piśmie, z jakiej kompilacji PHP Państwo korzystają i kiedy została załatana.
Krok 2: instalacja poprawionego wydania
Debian i Ubuntu (8.3 należy zastąpić własną gałęzią):
sudo apt update
sudo apt install --only-upgrade 'php8.3*'
apt changelog php8.3-fpm | grep -E 'CVE-2026-10961[89]'
RHEL, AlmaLinux, Rocky Linux:
sudo dnf upgrade 'php*'
rpm -q --changelog php-fpm | grep -E 'CVE-2026-10961[89]'
Serwery cPanel z pakietami EasyApache 4:
sudo dnf upgrade 'ea-php*' # older systems: sudo yum update 'ea-php*'
Alpine Linux (nazwy pakietów zawierają gałąź, np. php83):
apk update && apk upgrade 'php83*'
Obrazy Docker: w pliku Dockerfile należy przypiąć poprawiony tag, na przykład FROM php:8.3.36-fpm, a następnie przebudować obraz bez cache i zastąpić działające kontenery:
docker build --pull --no-cache -t myapp:php2shell .
docker compose up -d --build --force-recreate
Jeśli grep w changelogu niczego nie wypisuje, dystrybucja nie udostępniła jeszcze poprawki. Warto sprawdzać dalej, tam, gdzie kompilują Państwo PHP samodzielnie, użyć oficjalnego wydania z php.net, a w międzyczasie wdrożyć opisane niżej środki tymczasowe.
Krok 3: ponowne uruchomienie wszystkiego, co załadowało stare PHP
Nowy pakiet niczego nie zmienia w procesach, które już działają. Trzeba je uruchomić ponownie:
sudo systemctl restart php8.3-fpm # Debian, Ubuntu (one per installed version)
sudo systemctl restart php-fpm # RHEL family
sudo systemctl restart apache2 # Apache with mod_php (httpd on RHEL)
sudo supervisorctl restart all # long-running workers under Supervisor
php artisan queue:restart # Laravel queue workers
W Debianie i Ubuntu polecenie sudo needrestart -r l wyświetla usługi, które nadal korzystają ze starych bibliotek.
Krok 4: weryfikacja
Należy ponownie sprawdzić każde środowisko, tym razem to, którego używa serwer WWW, a nie tylko CLI:
php-fpm8.3 -v # or: php-fpm -v
systemctl status php8.3-fpm | grep Active
Wersja musi być równa poprawionemu wydaniu lub wyższa (albo changelog pakietu musi wymieniać oba CVE), a czas „Active: since” musi być późniejszy niż aktualizacja. W WordPressie wersję można też odczytać w menu Narzędzia, Kondycja witryny, Informacje, Serwer. Proszę nie publikować strony phpinfo(), aby to sprawdzić: ujawnia ona dokładnie to, czego szukają atakujący.
Gdy aktualizacja musi poczekać
Te ustawienia zalecane przez badaczy zmniejszają ekspozycję na atak na czas przygotowania aktualizacji. Nie są poprawką:
; php.ini
post_max_size = 8M ; as low as your uploads allow
max_input_nesting_level = 32 ; as low as your forms allow
session.upload_progress.enabled = 0
fatal_error_backtraces = 0 ; where your PHP version supports it
; PHP-FPM pool: recycle workers more often (costs performance)
pm.max_requests = 100
Wartości są przykładowe; należy je przetestować z własną aplikacją. Ustawienie memory_limit = -1 blokuje niektóre ścieżki ataku, ale można go używać wyłącznie razem z limitem na poziomie systemu operacyjnego, takim jak memory.max w cgroup v2, i nigdy nie należy zastępować tego limitu przez RLIMIT_AS ani RLIMIT_DATA. Reguły WAF i CDN dostawcy pomagają jako rozwiązanie przejściowe, ale nie zastępują aktualizacji.
Szukanie oznak ataku
Nie istnieje jedna reguła wykrywania. Te polecenia wydobywają sygnały opisane przez badaczy:
grep -E 'Allowed memory size of [0-9]+ bytes exhausted' /var/log/php*-fpm.log /var/log/apache2/error.log
grep -E 'exited on signal (6|11)' /var/log/php*-fpm.log
awk '$9 == 500' /var/log/nginx/access.log | wc -l
Błędy limitu pamięci po nietypowych żądaniach multipart, nagłe serie odpowiedzi HTTP 500, procesy robocze PHP kończące działanie po sygnale oraz nietypowo duże ciasteczka PHPSESSID w odpowiedziach wymagają bliższego przyjrzenia się. Żaden z tych sygnałów nie dowodzi ataku, a ich brak nie dowodzi, że atak Państwa nie dotyczył. Jeśli Państwo je znajdą, należy zachować logi, wdrożyć poprawkę i zmienić sekrety, które znajdowały się w pamięci PHP: hasła do baz danych, klucze aplikacji i tokeny API. Nasz zespół reagowania na incydenty może przejąć dochodzenie, a nasze zarządzane usługi bezpieczeństwa mogą monitorować Państwa serwery po wdrożeniu poprawki.
Od czego zacząć
- Uruchomić polecenia inwentaryzacyjne na każdym serwerze i w każdym kontenerze oraz zapisać każdą wersję PHP.
- Zaktualizować pakiety menedżerem pakietów lub przebudować obrazy na poprawionym tagu.
- Ponownie uruchomić PHP-FPM, Apache i każdy proces roboczy PHP.
- Sprawdzić wersję i czas ponownego uruchomienia oraz zachować wynik jako dowód.
- Przeszukać logi grepem pod kątem opisanych wyżej oznak i zmienić sekrety w każdym systemie, w którym się pojawiły.
Szczegóły: strona z informacjami o PHP2Shell, komunikat PHP Foundation, Wiz Research.

