Krótko: mod_php to PHP jako moduł w serwerze WWW Apache. Każdy proces Apache zawiera wtedy pełny interpreter PHP i sam wykonuje kod PHP; SAPI nazywa się apache2handler. Jest to proste w konfiguracji, ale wiąże PHP z Apache, zwykle wymaga MPM prefork i prawie nie pozwala na rozdzielenie stron. Podręcznik PHP odradza je dla nowych instalacji, a w przypadku PHP2Shell zespół PHP ocenia ryzyko przy mod_php jako najwyższe.
Czym jest mod_php?
W mod_php Apache ładuje PHP jako osobny moduł do swoich procesów. Nie ma oddzielnej usługi PHP: gdy Apache ma wydać plik .php, ten sam proces, który przyjął żądanie, wykonuje także kod PHP. Przez wiele lat był to standardowy sposób uruchamiania PHP i do dziś jest rozpowszechniony na starszych serwerach i w niektórych obrazach Docker.
Według podręcznika PHP jako moduł serwera czyta swoją konfigurację tylko raz, przy starcie serwera WWW. Zmiany w php.ini i aktualizacje modułu działają więc dopiero po restarcie Apache.
Ważne dla zrozumienia: procesy Apache żyją długo. Jeden proces przyjmuje kolejno wiele połączeń, zanim zostanie wymieniony; ile, reguluje dyrektywa Apache MaxConnectionsPerChild. Wbudowany interpreter PHP pozostaje w tym czasie ten sam. Kto wymieni bibliotekę libphp na dysku, nie zmienia niczego w działających procesach.
Dla zarządu i osób odpowiedzialnych za projekty można to podsumować tak: w mod_php serwer WWW i PHP stanowią jedność. Kto dotyka jednego, dotyka drugiego. Aktualizacja PHP oznacza restart serwera WWW, błąd w PHP działa z uprawnieniami serwera WWW, a rozdzielenie kilku stron na tym samym serwerze jest prawie niemożliwe.
Jak włącza się mod_php?
Podręcznik PHP pokazuje włączenie w dwóch krokach: załadowanie modułu i określenie, które pliki ma przetwarzać PHP.
LoadModule php_module modules/libphp.so
<FilesMatch \.php$>
SetHandler application/x-httpd-php
</FilesMatch>
Podręcznik zaleca FilesMatch z SetHandler zamiast samego AddType, aby wgrane pliki, takie jak bild.php.jpg, nie były wykonywane jako PHP. W Debianie i Ubuntu tę pracę przejmują pakiety takie jak libapache2-mod-php8.3 oraz polecenia a2enmod i a2dismod.
To, czy mod_php jest aktywny, można sprawdzić bez wprowadzania zmian:
apachectl -M 2>/dev/null | grep -i php # Debian/Ubuntu
httpd -M 2>/dev/null | grep -i php # rodzina RHEL
apachectl -V | grep -i mpm # aktywny MPM (prefork, worker, event)
Prefork, Thread Safety i zasoby
Apache rozdziela żądania przez moduł wieloprocesowy (MPM). Według podręcznika PHP mod_php wymaga MPM prefork, o ile PHP nie zostało zbudowane z Zend Thread Safety (--enable-zts). Większość pakietów dystrybucji jest zbudowana bez Thread Safety.
Prefork oznacza: jeden proces na równoczesne połączenie, a każdy proces niesie kompletny interpreter PHP. Także żądania obrazów lub plików CSS zajmują więc proces z PHP w bagażu. Kosztuje to pamięć i ogranicza obciążenie, jakie serwer może udźwignąć.
| Cecha | mod_php | PHP-FPM |
|---|---|---|
| Gdzie działa PHP? | w każdym procesie Apache | w osobnej usłudze |
| MPM Apache | zwykle prefork |
możliwy event |
| Użytkownik dla każdej strony | nie, wszystko jako użytkownik Apache | tak, dla każdej puli |
| Restart PHP | tylko razem z Apache | niezależnie od Apache |
| Ustawienia dla katalogu | php_value w .htaccess |
pula lub .user.ini |
Podręcznik zaleca dlatego dla wszystkich nowoczesnych instalacji PHP-FPM z mod_proxy_fcgi: lepsze zarządzanie zasobami, rozdzielenie procesów, restart PHP bez restartu Apache i zgodność z MPM event, który od Apache 2.4 jest standardem. Podstawy podajemy na stronie PHP-FPM wyjaśniony.
Ustawienia przez .htaccess, php_value i php_admin_value
W mod_php ustawienia PHP można zadawać bezpośrednio w konfiguracji Apache. Podręcznik rozróżnia przy tym tryby zmiany: wpisy z INI_PERDIR mogą znajdować się w php.ini, .htaccess lub httpd.conf, wpisy z INI_SYSTEM tylko w php.ini lub httpd.conf.
# W konfiguracji VirtualHost: zablokowane dla aplikacji
php_admin_flag display_errors off
php_admin_value upload_max_filesize 24M
# Możliwe w .htaccess, ale aplikacja może nadpisać
php_value max_execution_time 60
php_admin_value i php_admin_flag są dozwolone tylko w konfiguracji serwera, nie w .htaccess. Właśnie to rozróżnienie jest ważne przy środkach przejściowych dla PHP2Shell, ponieważ wartości takie jak session.upload_progress.enabled nie mogą być resetowane przez aplikację.
mod_php i PHP2Shell: dlaczego ryzyko jest najwyższe
Zespół PHP ocenia ryzyko związane z PHP2Shell przy mod_php jako najwyższe: pokazano tam exploit, zanim w ogóle zacznie działać kod aplikacji. Wtyczki bezpieczeństwa lub kontrole w CMS przychodzą więc za późno. Dochodzi to, że w mod_php PHP działa z uprawnieniami i w pamięci serwera WWW. Szczegółową ocenę podajemy na stronie Dlaczego mod_php niesie najwyższe ryzyko.
Dla operatorów obowiązuje więc:
- Zaktualizować moduł PHP do 8.5.12, 8.4.27, 8.3.36 lub 8.2.35 albo do potwierdzonego backportu.
- Zrestartować Apache w całości, a nie tylko przeładować, i sprawdzić czas startu procesów.
- Ustawić wartości przejściowe przez
php_admin_valuew konfiguracji serwera, jeśli aktualizacja nie jest jeszcze możliwa. - Następnie zaplanować przejście na PHP-FPM, jak opisano na stronie Zabezpieczanie Apache z mod_php.
Jak konkretnie pomaga PHP SOS?
- Rozpoznanie: Sprawdzamy, na których serwerach działa mod_php, z jakim MPM i z jakiego źródła pakietów.
- Aktualizacja: Aktualizujemy moduł PHP, restartujemy Apache w całości i dokumentujemy stan.
- Zabezpieczenie okresu przejściowego: Tam, gdzie aktualizacja jest zablokowana, ustawiamy środki z php.net jako zablokowane w konfiguracji serwera.
- Przejście: W ramach utwardzania serwera migrujemy z testami na PHP-FPM z własnymi pulami.
Częste pytania
Dlaczego mówi się mod_php, skoro moduł nazywa się php_module?
mod_php to potoczna nazwa PHP jako modułu Apache. W konfiguracji ładuje się go przez LoadModule; podręcznik PHP podaje jako przykład LoadModule php_module modules/libphp.so. Starsze wersje używały nazw takich jak php7_module czy php5_module.
Dlaczego mod_php potrzebuje MPM prefork?
Według podręcznika PHP mod_php wymaga MPM prefork, o ile PHP nie zostało zbudowane z Zend Thread Safety. Większość pakietów dystrybucji jest zbudowana bez Thread Safety. Prefork uruchamia dla każdego równoczesnego połączenia osobny proces, co zużywa więcej pamięci.
Czy wiersze php_value w .htaccess działają także z PHP-FPM?
Nie. php_value i php_flag w .htaccess to dyrektywy Apache modułu PHP i działają tylko z mod_php. W PHP-FPM takie ustawienia należą do puli lub, dla dozwolonych wartości, do pliku .user.ini.
Czy muszę natychmiast zrezygnować z mod_php?
Najpierw przychodzi aktualizacja PHP z pełnym restartem Apache. Przejście na PHP-FPM jest potem sensowne, ale powinno być zaplanowane i przetestowane. Nie zamyka ono PHP2Shell, ponieważ PHP-FPM również jest dotknięty.