Trumpai: mod_php yra PHP kaip Apache žiniatinklio serverio modulis. Tuomet kiekviename Apache procese yra visavertis PHP interpretatorius, kuris pats vykdo PHP kodą; SAPI vadinasi apache2handler. Tokią sąranką lengva įrengti, bet PHP susiejamas su Apache, dažniausiai reikalingas prefork MPM ir vargiai įmanomas svetainių atskyrimas. PHP vadovas naujiems diegimams to atkalba, o esant PHP2Shell PHP komanda mod_php riziką vertina didžiausią.
Kas yra mod_php?
Esant mod_php, Apache įkelia PHP kaip atskirą modulį į savo procesus. Atskiros PHP tarnybos nėra: kai Apache turi pateikti .php failą, tą patį PHP kodą vykdo tas pats procesas, kuris priėmė užklausą. Daugelį metų tai buvo standartinis PHP eksploatavimo būdas, ir jis iki šiol paplitęs senesniuose serveriuose bei kai kuriuose Docker atvaizduose.
Pasak PHP vadovo, kaip serverio modulis PHP konfigūraciją nuskaito tik vieną kartą, paleidžiant žiniatinklio serverį. Todėl php.ini pakeitimai ir modulio atnaujinimai įsigalioja tik paleidus Apache iš naujo.
Supratimui svarbu: Apache procesai gyvena ilgai. Procesas nuosekliai priima daug ryšių, kol bus pakeistas; kiek jų, nustato Apache direktyva MaxConnectionsPerChild. Įterptasis PHP interpretatorius per tą laiką lieka tas pats. Kas diske pakeičia biblioteką libphp, veikiančių procesų nepakeičia.
Vadovybei ir projektų vadovams tai galima apibendrinti taip: esant mod_php, žiniatinklio serveris ir PHP yra viena visuma. Kas liečia vieną, paveikia kitą. PHP atnaujinimas reiškia žiniatinklio serverio paleidimą iš naujo, PHP klaida vykdoma su žiniatinklio serverio teisėmis, o kelių svetainių atskyrimas tame pačiame serveryje vargiai įmanomas.
Kaip mod_php įtraukiamas?
PHP vadovas parodo įtraukimą dviem žingsniais: modulio įkėlimas ir nustatymas, kuriuos failus turi apdoroti PHP.
LoadModule php_module modules/libphp.so
<FilesMatch \.php$>
SetHandler application/x-httpd-php
</FilesMatch>
Vadovas rekomenduoja FilesMatch su SetHandler, o ne tik AddType, kad įkelti failai, tokie kaip bild.php.jpg, nebūtų vykdomi kaip PHP. Debian ir Ubuntu šį darbą atlieka paketai, tokie kaip libapache2-mod-php8.3, ir komandos a2enmod bei a2dismod.
Ar mod_php aktyvus, galima patikrinti tik skaitant:
apachectl -M 2>/dev/null | grep -i php # Debian/Ubuntu
httpd -M 2>/dev/null | grep -i php # RHEL šeima
apachectl -V | grep -i mpm # aktyvus MPM (prefork, worker, event)
Prefork, Thread Safety ir ištekliai
Apache užklausas paskirsto per daugiaprocesį modulį (MPM). Pasak PHP vadovo, mod_php reikia prefork MPM, jei PHP nesukurtas su Zend Thread Safety (--enable-zts). Dauguma distribucijų paketų sukurti be Thread Safety.
Prefork reiškia: vienas procesas vienam vienu metu esančiam ryšiui, ir kiekvienas procesas neša visą PHP interpretatorių. Net užklausos paveikslėliams ar CSS failams užima procesą su PHP bagaže. Tai kainuoja atmintį ir riboja apkrovą, kurią gali atlaikyti serveris.
| Požymis | mod_php | PHP-FPM |
|---|---|---|
| Kur veikia PHP? | kiekviename Apache procese | atskiroje tarnyboje |
| Apache MPM | dažniausiai prefork |
galimas event |
| Naudotojas kiekvienai svetainei | ne, viskas kaip Apache naudotojas | taip, kiekvienam baseinui |
| PHP paleidimas iš naujo | tik kartu su Apache | nepriklausomai nuo Apache |
| Nustatymai kiekvienam katalogui | php_value .htaccess |
baseinas arba .user.ini |
Todėl vadovas visiems šiuolaikiniams diegimams rekomenduoja PHP-FPM su mod_proxy_fcgi: geresnis išteklių valdymas, procesų atskyrimas, PHP paleidimas iš naujo be Apache paleidimo ir suderinamumas su event MPM, kuris nuo Apache 2.4 yra standartinis. Pagrindai aprašyti skyriuje PHP-FPM paaiškinta.
Nustatymai su .htaccess, php_value ir php_admin_value
Su mod_php PHP nustatymus galima nustatyti tiesiai Apache konfigūracijoje. Vadovas čia skiria keitimo režimus: įrašai su INI_PERDIR gali būti php.ini, .htaccess ar httpd.conf, įrašai su INI_SYSTEM tik php.ini ar httpd.conf.
# VirtualHost konfigūracijoje: programai užrakinta
php_admin_flag display_errors off
php_admin_value upload_max_filesize 24M
# Galima .htaccess, bet programa gali perrašyti
php_value max_execution_time 60
php_admin_value ir php_admin_flag leidžiami tik serverio konfigūracijoje, o ne .htaccess. Būtent šis skirtumas svarbus pereinamosioms priemonėms nuo PHP2Shell, nes tokių reikšmių kaip session.upload_progress.enabled programa neturi galėti atstatyti.
mod_php ir PHP2Shell: kodėl rizika didžiausia
PHP komanda PHP2Shell riziką mod_php atveju vertina didžiausią: ten parodytas exploit dar prieš pradedant vykdyti bet kokį programos kodą. Saugumo papildiniai ar CMS patikros taip pavėluoja. Be to, esant mod_php, PHP veikia su žiniatinklio serverio teisėmis ir jo atmintyje. Išsamus įvertinimas pateiktas skyriuje Kodėl mod_php kelia didžiausią riziką.
Todėl eksploatuotojams galioja:
- PHP modulį atnaujinti iki 8.5.12, 8.4.27, 8.3.36 ar 8.2.35 arba iki patvirtinto backport.
- Apache paleisti iš naujo visiškai, o ne tik perkrauti, ir patikrinti procesų paleidimo laiką.
- Pereinamąsias reikšmes nustatyti per
php_admin_valueserverio konfigūracijoje, jei atnaujinimas dar neįmanomas. - Po to suplanuoti perėjimą prie PHP-FPM, kaip aprašyta skyriuje Apache su mod_php apsauga.
Kaip PHP SOS padeda konkrečiai?
- Atpažinimas: tikriname, kuriuose serveriuose veikia mod_php, su kokiu MPM ir iš kokio paketų šaltinio.
- Pataisymas: atnaujiname PHP modulį, visiškai iš naujo paleidžiame Apache ir įrodome būseną.
- Pereinamojo laikotarpio apsauga: kur atnaujinimas užblokuotas, php.net priemones nustatome užrakintas serverio konfigūracijoje.
- Perėjimas: serverio sutvirtinimo rėmuose išbandytai migruojame į PHP-FPM su atskirais baseinais.
Dažni klausimai
Kodėl sakoma mod_php, jei modulis vadinasi php_module?
mod_php yra šnekamasis PHP kaip Apache modulio pavadinimas. Konfigūracijoje jis įkeliamas per LoadModule; PHP vadovas kaip pavyzdį nurodo LoadModule php_module modules/libphp.so. Senesnėse versijose naudoti pavadinimai, tokie kaip php7_module ar php5_module.
Kodėl mod_php reikia prefork MPM?
Pasak PHP vadovo, mod_php reikia prefork MPM, jei PHP nesukurtas su Zend Thread Safety. Dauguma distribucijų paketų sukurti be Thread Safety. Prefork kiekvienam vienu metu esančiam ryšiui paleidžia atskirą procesą, todėl reikia daugiau atminties.
Ar php_value eilutės .htaccess veikia ir su PHP-FPM?
Ne. php_value ir php_flag .htaccess yra PHP modulio Apache direktyvos ir veikia tik su mod_php. Su PHP-FPM tokie nustatymai priklauso baseinui arba, leidžiamoms reikšmėms, .user.ini.
Ar mod_php reikia atsisakyti nedelsiant?
Pirmiausia ateina PHP atnaujinimas su visišku Apache paleidimu iš naujo. Perėjimas prie PHP-FPM po to yra prasmingas, bet jį reikia suplanuoti ir išbandyti. PHP2Shell jis neuždaro, nes PHP-FPM taip pat paveiktas.