Stručne: mod_php je PHP ako modul vo webovom serveri Apache. Každý proces Apache potom obsahuje úplný interpreter PHP a kód PHP vykonáva sám; SAPI sa volá apache2handler. Je to jednoduché nastaviť, ale PHP to viaže na Apache, zvyčajne vyžaduje prefork MPM a takmer nedovoľuje oddelenie medzi webmi. Príručka PHP od neho pre nové inštalácie odrádza a pri PHP2Shell tím PHP hodnotí riziko pri mod_php ako najvyššie.
Čo je mod_php?
Pri mod_php načíta Apache PHP ako samostatný modul do svojich procesov. Neexistuje oddelená služba PHP: keď má Apache odovzdať súbor .php, ten istý proces, ktorý požiadavku prijal, vykoná aj kód PHP. Po mnoho rokov to bol štandardný spôsob prevádzky PHP a na starších serveroch a v niektorých obrazoch Docker je to rozšírené dodnes.
Podľa príručky PHP číta PHP ako serverový modul svoju konfiguráciu iba raz, pri štarte webového servera. Zmeny v php.ini a aktualizácie modulu preto pôsobia až po reštarte Apache.
Dôležité pre pochopenie: procesy Apache žijú dlho. Jeden proces prijme postupne mnoho spojení, kým sa nahradí; koľko, určuje direktíva Apache MaxConnectionsPerChild. Vložený interpreter PHP zostáva po tento čas ten istý. Kto vymení knižnicu libphp na disku, na bežiacich procesoch nič nezmení.
Pre konateľov a projektových zodpovedných sa to dá zhrnúť takto: pri mod_php tvoria webový server a PHP jeden celok. Kto sa dotkne jedného, ovplyvní aj druhé. Aktualizácia PHP znamená reštart webového servera, chyba v PHP beží s právami webového servera a oddelenie viacerých webov na tom istom serveri je takmer nemožné.
Ako sa mod_php zapája?
Príručka PHP ukazuje zapojenie v dvoch krokoch: načítať modul a určiť, ktoré súbory má PHP spracúvať.
LoadModule php_module modules/libphp.so
<FilesMatch \.php$>
SetHandler application/x-httpd-php
</FilesMatch>
Príručka odporúča FilesMatch so SetHandler namiesto samotného AddType, aby sa nahrané súbory ako bild.php.jpg nevykonávali ako PHP. V Debiane a Ubuntu túto prácu preberajú balíky ako libapache2-mod-php8.3 a príkazy a2enmod a a2dismod.
Či je mod_php aktívny, sa dá overiť len na čítanie:
apachectl -M 2>/dev/null | grep -i php # Debian/Ubuntu
httpd -M 2>/dev/null | grep -i php # rodina RHEL
apachectl -V | grep -i mpm # aktívny MPM (prefork, worker, event)
Prefork, Thread Safety a zdroje
Apache rozdeľuje požiadavky cez modul Multi-Processing (MPM). Podľa príručky PHP vyžaduje mod_php MPM prefork, pokiaľ PHP nebolo zostavené so Zend Thread Safety (--enable-zts). Väčšina balíkov distribúcií je zostavená bez Thread Safety.
Prefork znamená: jeden proces na súbežné spojenie a každý proces nesie kompletný interpreter PHP. Aj požiadavky na obrázky alebo súbory CSS tak zaberajú proces s PHP v batohu. To stojí pamäť a obmedzuje zaťaženie, ktoré server unesie.
| Vlastnosť | mod_php | PHP-FPM |
|---|---|---|
| Kde beží PHP? | v každom procese Apache | v samostatnej službe |
| MPM Apache | väčšinou prefork |
možné event |
| Používateľ pre každý web | nie, všetko ako používateľ Apache | áno, pre každý pool |
| Reštart PHP | iba s Apache | nezávisle od Apache |
| Nastavenia pre každý adresár | php_value v .htaccess |
pool alebo .user.ini |
Príručka preto odporúča pre všetky moderné inštalácie PHP-FPM s mod_proxy_fcgi: lepšia správa zdrojov, oddelenie procesov, reštart PHP bez reštartu Apache a kompatibilita s MPM event, ktorý je od Apache 2.4 štandardom. Základy sú v časti PHP-FPM vysvetlené.
Nastavenia cez .htaccess, php_value a php_admin_value
S mod_php sa dajú nastavenia PHP zadať priamo v konfigurácii Apache. Príručka pritom rozlišuje režimy zmeny: záznamy s INI_PERDIR smú byť v php.ini, .htaccess alebo httpd.conf, záznamy s INI_SYSTEM iba v php.ini alebo httpd.conf.
# V konfigurácii VirtualHost: pre aplikáciu zamknuté
php_admin_flag display_errors off
php_admin_value upload_max_filesize 24M
# V .htaccess možné, ale aplikácia ich môže prepísať
php_value max_execution_time 60
php_admin_value a php_admin_flag sú povolené iba v konfigurácii servera, nie v .htaccess. Práve tento rozdiel je pri prechodných opatreniach k PHP2Shell dôležitý, pretože hodnoty ako session.upload_progress.enabled nesmie aplikácia vrátiť späť.
mod_php a PHP2Shell: prečo je riziko najvyššie
Tím PHP hodnotí riziko PHP2Shell pri mod_php ako najvyššie: tam bol exploit predvedený ešte predtým, než vôbec beží kód aplikácie. Bezpečnostné zásuvné moduly alebo kontroly v CMS tak prichádzajú neskoro. Ďalej platí, že PHP beží pri mod_php s právami a v pamäti webového servera. Podrobné zaradenie je na stránke Prečo nesie mod_php najvyššie riziko.
Pre prevádzkovateľov preto platí:
- Aktualizovať modul PHP na 8.5.12, 8.4.27, 8.3.36 alebo 8.2.35, resp. potvrdený backport.
- Apache úplne reštartovať, nielen znova načítať, a skontrolovať čas spustenia procesov.
- Prechodné hodnoty zadať cez
php_admin_valuev konfigurácii servera, ak aktualizácia ešte nie je možná. - Potom naplánovať prechod na PHP-FPM, ako je opísané v časti Zabezpečenie Apache s mod_php.
Ako konkrétne pomáha PHP SOS?
- Rozpoznať: Zisťujeme, na ktorých serveroch beží mod_php, s akým MPM a z akého zdroja balíkov.
- Záplatovať: Aktualizujeme modul PHP, Apache úplne reštartujeme a stav dokladáme.
- Zabezpečiť prechod: Tam, kde je aktualizácia blokovaná, nastavíme opatrenia z php.net zamknuté v konfigurácii servera.
- Prestaviť: V rámci zabezpečenia servera (hardening) otestovane migrujeme na PHP-FPM s vlastnými poolmi.
Časté otázky
Prečo sa hovorí mod_php, keď sa modul volá php_module?
mod_php je hovorový názov pre PHP ako modul Apache. V konfigurácii sa načítava pomocou LoadModule; príručka PHP uvádza ako príklad LoadModule php_module modules/libphp.so. Staršie verzie používali názvy ako php7_module alebo php5_module.
Prečo mod_php potrebuje prefork MPM?
Podľa príručky PHP vyžaduje mod_php prefork MPM, pokiaľ PHP nebolo zostavené so Zend Thread Safety. Väčšina balíkov distribúcií je zostavená bez Thread Safety. Prefork spúšťa pre každé súbežné spojenie samostatný proces, čo vyžaduje viac pamäte.
Fungujú riadky php_value v .htaccess aj s PHP-FPM?
Nie. php_value a php_flag v .htaccess sú direktívy Apache modulu PHP a pôsobia iba s mod_php. Pod PHP-FPM patria takéto nastavenia do poolu alebo, pre povolené hodnoty, do .user.ini.
Musím mod_php zrušiť okamžite?
Najprv príde aktualizácia PHP s úplným reštartom Apache. Prechod na PHP-FPM je potom zmysluplný, mal by sa však naplánovať a otestovať. PHP2Shell nezatvára, pretože dotknuté je aj PHP-FPM.