Εν συντομία: Το open_basedir περιορίζει τους καταλόγους στους οποίους επιτρέπεται η πρόσβαση της PHP. Μόνο του είναι απλώς ένα πρόσθετο φράγμα. Αποτελεσματική απομόνωση ανά ιστότοπο προκύπτει μόνο από τον συνδυασμό: ξεχωριστός χρήστης συστήματος, ξεχωριστό pool PHP-FPM, ξεχωριστός φάκελος tmp και ξεχωριστές προσβάσεις στη βάση δεδομένων. Τότε μια εισβολή σε έναν ιστότοπο περιορίζεται σε αυτόν τον ιστότοπο.
Γιατί μετά το PHP2Shell η απομόνωση καθορίζει τη ζημιά
Σε πολλούς διακομιστές εκτελούνται πολλοί ιστότοποι δίπλα-δίπλα: ο ιστότοπος της εταιρείας, ένα κατάστημα, μια παλιά σελίδα καμπάνιας, σε πρακτορεία συχνά δεκάδες έργα πελατών. Συχνά μοιράζονται έναν χρήστη συστήματος και μια διεργασία PHP. Αν παραβιαστεί ένας από αυτούς, όλοι οι άλλοι είναι εκτεθειμένοι.
Το PHP2Shell κάνει αυτόν τον κίνδυνο απτό. Οι ευπάθειες CVE-2026-109618 και CVE-2026-109619 επιτρέπουν την εκτέλεση κακόβουλου κώδικα χωρίς σύνδεση, ανεξάρτητα από το CMS. Σύμφωνα με δημοσιεύματα, υπήρξε ήδη στις 17.10.2026 μια πρώτη απόπειρα επίθεσης, ενώ τα patches ακολούθησαν στις 21.10. Η διόρθωση είναι η ενημέρωση. Το αν μια επίθεση στο διάστημα πριν πλήττει έναν ιστότοπο ή δέκα, το καθορίζει όμως η απομόνωση.
Ειδικά στη δεύτερη ευπάθεια προστίθεται μια ακόμη σκέψη: σύμφωνα με το έργο PHP, η εσωτερική κατάσταση ενός αιτήματος μπορεί να παραμείνει σε έναν worker και να χρησιμοποιηθεί από ένα μεταγενέστερο αίτημα στον ίδιο worker. Τα χωριστά pools ανά ιστότοπο φροντίζουν ώστε οι ιστότοποι να μην μοιράζονται καθόλου workers.
Τι προσφέρει το open_basedir
Με το open_basedir ορίζετε μια λίστα καταλόγων. Οι συναρτήσεις αρχείων της PHP όπως οι fopen, include ή file_get_contents αρνούνται τότε την πρόσβαση σε οτιδήποτε εκτός αυτής της λίστας. Ένα script που έχει εισαχθεί κρυφά δεν μπορεί έτσι εύκολα να διαβάσει τα αρχεία διαμόρφωσης του γειτονικού ιστότοπου.
Τα όρια είναι σημαντικά: ο έλεγχος γίνεται μέσα στην PHP. Προγράμματα που εκκινούνται εκτός PHP δεν υπόκεινται σε αυτόν και σφάλματα στον διερμηνέα μπορούν να τον παρακάμψουν. Γι' αυτό το open_basedir ανήκει πάντα μαζί με αποκλεισμένες συναρτήσεις συστήματος, όπως περιγράφεται στον οδηγό Σωστή χρήση του disable_functions, και πάνω απ' όλα με διαχωρισμό σε επίπεδο λειτουργικού συστήματος.
Απομόνωση ανά ιστότοπο σε τέσσερα επίπεδα
Ένας ανθεκτικός διαχωρισμός βασίζεται σε πολλά επίπεδα. Κάθε ένα αναχαιτίζει ό,τι δεν καλύπτει το προηγούμενο.
| Επίπεδο | Μέτρο | Αποτέλεσμα |
|---|---|---|
| Λειτουργικό σύστημα | ξεχωριστός χρήστης συστήματος ανά ιστότοπο | Τα αρχεία άλλων ιστοτόπων δεν είναι αναγνώσιμα |
| Διεργασίες PHP | ξεχωριστό pool PHP-FPM με δικό του socket | κανένας κοινός worker, δικές του ρυθμίσεις |
| Διαμόρφωση PHP | open_basedir, δικοί του φάκελοι tmp και session |
πρόσθετο φράγμα, κανένα κοινό προσωρινό αρχείο |
| Δεδομένα | ξεχωριστός χρήστης βάσης δεδομένων με δικαιώματα μόνο στη δική του βάση | καμία πρόσβαση σε ξένα δεδομένα πελατών |
Σε υψηλή ανάγκη προστασίας, π.χ. σε καταστήματα με διεκπεραίωση πληρωμών ή σε portals με δεδομένα υγείας, προστίθενται containers ή χωριστοί διακομιστές.
Ρύθμιση του open_basedir στο pool PHP-FPM
Το παρακάτω παράδειγμα δείχνει ένα pool για έναν ιστότοπο με δικό του χρήστη seite1. Τις διαδρομές και τον αριθμό έκδοσης τους προσαρμόζετε στο σύστημά σας.
; /etc/php/8.3/fpm/pool.d/seite1.conf
[seite1]
user = seite1
group = seite1
listen = /run/php/seite1.sock
listen.owner = www-data
listen.group = www-data
listen.mode = 0660
pm = ondemand
pm.max_children = 10
php_admin_value[open_basedir] = /var/www/seite1/:/var/www/seite1-tmp/
php_admin_value[upload_tmp_dir] = /var/www/seite1-tmp/
php_admin_value[sys_temp_dir] = /var/www/seite1-tmp/
php_admin_value[session.save_path] = /var/www/seite1-tmp/sessions
php_admin_value[error_log] = /var/log/php/seite1.error.log
php_admin_flag[session.upload_progress.enabled] = off
Η τελευταία γραμμή ορίζει ταυτόχρονα το προσωρινό μέτρο του php.net για το PHP2Shell. Ισχύει μόνο από το pool, το php.ini ή τη διαμόρφωση του διακομιστή, όχι μέσω ini_set() ή .user.ini. Τους φακέλους τους δημιουργείτε με τα κατάλληλα δικαιώματα:
sudo useradd --system --home /var/www/seite1 --shell /usr/sbin/nologin seite1
sudo mkdir -p /var/www/seite1-tmp/sessions
sudo chown -R seite1:seite1 /var/www/seite1-tmp
sudo chmod 700 /var/www/seite1-tmp
Πώς πρέπει να έχουν τα δικαιώματα στον ίδιο τον κατάλογο του ιστού, περιγράφει ο οδηγός Δικαιώματα αρχείων στον διακομιστή ιστού.
Σύνδεση του διακομιστή ιστού και έλεγχος του αποτελέσματος
Στο Nginx κάθε ιστότοπος παραπέμπει στο δικό του socket. Έτσι κανένα αίτημα δεν καταλήγει στο pool ενός άλλου ιστότοπου.
server {
server_name seite1.example;
root /var/www/seite1/public;
location ~ \.php$ {
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_pass unix:/run/php/seite1.sock;
}
}
Περαιτέρω υποδείξεις για αυτόν τον συνδυασμό θα βρείτε στη σελίδα Ασφάλεια του Nginx με PHP-FPM. Μετά την επανεκκίνηση ελέγχετε αν τα pools εκτελούνται πράγματι χωριστά:
sudo systemctl restart php8.3-fpm
# Κάθε pool πρέπει να εκτελείται υπό τον δικό του χρήστη
ps -eo user,pid,cmd | grep "[p]hp-fpm: pool"
Δοκιμάστε στη συνέχεια όλες τις λειτουργίες του ιστότοπου: uploads, επεξεργασία εικόνας, caches, προγραμματισμένες εργασίες. Μηνύματα σφάλματος με την ένδειξη open_basedir restriction στο log σφαλμάτων δείχνουν ποια διαδρομή λείπει ακόμη. Προσθέστε μόνο διαδρομές που η εφαρμογή χρειάζεται πραγματικά, και ποτέ ολόκληρο το σύστημα αρχείων.
Τα πρακτορεία με πολλούς ιστοτόπους πελατών πρέπει να διατηρούν τη διαμόρφωση του pool ως πρότυπο. Έτσι κάθε νέος ιστότοπος αποκτά τον διαχωρισμό αυτόματα, αντί να χρειαστεί να προστεθεί αργότερα. Το υπόβαθρο για αυτή την περίπτωση βρίσκεται στη σελίδα Συνεργάτης ασφάλειας για πρακτορεία.
Τυπικά εμπόδια κατά τη μετάβαση
Η μετάβαση σε χωριστά pools είναι προγραμματίσιμη, έχει όμως ορισμένες επαναλαμβανόμενες παγίδες. Η συχνότερη αφορά κοινόχρηστες βιβλιοθήκες: αν π.χ. ένα framework ή ένας φάκελος με γραμματοσειρές βρίσκεται εκτός του καταλόγου του ιστότοπου, αυτή η διαδρομή πρέπει να προστεθεί στο open_basedir για ανάγνωση. Καλύτερο είναι να φέρετε τέτοιες εξαρτήσεις μέσα στο ίδιο το έργο.
Η δεύτερη παγίδα είναι τα sessions. Αν αλλάξει ο χώρος αποθήκευσης, όλοι οι επισκέπτες αποσυνδέονται μία φορά και τα καλάθια αγορών που βρίσκονται σε εξέλιξη χάνονται. Προγραμματίστε γι' αυτό τη μετάβαση σε ήσυχο χρονικό παράθυρο και ανακοινώστε την εσωτερικά.
Τρίτον, οι προγραμματισμένες εργασίες εκτελούνται συχνά μέσω της γραμμής εντολών και άρα υπό διαφορετικό χρήστη από τον ιστότοπο. Ελέγξτε τα cronjobs και τις ουρές και αφήστε τα να εκτελούνται υπό τον νέο χρήστη του ιστότοπου, αλλιώς δημιουργούνται αρχεία με λάθος ιδιοκτήτη, τα οποία η PHP δεν επιτρέπεται αργότερα να αλλάξει.
Τέλος, κάθε pool πρέπει να έχει δικά του όρια για διεργασίες και μνήμη. Ένας ιστότοπος που δέχεται φόρτο ή δέχεται επίθεση δεν μπορεί έτσι να λυγίσει και τους υπόλοιπους.
Πώς βοηθά συγκεκριμένα η PHP SOS;
- Καταγράφουμε ποιοι ιστότοποι μοιράζονται σήμερα χρήστες, διεργασίες και βάσεις δεδομένων.
- Στήνουμε για κάθε ιστότοπο δικούς του χρήστες, pools, φακέλους tmp και προσβάσεις στη βάση δεδομένων, χωρίς να αλλάξουμε τις εφαρμογές.
- Δοκιμάζουμε κάθε ιστότοπο μετά τη μετάβαση και διορθώνουμε στοχευμένα τις διαδρομές που λείπουν.
- Τεκμηριώνουμε τον διαχωρισμό ως πρότυπο για μελλοντικά έργα.
Πώς εντάσσεται αυτό σε μια συνολική στρατηγική, περιγράφει η υπηρεσία Θωράκιση διακομιστών PHP.
Συχνές ερωτήσεις
Αρκεί το open_basedir για να διαχωρίσω τους ιστοτόπους μεταξύ τους;
Όχι. Το open_basedir είναι ένα πρόσθετο φράγμα μέσα στην PHP, όχι σκληρός διαχωρισμός. Αξιόπιστη γίνεται η απομόνωση μόνο με ξεχωριστούς χρήστες συστήματος και pools ανά ιστότοπο, και σε υψηλότερη ανάγκη προστασίας με containers ή χωριστούς διακομιστές.
Γιατί μετά τη ρύθμιση του open_basedir δεν λειτουργούν πλέον τα uploads;
Συνήθως λείπει από τη λίστα ο φάκελος για τα προσωρινά αρχεία. Δημιουργήστε για κάθε ιστότοπο έναν δικό του φάκελο tmp, καταχωρίστε τον στο open_basedir και ορίστε τα upload_tmp_dir και sys_temp_dir σε αυτόν τον φάκελο.
Μπορεί μια εφαρμογή να άρει μόνη της το open_basedir;
Μια εφαρμογή μπορεί να περιορίσει περαιτέρω τη ρύθμιση κατά την εκτέλεση, αλλά όχι να τη χαλαρώσει. Ορίστε παρ' όλα αυτά το open_basedir μέσω php_admin_value στο pool, ώστε η τιμή να είναι αδιαμφισβήτητα σταθερή.
Είναι δυνατή η απομόνωση και στο shared hosting;
Αυτό εξαρτάται από τον πάροχο. Πολλές προσφορές διαχωρίζουν τους πελάτες μέσω ξεχωριστών χρηστών και διεργασιών PHP. Ρωτήστε πώς υλοποιείται ο διαχωρισμός, ιδίως αν περισσότεροι ιστότοποί σας βρίσκονται σε ένα πακέτο.