Εν συντομία: Το mod_php είναι η PHP ως μονάδα στον διακομιστή ιστού Apache. Κάθε διεργασία του Apache περιέχει τότε έναν πλήρη διερμηνέα PHP και εκτελεί η ίδια τον κώδικα PHP· το SAPI ονομάζεται apache2handler. Είναι απλό στη ρύθμιση, δένει όμως την PHP με τον Apache, απαιτεί συνήθως το MPM prefork και επιτρέπει μόλις διαχωρισμό μεταξύ ιστοτόπων. Το εγχειρίδιο της PHP το αποθαρρύνει για νέες εγκαταστάσεις και στο PHP2Shell η ομάδα της PHP κατατάσσει τον κίνδυνο στο mod_php ως τον υψηλότερο.
Τι είναι το mod_php;
Στο mod_php ο Apache φορτώνει την PHP ως δική του μονάδα μέσα στις διεργασίες του. Δεν υπάρχει ξεχωριστή υπηρεσία PHP: όταν ο Apache πρέπει να παραδώσει ένα αρχείο .php, η ίδια διεργασία που δέχτηκε το αίτημα εκτελεί και τον κώδικα PHP. Επί πολλά χρόνια αυτός ήταν ο συνήθης τρόπος λειτουργίας της PHP και παραμένει διαδεδομένος σε παλαιότερους διακομιστές και σε ορισμένα images Docker.
Σύμφωνα με το εγχειρίδιο της PHP, ως μονάδα διακομιστή η PHP διαβάζει τη διαμόρφωσή της μόνο μία φορά, κατά την εκκίνηση του διακομιστή ιστού. Οι αλλαγές στο php.ini και οι ενημερώσεις της μονάδας ισχύουν γι' αυτό μόνο μετά από επανεκκίνηση του Apache.
Σημαντικό για την κατανόηση: οι διεργασίες του Apache ζουν πολύ. Μια διεργασία δέχεται διαδοχικά πολλές συνδέσεις προτού αντικατασταθεί· πόσες, το ρυθμίζει η οδηγία Apache MaxConnectionsPerChild. Ο ενσωματωμένος διερμηνέας PHP παραμένει στο διάστημα αυτό ο ίδιος. Όποιος αντικαταστήσει τη βιβλιοθήκη libphp στον δίσκο, δεν αλλάζει τίποτα στις εκτελούμενες διεργασίες.
Για τη διοίκηση και τους υπευθύνους έργων αυτό συνοψίζεται ως εξής: στο mod_php ο διακομιστής ιστού και η PHP αποτελούν μία ενότητα. Όποιος αγγίξει το ένα, επηρεάζει το άλλο. Μια ενημέρωση της PHP σημαίνει επανεκκίνηση του διακομιστή ιστού, ένα σφάλμα στην PHP εκτελείται με τα δικαιώματα του διακομιστή ιστού και ένας διαχωρισμός μεταξύ πολλών ιστοτόπων στον ίδιο διακομιστή είναι σχεδόν αδύνατος.
Πώς ενσωματώνεται το mod_php;
Το εγχειρίδιο της PHP δείχνει την ενσωμάτωση σε δύο βήματα: φόρτωση της μονάδας και καθορισμός των αρχείων που πρέπει να επεξεργάζεται η PHP.
LoadModule php_module modules/libphp.so
<FilesMatch \.php$>
SetHandler application/x-httpd-php
</FilesMatch>
Το εγχειρίδιο συνιστά FilesMatch με SetHandler αντί για μόνο AddType, ώστε αρχεία που ανεβάζονται, όπως το bild.php.jpg, να μην εκτελούνται ως PHP. Σε Debian και Ubuntu αυτή τη δουλειά αναλαμβάνουν πακέτα όπως το libapache2-mod-php8.3 και οι εντολές a2enmod και a2dismod.
Το αν το mod_php είναι ενεργό, μπορεί να ελεγχθεί μόνο με ανάγνωση:
apachectl -M 2>/dev/null | grep -i php # Debian/Ubuntu
httpd -M 2>/dev/null | grep -i php # οικογένεια RHEL
apachectl -V | grep -i mpm # ενεργό MPM (prefork, worker, event)
Prefork, Thread Safety και πόροι
Ο Apache κατανέμει τα αιτήματα μέσω μιας μονάδας πολυεπεξεργασίας (MPM). Σύμφωνα με το εγχειρίδιο της PHP, το mod_php απαιτεί το MPM prefork, εφόσον η PHP δεν έχει κατασκευαστεί με Zend Thread Safety (--enable-zts). Τα περισσότερα πακέτα διανομών κατασκευάζονται χωρίς Thread Safety.
Το prefork σημαίνει: μία διεργασία ανά ταυτόχρονη σύνδεση και κάθε διεργασία φέρει έναν ολόκληρο διερμηνέα PHP. Έτσι ακόμη και αιτήματα για εικόνες ή αρχεία CSS δεσμεύουν μια διεργασία με την PHP στις αποσκευές της. Αυτό κοστίζει μνήμη και περιορίζει το φορτίο που μπορεί να σηκώσει ένας διακομιστής.
| Χαρακτηριστικό | mod_php | PHP-FPM |
|---|---|---|
| Πού εκτελείται η PHP; | σε κάθε διεργασία του Apache | σε ξεχωριστή υπηρεσία |
| MPM του Apache | συνήθως prefork |
δυνατό το event |
| Χρήστης ανά ιστότοπο | όχι, όλα ως χρήστης Apache | ναι, ανά pool |
| Επανεκκίνηση της PHP | μόνο μαζί με τον Apache | ανεξάρτητα από τον Apache |
| Ρυθμίσεις ανά κατάλογο | php_value στο .htaccess |
pool ή .user.ini |
Το εγχειρίδιο συνιστά γι' αυτό για όλες τις σύγχρονες εγκαταστάσεις το PHP-FPM με mod_proxy_fcgi: καλύτερη διαχείριση πόρων, διαχωρισμό διεργασιών, επανεκκίνηση της PHP χωρίς επανεκκίνηση του Apache και συμβατότητα με το MPM event, που είναι η προεπιλογή από τον Apache 2.4. Τα βασικά βρίσκονται στη σελίδα Το PHP-FPM εξηγημένο.
Ρυθμίσεις με .htaccess, php_value και php_admin_value
Με το mod_php οι ρυθμίσεις PHP μπορούν να οριστούν απευθείας στη διαμόρφωση του Apache. Το εγχειρίδιο διακρίνει εδώ τρόπους αλλαγής: οι εγγραφές με INI_PERDIR επιτρέπεται να βρίσκονται στο php.ini, στο .htaccess ή στο httpd.conf, οι εγγραφές με INI_SYSTEM μόνο στο php.ini ή στο httpd.conf.
# Στη διαμόρφωση του VirtualHost: κλειδωμένο για την εφαρμογή
php_admin_flag display_errors off
php_admin_value upload_max_filesize 24M
# Δυνατό στο .htaccess, αλλά μπορεί να παρακαμφθεί από την εφαρμογή
php_value max_execution_time 60
Τα php_admin_value και php_admin_flag επιτρέπονται μόνο στη διαμόρφωση του διακομιστή, όχι στο .htaccess. Ακριβώς αυτή η διάκριση είναι σημαντική στα προσωρινά μέτρα για το PHP2Shell, επειδή τιμές όπως το session.upload_progress.enabled δεν επιτρέπεται να επαναφέρονται από την εφαρμογή.
mod_php και PHP2Shell: γιατί ο κίνδυνος είναι ο υψηλότερος
Η ομάδα της PHP κατατάσσει τον κίνδυνο από το PHP2Shell στο mod_php ως τον υψηλότερο: εκεί επιδείχθηκε exploit προτού καν εκτελεστεί κώδικας εφαρμογής. Τα plugins ασφαλείας ή οι έλεγχοι στο CMS έρχονται έτσι πολύ αργά. Προστίθεται ότι στο mod_php η PHP εκτελείται με τα δικαιώματα και στη μνήμη του διακομιστή ιστού. Η αναλυτική ένταξη βρίσκεται στη σελίδα Γιατί το mod_php φέρει τον υψηλότερο κίνδυνο.
Για τους διαχειριστές ισχύει γι' αυτό:
- Ενημερώστε τη μονάδα PHP στις 8.5.12, 8.4.27, 8.3.36 ή 8.2.35, αντίστοιχα σε ένα επιβεβαιωμένο backport.
- Επανεκκινήστε πλήρως τον Apache, όχι μόνο reload, και ελέγξτε την ώρα εκκίνησης των διεργασιών.
- Ορίστε προσωρινές τιμές μέσω
php_admin_valueστη διαμόρφωση του διακομιστή, όταν η ενημέρωση δεν είναι ακόμη δυνατή. - Έπειτα σχεδιάστε τη μετάβαση στο PHP-FPM, όπως περιγράφεται στη σελίδα Θωράκιση του Apache με mod_php.
Πώς βοηθά συγκεκριμένα η PHP SOS;
- Αναγνώριση: Ελέγχουμε σε ποιους διακομιστές εκτελείται το mod_php, με ποιο MPM και από ποια πηγή πακέτων.
- Ενημέρωση: Ενημερώνουμε τη μονάδα PHP, επανεκκινούμε πλήρως τον Apache και τεκμηριώνουμε την κατάσταση.
- Ασφάλιση της μετάβασης: Όπου η ενημέρωση είναι μπλοκαρισμένη, ορίζουμε τα μέτρα του php.net κλειδωμένα στη διαμόρφωση του διακομιστή.
- Μετάβαση: Στο πλαίσιο της θωράκισης διακομιστή μεταβαίνουμε δοκιμασμένα στο PHP-FPM με δικά του pools.
Συχνές ερωτήσεις
Γιατί λέγεται mod_php, αφού η μονάδα ονομάζεται php_module;
Το mod_php είναι η καθομιλουμένη ονομασία για την PHP ως μονάδα Apache. Στη διαμόρφωση φορτώνεται με LoadModule· το εγχειρίδιο της PHP αναφέρει ως παράδειγμα το LoadModule php_module modules/libphp.so. Παλαιότερες εκδόσεις χρησιμοποιούσαν ονόματα όπως php7_module ή php5_module.
Γιατί το mod_php χρειάζεται το MPM prefork;
Σύμφωνα με το εγχειρίδιο της PHP, το mod_php απαιτεί το MPM prefork, εφόσον η PHP δεν έχει κατασκευαστεί με Zend Thread Safety. Τα περισσότερα πακέτα διανομών κατασκευάζονται χωρίς Thread Safety. Το prefork ξεκινά για κάθε ταυτόχρονη σύνδεση μια ξεχωριστή διεργασία, κάτι που απαιτεί περισσότερη μνήμη.
Λειτουργούν οι γραμμές php_value στο .htaccess και με το PHP-FPM;
Όχι. Τα php_value και php_flag στο .htaccess είναι οδηγίες Apache της μονάδας PHP και ισχύουν μόνο με το mod_php. Στο PHP-FPM τέτοιες ρυθμίσεις ανήκουν στο pool ή, για επιτρεπόμενες τιμές, σε ένα .user.ini.
Πρέπει να καταργήσω αμέσως το mod_php;
Πρώτα έρχεται η ενημέρωση της PHP με πλήρη επανεκκίνηση του Apache. Η μετάβαση στο PHP-FPM είναι κατόπιν λογική, πρέπει όμως να σχεδιαστεί και να δοκιμαστεί. Δεν κλείνει το PHP2Shell, επειδή και το PHP-FPM επηρεάζεται.