LW IT Solutions logo LW IT Solutions logo LW IT Solutions
« Przegląd bloga /Tworzenie stron internetowych / PHP2Shell: skuteczna ochrona i problem witryn bez...
Ten artykuł w innych językach:

PHP2Shell: skuteczna ochrona i problem witryn bez aktualizacji

PHP2Shell: skuteczna ochrona i problem witryn bez aktualizacji

Management Summary

PHP2Shell oznacza krytyczne błędy PHP, oprogramowania obsługującego wiele witryn. Ochrona wymaga rzeczywistego działania poprawionej wersji na każdej stronie; sama instalacja aktualizacji lub poprawne logowanie tego nie potwierdzają. Zapomniane instalacje i niejasna odpowiedzialność za utrzymanie mogą pozostawić luki. Artykuł łączy inwentaryzację, sprawdzone aktualizacje i badanie możliwych wcześniejszych ataków. Aktualizacja usuwa podatność, lecz nie skutki istniejącego włamania.

Spis treści
  1. Nowe informacje: próby ataku przed publikacją
  2. Co kryje się pod nazwą PHP2Shell?
  3. Które aktualizacje zapewniają ochronę?
  4. Od aktualizacji pakietu do ochrony usługi
  5. Skutki braku aktualizacji
  6. Czy administratorzy rzeczywiście zainstalują poprawki?
  7. Ile witryn pozostanie zagrożonych?
  8. Linux w praktyce: inwentaryzacja faktycznie używanego środowiska
  9. Aktualizacja PHP 8.4 przez APT
  10. Aktualizacja PHP 8.5 przez APT
  11. Aktualny pakiet nie potwierdza aktualnego procesu
  12. PHP 7.4: poprawka bezpieczeństwa zamiast niezmienionego 7.4.33
  13. Ślady ataku: łączenie zdarzeń z kilku zapisów
  14. Rozpoznawanie PHP2Shell w logach: podejrzenie to jeszcze nie dowód
  15. Pierwsze zapytania do logów w Linuksie
  16. Lepsze logowanie bez gromadzenia treści formularzy
  17. Ochrona przed zakończeniem aktualizacji
  18. Konkretne ślady włamania: oddzielna naprawa i obsługa incydentu
  19. Pytania i odpowiedzi
  20. Źródła

Stan na 25 października 2026 r. PHP wykonuje na serwerze kod wielu witryn, między innymi WordPressa. Dwa krytyczne błędy PHP mogą w określonych warunkach pozwolić na wykonanie obcych poleceń bez logowania. Nazwa tych błędów to PHP2Shell. Poprawki obu są dostępne od 21 października. Kluczowe jest sprawdzenie, czy witryna rzeczywiście korzysta już z poprawionego PHP. Osobny błąd sesji opisany 23 października został wyjaśniony poniżej. [1] [6]

Nowe informacje: próby ataku przed publikacją

AWS zaobserwował próbę ataku PHP2Shell 17 października 2026 r., przed publicznym ujawnieniem błędów. Dane pochodzą z MadPot: celowo dostępnych systemów-pułapek rejestrujących ataki. Przy kolejnych próbach nie było jasne, czy atak na rzeczywisty serwer zakończyłby się powodzeniem. Nie jest to liczba ofiar na świecie. Badanie zagrożonej instalacji powinno więc obejmować także okres sprzed ujawnienia. AWS: własne obserwacje i ograniczenia

Co kryje się pod nazwą PHP2Shell?

Identyfikatory błędów to CVE-2026-109618 i CVE-2026-109619. Numery CVE pozwalają jednoznacznie wskazać lukę. Przy pierwszym błędzie PHP może po wyczerpaniu pamięci uznać niepełne dane za prawidłowe. Przy drugim pozostają odwołania do zwolnionej pamięci, z których może skorzystać kolejne żądanie. Oba błędy znajdują się w samym PHP. [3] [4]

Sprawdzenia wymagają także stare gałęzie PHP. cPanel wymienia podatne wersje od PHP 5 i podaje poprawione wydania własnych pakietów. Przejście z PHP 7 na dowolną wersję PHP 8 nie jest więc wystarczającym dowodem. Potrzebna jest konkretna wersja pakietu z potwierdzonym usunięciem obu błędów. [7]

W Apache z mod_php PHP działa wewnątrz serwera WWW. Potwierdzony atak może tam nastąpić jeszcze przed wykonaniem kodu witryny. PHP-FPM obsługuje natomiast żądania w osobnych procesach PHP, zwanych workerami i grupowanych w pule. PHP Foundation potwierdza wykonanie obcego kodu także przez FPM, zależnie od aplikacji. Logowanie do WordPressa nie zapewnia więc ochrony przed tymi błędami PHP. [2]

Które aktualizacje zapewniają ochronę?

Oficjalne poprawki obu błędów zawierają wersje 8.2.35, 8.3.36, 8.4.27 i 8.5.12. W danej gałęzi potrzebna jest taka lub nowsza poprawiona wersja. PHP 8.1 i starsze gałęzie nie otrzymują już regularnych wydań projektu PHP. Wyjątkowo udostępniono niewielkie poprawki kodu dla 7.4, 8.0 i 8.1. Dostawca może przenieść poprawkę do starszego pakietu; taki zabieg to backport. Nie oznacza to wznowienia ogólnego wsparcia starej gałęzi. [1]

Backport może zachować pierwotny numer wersji PHP. Dodatkowa rewizja pakietu wskazuje wtedy zmienione wydanie dostawcy. Liczą się pełna wersja pakietu i potwierdzenie usunięcia obu CVE. Ani stary numer podstawowy, ani etykieta „PHP 8” nie wystarczają do oceny. [7]

Dodatkowy komunikat z 23 października: konfiguracja sesji

PHP opisuje kolejny nietypowy przypadek pod numerem CVE-2026-115560: ustawienie session.serialize_handler wskazuje php_binary lub php_serialize, aplikacja przełącza format na php przez ini_set() przed session_start(), a zapis postępu przesyłania pozostaje aktywny. Te nazwy oznaczają różne formaty zapisu danych sesji. PHP zaleca session.upload_progress.enabled=0 do następnego regularnego wydania z poprawkami. Według PHP aplikacje bez takiej zmiany formatu podczas działania mogą pozostawić funkcję włączoną. Komunikat uzupełnia dwie aktualizacje z 21 października; pełny opis zapowiedziano na następne wydanie. PHP: komunikat o sesjach z 23 października 2026 r.

Cztery etapy: inwentaryzacja, poprawienie obu podatności, wymiana działających procesów i kontrola obsługi stron
Poprawka musi trafić do działającej usługi WWW.

Od aktualizacji pakietu do ochrony usługi

  1. Inwentaryzacja: Zakres obejmuje domeny, pule PHP, kontenery, zapomniane instalacje testowe i wbudowane panele administracyjne.
  2. Potwierdzenie poprawki: Każde środowisko wymaga udokumentowania źródła pakietu, rewizji i usunięcia obu podatności.
  3. Wymiana działających instancji: Procesy PHP muszą załadować poprawiony kod. Kontener startuje z przygotowanego pakietu programu i środowiska, zwanego obrazem. Własne kontenery wymagają nowego obrazu z poprawionym PHP, a następnie uruchomienia nowych kontenerów z tego obrazu. Aktualizacja otaczającego serwera nie zmienia istniejącego obrazu. [8]
  4. Kontrola obsługi WWW: Wiersz poleceń może korzystać z innej instalacji PHP niż witryna. Weryfikację zamyka przypisanie domeny do faktycznie działającego środowiska i sprawdzenie podstawowych funkcji.

W przypadku braku możliwości natychmiastowej aktualizacji ENISA zaleca rozważenie izolacji publicznie dostępnych aplikacji. Statyczna strona techniczna obsługiwana przed PHP może zatrzymać ruch do podatnego środowiska. Wtyczka trybu konserwacji działająca wewnątrz tej samej aplikacji PHP nie zapewnia takiego oddzielenia w sposób niezawodny. [5]

Ustawienia tymczasowe zamykają tylko niektóre drogi ataku. session.upload_progress.enabled=0 wyłącza zapisywanie postępu przesyłania pliku w danych sesji. Blokuje to określone drogi związane z sesjami, lecz nie zastępuje obu aktualizacji. memory_limit=-1 również nie usuwa błędów całkowicie i może zwiększać ryzyko awarii przy dużym zużyciu pamięci. PHP odradza w tym celu limity systemowe RLIMIT_AS i RLIMIT_DATA: nieudany przydział pamięci nadal może uruchomić podatny kod. Mechanizm cgroup w Linuksie ogranicza zużycie zasobów przez grupy procesów, ale także nie stanowi pełnej naprawy. [3] [4]

Skutki braku aktualizacji

Punktem wyjścia jest wykonanie kodu z uprawnieniami procesu WWW, a nie automatyczne uzyskanie pełnych uprawnień administratora (root). Zależnie od uprawnień i dostępnych sekretów możliwe następstwa obejmują kradzież danych dostępowych do bazy, ujawnienie danych klientów, zmianę treści, instalację złośliwego oprogramowania oraz nadużycie kluczy API. Dostępne usługi wewnętrzne mogą stać się kolejnym celem, jeśli pozwalają na to połączenia sieciowe i uprawnienia. [3]

W sklepie internetowym zmieniona strona płatności może wyrządzić większe szkody niż widoczna awaria. Dochodzą koszty analizy, odtwarzania, przestoju i utraty zaufania. Późniejsza aktualizacja nie usuwa wcześniej zainstalowanej furtki. Konkretne ślady włamania wymagają izolacji, zabezpieczenia dowodów, kontroli danych dostępowych i odtworzenia z zaufanego stanu.

Czy administratorzy rzeczywiście zainstalują poprawki?

Ocena: Szybki początkowy spadek liczby zagrożonych instalacji jest prawdopodobny; pełne zakończenie aktualizacji w ciągu kilku dni wydaje się mało realne. Centralnie utrzymywane platformy mogą poprawić wiele witryn jednocześnie. Własne serwery zależą od odpowiedzialności, dostępności pakietów, zgodności i kontrolowanych restartów. Google Cloud wyraźnie rozróżnia środowiska aktualizowane automatycznie oraz usługi wymagające ponownego wdrożenia. [8]

Najtrudniejsza pozostanie zapewne grupa porzuconych projektów, starych wdrożeń agencyjnych, kontenerów bez procesu utrzymania i aplikacji zależnych od niewspieranych gałęzi. Opóźnienia nie oznaczają automatycznie zaniedbania administratorów. Brak budżetu, niejasny podział odpowiedzialności i niesprawdzone zależności starszych aplikacji mogą organizacyjnie zablokować prostą technicznie poprawkę. Konkretna globalna skuteczność aktualizacji byłaby obecnie spekulacją.

Ile witryn pozostanie zagrożonych?

W3Techs podaje na 25 października 2026 r. udział PHP wynoszący 69,2 procent witryn o rozpoznanym języku programowania po stronie serwera. Wśród rozpoznanych witryn PHP wersja 7 stanowi 26,8 procent, a wersja 5 — 7,7 procent, łącznie 34,5 procent. Te dane opisują wykryte użycie. Nie wskazują, które witryny otrzymały już poprawki bezpieczeństwa. [9]

Nie wynika z tego wiarygodna bezwzględna liczba nadal zagrożonych witryn. Poprawki dostawców, różnice konfiguracji, ukryte numery wersji oraz wiele witryn na jednym serwerze uniemożliwiają proste przeliczenie. Pojedyncze podstrony, domeny i serwery są ponadto różnymi jednostkami zliczania.

Wyłącznie ilustracja rachunkowa: w grupie miliona faktycznie podatnych instalacji skuteczne ukończenie 95 proc. aktualizacji pozostawiłoby 50 000 bez poprawki. To ani pomiar, ani prognoza. Obliczenie pokazuje jedynie, dlaczego nawet wysoki poziom ukończenia aktualizacji może pozostawić znaczącą grupę zagrożonych systemów. Dla konkretnej witryny potwierdzony stan poprawki ma większą wartość niż globalny procent.

Linux w praktyce: inwentaryzacja faktycznie używanego środowiska

Poniższe przykłady dotyczą systemów Debian/Ubuntu z APT i już skonfigurowanymi zaufanymi repozytoriami. Odpowiednia gałąź PHP musi być wcześniej zainstalowana. Systemy RPM, panele hostingowe i własne kontenery wymagają procedury właściwego dostawcy. Dodanie przypadkowego zewnętrznego repozytorium nie jest wiarygodną strategią naprawy.

Przed zmianą potrzebne są możliwa do odtworzenia kopia zapasowa, przypisanie każdej domeny do puli PHP i krótki plan testów. Instalacja pakietów może ponownie uruchomić usługi jeszcze przed zakończeniem polecenia. Okno serwisowe zaczyna się więc przed instalacją. Poniższa lista obejmuje między innymi PHP w wierszu poleceń (CLI) i usługi. Oddzielnie trzeba ustalić, z której instalacji PHP korzysta serwer WWW dla każdej witryny.

ShellLinux: inwentaryzacja PHP
cat /etc/os-release
command -v php
php -v
php --ini
dpkg-query -W -f='${binary:Package}\t${Version}\n' 'php*' 'libapache2-mod-php*' 2>/dev/null
systemctl list-units --type=service --all | grep -E 'php.*fpm|apache2|nginx'
ps -eo pid,lstart,comm | grep -E 'php|apache2'

Domena może korzystać z PHP 8.4 przez FPM, podczas gdy polecenie php wskazuje na 8.5. Dodatkowe kopie mogą istnieć w kontenerach, katalogach hostingu i zapomnianych usługach testowych. Potwierdzenie dla każdej instalacji wymaga źródła pakietu, pełnej rewizji, usługi lub kontenera oraz przypisanych witryn.

Aktualizacja PHP 8.4 przez APT

Przebieg wybiera już zainstalowane pakiety gałęzi 8.4, w tym obecne rozszerzenia i moduł Apache. Najpierw odczytywana jest pełna lista pakietów; błąd odczytu przerywa działanie. Następnie wybierane są pakiety 8.4. Symulacja APT niczego nie instaluje. „Kandydat” oznacza wersję, którą APT zainstalowałby. Potrzebne jest co najmniej PHP 8.4.27 albo backport potwierdzony dla obu błędów. Dla Debiana 13 udokumentowana poprawiona wersja to 8.4.27-1~deb13u1. Dokumentacja APT Debian: CVE-2026-109618 Debian: CVE-2026-109619

ShellPHP 8.4: repozytorium i plan aktualizacji
set -euo pipefail
branch=8.4
sudo apt-get update
package_rows=$(dpkg-query -W -f='${db:Status-Abbrev} ${binary:Package}\n')
selected_rows=$(awk -v branch="$branch" '
  $1 == "ii" && ($2 == "php" branch ||
    index($2, "php" branch ":") == 1 ||
    index($2, "php" branch "-") == 1 ||
    $2 == "libapache2-mod-php" branch ||
    index($2, "libapache2-mod-php" branch ":") == 1) { print $2 }
' <<< "$package_rows")
test -n "$selected_rows"
mapfile -t php_packages <<< "$selected_rows"

apt-cache policy "${php_packages[@]}"
sudo apt-get -s install --only-upgrade "${php_packages[@]}"

Instalacja następuje dopiero po sprawdzeniu planu. Nieoczekiwane usuwanie pakietów, zmiana gałęzi lub nadal podatny kandydat wymagają przerwania procedury. Kolejny blok należy do tej samej sesji Bash i zakłada istniejącą usługę FPM:

ShellPHP 8.4: instalacja i kontrola FPM
sudo apt-get install --only-upgrade "${php_packages[@]}"
sudo /usr/sbin/php-fpm8.4 -t
sudo systemctl restart php8.4-fpm
systemctl is-active php8.4-fpm
/usr/bin/php8.4 -v
/usr/sbin/php-fpm8.4 -v

Aktualizacja PHP 8.5 przez APT

Dla istniejącej instalacji 8.5 obowiązuje analogiczny przebieg z poprawionym kandydatem od 8.5.12 albo potwierdzoną poprawką dostawcy. Standardowe repozytorium Debiana 13 nie udostępnia PHP 8.5 tylko dlatego, że istnieje nowsza gałąź PHP. Brak odpowiedniego kandydata z już zatwierdzonego źródła kończy procedurę przed instalacją.

ShellPHP 8.5: repozytorium i plan aktualizacji
set -euo pipefail
branch=8.5
sudo apt-get update
package_rows=$(dpkg-query -W -f='${db:Status-Abbrev} ${binary:Package}\n')
selected_rows=$(awk -v branch="$branch" '
  $1 == "ii" && ($2 == "php" branch ||
    index($2, "php" branch ":") == 1 ||
    index($2, "php" branch "-") == 1 ||
    $2 == "libapache2-mod-php" branch ||
    index($2, "libapache2-mod-php" branch ":") == 1) { print $2 }
' <<< "$package_rows")
test -n "$selected_rows"
mapfile -t php_packages <<< "$selected_rows"

apt-cache policy "${php_packages[@]}"
sudo apt-get -s install --only-upgrade "${php_packages[@]}"

Kontynuacja również wymaga sprawdzonego planu, tej samej sesji Bash i istniejącej usługi FPM.

ShellPHP 8.5: instalacja i kontrola FPM
sudo apt-get install --only-upgrade "${php_packages[@]}"
sudo /usr/sbin/php-fpm8.5 -t
sudo systemctl restart php8.5-fpm
systemctl is-active php8.5-fpm
/usr/bin/php8.5 -v
/usr/sbin/php-fpm8.5 -v

Apache z mod_php wymaga natomiast zaktualizowanego modułu Apache oraz kontrolowanego restartu po poprawnym teście konfiguracji. W Debianie służy do tego sudo apache2ctl configtest. Aktualizacja PHP w konfiguracji opartej wyłącznie na FPM nie wymaga automatycznie restartu nginx. Oddzielne procesy nadrzędne FPM, stale działające usługi CLI i kontenery wymagają osobnej obsługi. Restart może przerwać aktywne żądania; w środowisku redundantnym wdrożenie powinno następować etapami.

Aktualny pakiet nie potwierdza aktualnego procesu

Linux może utrzymywać proces korzystający ze starego pliku wykonywalnego mimo jego zastąpienia. Nowe wywołanie php -v pokazuje wtedy poprawioną wersję, lecz istniejący proces nadal używa starego kodu. Poniższa kontrola tylko odczytuje informacje i wykrywa procesy PHP korzystające z usuniętego pliku:

ShellWykrywanie starych plików procesów PHP w Linuksie
sudo bash <<'BASH'
for link in /proc/[0-9]*/exe; do
  target=$(readlink "$link" 2>/dev/null) || continue
  case "$target" in
    *php*"(deleted)"*)
      pid=${link#/proc/}
      pid=${pid%/exe}
      printf 'PID %s: %s\n' "$pid" "$target"
      ;;
  esac
done
BASH

Wynik oznacza potrzebę sprawdzenia usługi i wersji, a nie dowód włamania. Pusty wynik też nie potwierdza pełnej ochrony: wyszukiwanie nie obejmuje załadowanych modułów Apache, bibliotek ani innych instalacji PHP. Następnie testy aplikacji obejmują logowanie, przesyłanie plików, formularze, zadania w tle i zadania zaplanowane. Publiczna strona phpinfo() ujawniałaby niepotrzebne szczegóły serwera. Właściwe są chroniona diagnostyka wewnętrzna oraz przypisanie działającego procesu do sprawdzonej instalacji.

PHP 7.4: poprawka bezpieczeństwa zamiast niezmienionego 7.4.33

PHP 7.4 pozostaje niewspierane. Preferowane rozwiązanie to migracja do wspieranej gałęzi albo potwierdzona poprawka w ramach przedłużonego wsparcia dotychczasowego dostawcy (LTS). Na nieunikniony okres przejściowy projekt PHP opublikował minimalną poprawkę kodu źródłowego obejmującą oba identyfikatory PHP2Shell. Nie przywraca to ogólnego wsparcia ani nie gwarantuje naprawy innych podatności.

Stan kodu (commit) zweryfikowany 25 października to 712e60f9edfd03f0960fc4fc3c2c375f42b90aa2. Poniższa procedura jednoznacznie wiąże źródła z tą rewizją. Ponowne zbudowanie niezmienionego wydania 7.4.33 nie zawiera tej poprawki. PHP: konkretny commit bezpieczeństwa

Przykład przekształca kod źródłowy PHP w programy dla wiersza poleceń i FPM. Wymaga oddzielnego, zgodnego środowiska budowania Debian/Ubuntu z Git i certyfikatami CA. Bloki należą do tej samej sesji Bash. Przykład nie jest w pełni sprawdzoną instalacją produkcyjną. Starego kodu PHP nie da się budować z każdą kombinacją aktualnych bibliotek systemowych.

ShellPHP 7.4: wskazanie oficjalnego commitu bezpieczeństwa
set -euo pipefail
workdir=$(mktemp -d "$HOME/php74-php2shell.XXXXXX")
cd "$workdir"
git init php-src
cd php-src
git remote add origin https://github.com/php/php-src.git
commit=712e60f9edfd03f0960fc4fc3c2c375f42b90aa2
git fetch --depth=1 origin "$commit"
git checkout --detach FETCH_HEAD
test "$(git rev-parse HEAD)" = "$commit"
git show -s --format='%H%n%s%n%b' HEAD

Poniżej znajdują się podstawowe narzędzia i oddzielny katalog instalacyjny. --disable-all ogranicza zakres przykładu; wynik nie zawiera automatycznie wszystkich rozszerzeń potrzebnych WordPressowi lub innej aplikacji. Użytkownik i grupa www-data muszą istnieć w środowisku docelowym. PHP: instalacja w Uniksie · PHP: opcje kompilacji FPM

ShellPHP 7.4: minimalna kompilacja i testy
sudo apt-get update
sudo apt-get install --no-install-recommends \
  build-essential autoconf bison re2c pkg-config \
  libxml2-dev libsqlite3-dev

./buildconf --force
prefix=/opt/php74-php2shell-712e60f9
test ! -e "$prefix"
./configure \
  --prefix="$prefix" \
  --with-config-file-path="$prefix/etc" \
  --with-config-file-scan-dir="$prefix/etc/conf.d" \
  --disable-all --enable-cli --enable-fpm --enable-session \
  --with-fpm-user=www-data --with-fpm-group=www-data \
  --without-pear
make -j2
NO_INTERACTION=1 REPORT_EXIT_STATUS=1 make test

Nieudane lub nieoczekiwanie pominięte istotne testy wymagają wyjaśnienia. Dopiero zaakceptowany wynik pozwala przejść do instalacji w nowym katalogu docelowym, nazwanym w skrypcie prefix. Nie zastępuje to /usr/bin/php ani istniejących pakietów dystrybucji:

ShellPHP 7.4: oddzielna instalacja i identyfikacja
sudo make install
sudo install -d -m 0755 "$prefix/etc/conf.d"
sudo install -m 0644 php.ini-production "$prefix/etc/php.ini"
"$prefix/bin/php" -n -v
"$prefix/bin/php" --ini
"$prefix/sbin/php-fpm" -v
git rev-parse HEAD

Wynik może nadal wskazywać wersję 7.4. Dowód poprawki tworzą więc sprawdzony stan kodu, zapis budowania i faktycznie używany program. Witryna może wymagać dodatkowych rozszerzeń, na przykład sterowników baz danych, mbstring, XML, cURL lub ZIP. Rozszerzenia muszą pasować do interfejsu binarnego tej kompilacji PHP (ABI). Narzędzia budowania phpize i php-config także muszą pochodzić z dokładnie tej instalacji.

Konfiguracja FPM, konto usługi i uprawnienia plików wymagają osobnych testów. Osobne gniazdo, czyli punkt połączenia, oraz osobna usługa oddzielają nową instalację od starej. Po poprawnym teście php-fpm -t -y /sciezka/do/php-fpm.conf serwer WWW może kierować żądania do nowej puli. Samo poprawne uruchomienie PHP w wierszu poleceń nie zmienia witryny. Po nieudanym przełączeniu aplikacja pozostaje odizolowana; stara podatna wersja nie powinna po prostu wracać do publicznego dostępu.

Ślady ataku: łączenie zdarzeń z kilku zapisów

Datadog odtworzył błędy we własnym laboratorium. Skuteczne wykonanie kodu nie musi powodować awarii procesu ani podejrzanego statusu HTTP. HTTP 200 nie jest zatem potwierdzeniem bezpieczeństwa. Podejrzane formularze, błędy pamięci i niespodziewane procesy potomne nabierają znaczenia w powiązaniu czasowym. Pojedynczy błąd braku pamięci nie dowodzi ataku. Datadog Security Labs: własna analiza

Badanie łączy zapisy serwera WWW, błędy PHP, uruchomione procesy i nieoczekiwane zmiany plików. Przed czyszczeniem konieczne jest zabezpieczenie dostępnych dowodów. Pełne treści formularzy mogą zawierać hasła i nie powinny być rutynowo zapisywane. Zapora aplikacji internetowych (WAF) filtruje żądania, lecz nie naprawia PHP. Osobnego potwierdzenia wymagają dwa wyniki: działa poprawione PHP oraz zbadano możliwy wcześniejszy dostęp.

Rozpoznawanie PHP2Shell w logach: podejrzenie to jeszcze nie dowód

Nie istnieje uniwersalny wpis „wykryto PHP2Shell”. Nietypowe żądanie, błąd programu i potwierdzone obce polecenia to różne ustalenia. Silniejszą przesłanką jest spójny ciąg: nietypowe żądanie, błąd właściwego procesu PHP i niewyjaśnione działanie później. Brak wpisów może wynikać z wyłączonego zapisu, usunięcia starych plików lub krótkiego okresu przechowywania.

ObserwacjaInterpretacjaDalsza kontrola
Wiele żądań POST lub duże plikiRównież normalne podczas importów i dozwolonego przesyłaniaŚcieżka docelowa, czas i odstępstwo od zwykłego obciążenia
Brak pamięci, zakończenie procesu lub błędny dostęp do pamięci (segfault)Poszlaka, nie jednoznaczna sygnatura PHP2ShellPowiązane żądania, pula, numer procesu (PID) i znane błędy oprogramowania
Nieoczekiwany interpreter poleceń lub program pobierania uruchomiony przez PHPWyższy priorytet; część aplikacji legalnie uruchamia takie programyProces nadrzędny, rzeczywisty cel i powiązanie czasowe
Niezatwierdzona zmiana kodu albo potwierdzone obce polecenieKonkretny sygnał naruszeniaIzolacja, zabezpieczenie dowodów i ustalenie zakresu

Pierwsze zapytania do logów w Linuksie

Poniższe polecenia odczytują istniejące dane. Nazwy usług, ścieżki i przedział czasu muszą odpowiadać instalacji. Podana godzina korzysta z lokalnej strefy systemu; porównanie zapisów z różnych systemów wymaga uwzględnienia przesunięć i synchronizacji zegarów. Błędy PHP trafią do dziennika tylko wtedy, gdy usługa rzeczywiście wysyła tam takie komunikaty. systemd: journalctl

ShellDziennik: błędy pamięci i zakończenia procesów
sudo journalctl --since '2026-10-17 00:00:00' \
  -u php8.4-fpm -u php8.5-fpm -u apache2 -u nginx \
  --no-pager -o short-iso |
grep -Ei 'Allowed memory size.*exhausted|Out of memory|segfault|SIGSEGV|child .*exited on signal'

Brak wyniku oznacza wyłącznie „brak dopasowania w tych źródłach dla tego wzorca”. Oddzielne pliki błędów FPM, logi kontenerów i protokoły konkretnych hostów wymagają dodatkowych zapytań. Analiza powinna obejmować także pliki po rotacji.

Dla typowych logów dostępu Apache/nginx zapisujących żądanie HTTP poniższe zapytanie zwraca ostatnie sto pasujących wierszy POST z odczytanych plików. To wstępna analiza, nie kompletny skaner; kolejność plików nie gwarantuje sortowania chronologicznego:

ShellLogi dostępu: przegląd żądań POST
sudo zgrep -hE '"POST [^"]+ HTTP/[0-9.]+"' \
  /var/log/nginx/access.log* /var/log/apache2/access.log* |
tail -n 100

Nieistniejące ścieżki albo inny format wymagają dopasowania wyboru plików. Standardowe logi dostępu zwykle nie zawierają całego ciała żądania. Często zapisywana liczba bajtów opisuje zazwyczaj odpowiedź, a nie przesłany plik. Szukanie PHP_SESSION_UPLOAD_PROGRESS w zwykłych logach dostępu może więc niczego nie znaleźć mimo wysłania takiego pola formularza. Brakujących danych ciała żądania nie da się odtworzyć wstecz. Apache: znaczenie i konfiguracja logów

Dodatkowego kontekstu może dostarczyć aktualny obraz relacji między procesami:

ShellAktualne procesy i procesy nadrzędne
ps -eo pid,ppid,lstart,user,comm --forest

Lista obejmuje tylko procesy działające w tej chwili. Zakończone polecenia można odtworzyć wyłącznie przy wcześniej aktywnym monitorowaniu. Przykłady to audyt systemu operacyjnego i programy bezpieczeństwa zapisujące uruchomienia procesów (EDR). Zapis włączony dzisiaj nie dostarczy historii z wczoraj.

Lepsze logowanie bez gromadzenia treści formularzy

Dodatkowy dziennik nginx może zapisywać identyfikator, czas, metodę, ścieżkę i wynik żądania, a także ilość danych i czas obsługi. Definicja należy do bloku http { ... } w konfiguracji nginx. Nowy format pomaga dopiero przy przyszłych żądaniach. nginx: log_format i access_log

nginxnginx: dodatkowy format metadanych
log_format php2shell escape=json
  '{"time":"$time_iso8601","request_id":"$request_id",'
  '"client":"$remote_addr","method":"$request_method","uri":"$uri",'
  '"status":"$status","request_bytes":"$request_length",'
  '"response_bytes":"$body_bytes_sent","duration":"$request_time",'
  '"upstream_status":"$upstream_status"}';

Następny wiersz włącza format we właściwym bloku server { ... }. Konieczne jest sprawdzenie istniejących wpisów access_log oraz ustawień przejętych z bloku nadrzędnego: własny wpis na tym poziomie może zastąpić dotychczas odziedziczony zapis.

nginxnginx: włączenie formatu dla wybranego hosta
access_log /var/log/nginx/php2shell-access.log php2shell;

Przed przeładowaniem konfiguracja musi przejść test nginx -t. request_bytes obejmuje całe żądanie wraz z nagłówkami, a nie sam przesłany plik. Nie mierzy też zużycia pamięci przez PHP. $uri jest ścieżką przetworzoną przez nginx i może się zmienić przy wewnętrznym przekierowaniu. Parametry URL, cookies, nagłówki uwierzytelnienia i treść formularzy nie są bezpośrednio zapisywane. Adresy IP i ścieżki nadal mogą zawierać dane osobowe. Potrzebne są więc uprawnienia dostępu, czas przechowywania i regularna rotacja plików. Za serwerem pośredniczącym adres klienta jest wiarygodny tylko przy poprawnych regułach zaufania. OWASP: bezpieczne logowanie

Ochrona przed zakończeniem aktualizacji

Priorytetem jest poprawiona instalacja PHP. Jeśli szybka aktualizacja jest niemożliwa, publiczne żądania muszą zostać zatrzymane przed PHP, na przykład przez statyczną stronę serwisową lub ograniczenie dostępu. Dotyczy to również bezpośredniego dostępu do serwera źródłowego. Ochrona drogi przez CDN, który rozprowadza lub przekazuje treści, nie wystarczy przy otwartym dostępie bezpośrednim.

  • Limity żądań: Limity rozmiaru, przesyłania i częstotliwości na serwerze pośredniczącym (reverse proxy) powinny odpowiadać rzeczywistym potrzebom. Legalne importy i duże pliki wymagają sprawdzonych reguł. Małe żądanie może wewnętrznie zużyć więcej pamięci, więc limit rozmiaru nie zapewnia pełnej ochrony.
  • WAF jako dodatkowa warstwa: Odpowiednie reguły dostawcy wymagają włączenia i kontroli egzekwowania. Tryb obserwacyjny niczego nie blokuje; HTTP 403 potwierdza jedynie odrzucenie danego żądania.
  • Ograniczone uprawnienia: Oddzielne konta pul, minimalne prawa plików, ograniczone konta baz danych i dostęp sieciowy zmniejszają możliwe szkody. Przejęta aplikacja nadal może nadużyć wszystkich legalnie dostępnych sekretów.
  • Oficjalne środki przejściowe: Wczesne wyłączenie śledzenia postępu przesyłania w sesji blokuje określone ścieżki, lecz nie usuwa obu błędów w całości. Powszechne zniesienie limitu pamięci PHP bez odpowiednich ograniczeń zewnętrznych może spowodować dodatkowe awarie.

Konkretne ślady włamania: oddzielna naprawa i obsługa incydentu

Usunięcie podejrzanego pliku i aktualizacja PHP nie wystarczą do stwierdzenia, że skutki włamania zostały usunięte. Najpierw potrzebne jest odcięcie dalszego dostępu do zaatakowanej instalacji. Równolegle zabezpieczenia wymagają odpowiednie logi, znaczniki czasu i dostępne dane procesów. Nieprzemyślane czyszczenie może zniszczyć przydatne dowody.

Kolejne kroki obejmują ocenę dostępnych danych i sąsiednich systemów, wymianę potencjalnie ujawnionych danych dostępowych z zaufanego środowiska oraz w razie potrzeby odbudowę ze zweryfikowanych źródeł. Kopia zapasowa musi poprzedzać możliwe naruszenie zarówno czasowo, jak i pod względem zawartości. Powrót do publicznej obsługi wymaga poprawionego aktywnego środowiska, sprawdzonej aplikacji i dalszej obserwacji. „Poprawka zainstalowana” oraz „incydent zbadany” pozostają oddzielnymi ustaleniami.

Pytania i odpowiedzi

Czy aktualizacja WordPressa wystarczy?

Nie. Aktualizacja WordPressa nie zastępuje poprawionego środowiska PHP. Aplikacja i pakiety serwera wymagają oddzielnej kontroli.

Czy działająca witryna potwierdza bezpieczeństwo?

Nie. Zwykłe żądania mogą działać poprawnie mimo podatnego środowiska. Brak widocznych zmian nie wyklucza również wcześniejszego włamania.

Przydatne potwierdzenie łączy rewizję pakietu, informację dostawcy o usunięciu obu podatności i kontrolę aktywnych procesów WWW. Ślady naruszenia wymagają dodatkowego dochodzenia.

Źródła

  1. PHP: komunikat bezpieczeństwa z 21 października 2026 r.
  2. PHP Foundation: aktualizacja bezpieczeństwa i tło
  3. PHP: CVE-2026-109618
  4. PHP: CVE-2026-109619
  5. ENISA: wspólny komunikat bezpieczeństwa
  6. NHS England: PHP2Shell
  7. cPanel: poprawione wersje pakietów
  8. Google Cloud: aktualizacje PHP i ponowne wdrożenie
  9. W3Techs: użycie PHP 25 października 2026 r.

Dodatkowe źródła pierwotne i dokumentacja

Dalsze analizy i doniesienia

Dokumentacja analizy logów

Lukas Wójcik

Lukas Wójcik

Systems architect and technology enthusiast specializing in scalable tracking solutions, GMP Stack (GA4 & GTM), and robust backend architectures. Advocate for clean code and privacy-first design.

Kontakt

Masz pytanie lub pomysł na projekt internetowy? Napisz krótko, o co chodzi. Formularz korzysta z reCAPTCHA do ochrony przed spamem.

Napisanie komentarza

Przypadki brzegowe pominięte w artykule i pytania o kod są tu mile widziane.

Adres e-mail nie jest publikowany. Pola obowiązkowe oznaczono gwiazdką.