Krótko: Za pomocą PHP disable_functions blokują Państwo funkcje, przez które PHP wykonuje polecenia systemowe, takie jak exec, shell_exec lub proc_open. Utrudnia to atakującym następny krok po włamaniu. Ustawienie działa tylko z php.ini lub puli FPM, musi pasować do aplikacji i nie zastępuje aktualizacji.
Dlaczego disable_functions ma sens właśnie teraz
PHP2Shell dotyczy zdalnego wykonania złośliwego kodu bez logowania. Obie luki, CVE-2026-109618 i CVE-2026-109619, tkwią w samym interpreterze PHP i są naprawione w PHP 8.5.12, 8.4.27, 8.3.36 i 8.2.35. Aktualizacja jest jedynym sposobem na ich zamknięcie.
Utwardzanie działa o jedną warstwę dalej. Kto raz może wykonać kod na serwerze, zwykle chce iść dalej: uruchamiać polecenia systemowe, doładowywać narzędzia, zakładać trwałą tylną furtkę. Wiele z tych kroków przebiega przez kilka funkcji PHP. Jeśli są zablokowane, droga staje się żmudniejsza i bardziej widoczna.
disable_functions nie jest więc zamiennikiem poprawek, ale elementem na wypadek, gdyby mimo wszelkiej ostrożności coś się przedostało. Dotyczy to przyszłych luk tak samo jak PHP2Shell.
Co PHP disable_functions daje, a czego nie
Ustawienie usuwa wymienione funkcje ze środowiska uruchomieniowego. Jeśli skrypt wywoła zablokowaną funkcję, PHP przerywa działanie z błędem. Blokada obowiązuje każdy kod działający w tym procesie PHP, a więc także kod wprowadzony przez atakującego.
Warto znać granice:
- Ustawienie nie jest zamkniętą przestrzenią ochronną. Rozszerzenia PHP, błędy w interpreterze lub programy spoza PHP mogą je obejść.
- Nie przeszkadza atakującemu czytać ani zapisywać plików, do których ma dostęp użytkownik PHP. Za to odpowiadają uprawnienia do plików i izolacja.
- Działa tylko z php.ini lub jako
php_admin_value. Przezini_set(),.user.inilub.htaccessnie da się go ustawić.
Najwięcej disable_functions daje w połączeniu z czystym php.ini, osobnymi użytkownikami dla każdej strony i restrykcyjnymi uprawnieniami do plików. Podstawy podaje poradnik Jak bezpiecznie skonfigurować php.ini.
Które funkcje warto zablokować
Dla typowych stron bez zapotrzebowania na polecenia systemowe sprawdziła się poniższa lista. Obejmuje funkcje do uruchamiania procesów i sterowania działającymi procesami.
| Grupa | Funkcje | Typowe uprawnione zastosowanie |
|---|---|---|
| Wykonywanie poleceń | exec, shell_exec, system, passthru |
obróbka obrazów, kopie zapasowe przez skrypt |
| Otwieranie procesów | proc_open, popen |
Composer, narzędzia PDF, wysyłka poczty |
| Sterowanie procesami | proc_nice, proc_terminate, proc_get_status |
kolejki, zadania w tle |
| Zarządzanie procesami | pcntl_exec, pcntl_fork |
zwykle tylko w wierszu poleceń |
| Sygnały i uprawnienia | posix_kill, posix_setuid |
rzadko w pracy webowej |
W konfiguracji wygląda to tak:
; php.ini trybu pracy webowego, np. /etc/php/8.3/fpm/php.ini
disable_functions = exec,shell_exec,system,passthru,proc_open,popen,proc_nice,proc_terminate,proc_get_status,pcntl_exec,pcntl_fork,posix_kill,posix_setuid
Jeśli lista nie obowiązuje wszystkich stron na serwerze, proszę ustawić ją dla każdej puli FPM. Po przeładowaniu proszę sprawdzić, jaka lista faktycznie obowiązuje w tej puli:
; /etc/php/8.3/fpm/pool.d/meine-seite.conf (fragment)
php_admin_value[disable_functions] = exec,shell_exec,system,passthru,proc_open,popen
Wcześniejsze sprawdzenie aplikacji: jak uniknąć awarii
Kto ustawi listę bez sprawdzenia, ryzykuje, że zmniejszanie obrazów, faktury PDF lub wysyłka poczty nagle przestaną działać. Proszę więc wcześniej poszukać w kodzie dotkniętych funkcji:
# Gdzie i jak często funkcje są używane w kodzie?
grep -rnoE "\b(exec|shell_exec|system|passthru|proc_open|popen|pcntl_exec)\s*\(" /var/www/meine-seite --include="*.php" \
| cut -d: -f1 | sort | uniq -c | sort -rn | head -30
Trafienia nie oznaczają automatycznie, że funkcja jest potrzebna w pracy. Wiele bibliotek najpierw sprawdza, czy funkcja jest dostępna, a w przeciwnym razie wybiera inną drogę. Rozstrzygający jest test w środowisku stagingowym ze wszystkimi ważnymi procesami: zamówienie, faktura, wysyłka formularza, upload obrazu, zaplanowane zadania.
Jeśli aplikacja bezwzględnie wymaga jednej z tych funkcji, proszę sprawdzić wymagania systemowe producenta na jego oficjalnej stronie. Często zadanie można przenieść do osobnej puli lub skryptu wiersza poleceń, który nie jest dostępny przez sieć.
Aktywacja ustawienia i kontrola jego działania
Po zmianie PHP musi ponownie wczytać konfigurację. Potem proszę sprawdzić wartość w trybie pracy strony, a nie w wierszu poleceń:
sudo systemctl reload php8.3-fpm
php-fpm8.3 -i | grep "^disable_functions"
# Sprawdź w logu błędów wywołania zablokowanych funkcji
sudo grep -i "has been disabled" /var/log/php/*.log | tail -20
Komunikaty w logu błędów są cenne także później. Jeśli pojawiają się tam nagle wywołania zablokowanych funkcji, choć aplikacja ich nie używa, może to wskazywać na wprowadzony kod. Jak postępować dalej, opisuje poradnik Jak wykryć i usunąć webshell.
Typowe błędy przy stosowaniu disable_functions
W praktyce utwardzanie rzadko zawodzi z powodów technicznych, częściej z powodu drobiazgów. Te błędy są szczególnie rozpowszechnione:
- Zmieniony niewłaściwy plik: lista jest tylko w php.ini wiersza poleceń, a strona działa przez PHP-FPM i pozostaje niezabezpieczona.
- Brak restartu: plik jest poprawny, ale działające procesy nadal pracują ze starą konfiguracją.
- Zbyt szeroka blokada: zablokowano przy okazji funkcje takie jak
ini_setlubmail, a ważne procesy przerywają się niezauważenie. Błędy często wychodzą na jaw dopiero po kilku dniach, na przykład przy braku potwierdzeń zamówień. - Ustawione raz, nigdy niesprawdzane: po przeprowadzce, zmianie wersji PHP lub nowej instalacji przez panel hostingowy lista zniknęła.
- Fałszywe poczucie bezpieczeństwa: blokadę traktuje się jako zamiennik aktualizacji. Nie zamyka ona jednak żadnej luki w interpreterze.
Kontrolę aktywnej wartości proszę więc włączyć do rutyny po każdej aktualizacji PHP. Krótkie spojrzenie wystarcza, kosztuje niewiele czasu i zapobiega cichej utracie utwardzenia.
Przy kilku stronach na jednym serwerze: proszę utworzyć dla każdej strony osobną pulę z własną listą. Uzupełniająco open_basedir ogranicza katalogi, do których PHP ma dostęp.
Jak konkretnie pomaga PHP SOS?
- Sprawdzamy kod i procesy Państwa aplikacji pod kątem użycia krytycznych funkcji.
- Ustalamy dla każdej strony odpowiednią listę blokad i testujemy ją przed uruchomieniem produkcyjnym.
- Łączymy blokadę z pulami, uprawnieniami do plików i protokołowaniem w spójną koncepcję utwardzania.
- Dokumentujemy ustawienia i monitorujemy log błędów pod kątem podejrzanych wywołań.
Jak przebiega to jako całościowy pakiet, opisuje usługa Utwardzanie serwera dla serwerów WWW z PHP.
Częste pytania
Czy mogę ustawić disable_functions przez ini_set() lub .htaccess?
Nie. Ustawienie działa tylko z php.ini lub jako php_admin_value w puli FPM albo w konfiguracji Apache. W czasie działania nie da się go ustawić, a aplikacja nie może też ponownie odblokować zablokowanych funkcji.
Czy disable_functions chroni przed PHP2Shell?
Nie. PHP2Shell dotyczy samego interpretera PHP, a lukę zamyka wyłącznie aktualizacja. Zablokowane funkcje mogą jednak ograniczyć pole manewru atakującego po udanym wykorzystaniu luki.
Dlaczego php -i pokazuje inną listę niż moja strona?
Wiersz poleceń często czyta własny plik php.ini. Dla strony liczy się konfiguracja PHP-FPM, mod_php lub LiteSpeed. Wartość proszę więc sprawdzać w trybie pracy, przez który działa Państwa strona.
Które aplikacje potrzebują proc_open lub exec?
Zależy to od aplikacji. Typowe są obróbka obrazów przez programy zewnętrzne, generowanie PDF, wysyłka poczty przez sendmail lub narzędzia takie jak Composer. Proszę to sprawdzić w kodzie i w wymaganiach systemowych producenta.