Εν ολίγοις: Με expose_php = Off στο php.ini εξαφανίζεται η κεφαλίδα X-Powered-By: PHP/…. Σε αυτό προστίθενται το server_tokens off; στο Nginx και τα ServerTokens Prod και ServerSignature Off στον Apache. Αυτό δεν κάνει κανέναν διακομιστή ασφαλέστερο, αφαιρεί όμως από τις αυτοματοποιημένες σαρώσεις μια έτοιμη λίστα εκδόσεων. Την κατάσταση των patches την ελέγχετε στη συνέχεια μέσω του διαχειριστή πακέτων και των διεργασιών, όχι μέσω κεφαλίδων.
Η επαγγελματική κάρτα σε κάθε απάντηση
Όποιος ήθελε να μάθει μετά τις 21 Οκτωβρίου 2026 πόσοι διακομιστές εμφανίζουν ακόμη παλιά έκδοση PHP, δεν χρειαζόταν να ψάξει πολύ. Πολλοί διακομιστές ιστού αναφέρουν την έκδοση PHP σε κάθε μεμονωμένη απάντηση, για παράδειγμα ως X-Powered-By: PHP/8.2.20. Υπηρεσίες αναζήτησης σε όλο το διαδίκτυο διαβάζουν αυτές τις ενδείξεις και η Unit 42 της Palo Alto Networks μέτρησε για το PHP2Shell περισσότερες από 22,6 εκατομμύρια εκτεθειμένες, δυνητικά ευάλωτες εγκαταστάσεις.
Για τους επιτιθέμενους μια τέτοια ένδειξη είναι συντόμευση. Μπορούν να προταξινομήσουν στόχους, αντί να δοκιμάζουν στα τυφλά. Για τους φορείς λειτουργίας είναι αντίθετα άχρηστη, επειδή δεν αποδεικνύει ούτε την κατάσταση των patches: οι διανομές παραδίδουν συχνά διορθώσεις ως backport χωρίς νέο αριθμό έκδοσης.
Αυτό το άρθρο δείχνει πού αποκαλύπτουν πληροφορίες έκδοσης η PHP και ο διακομιστής ιστού και πώς απενεργοποιούνται οι ενδείξεις. Λέει επίσης ανοιχτά τι προσφέρει αυτό και τι όχι.
Πού εμφανίζονται παντού οι ενδείξεις έκδοσης
Η έκδοση PHP είναι μόνο ένα από πολλά σημεία. Αξίζει μια πλήρης ματιά, επειδή ένα μοναδικό ξεχασμένο σημείο υποβαθμίζει τα υπόλοιπα μέτρα.
| Σημείο εύρεσης | Παράδειγμα | Απενεργοποίηση μέσω |
|---|---|---|
| Κεφαλίδα HTTP της PHP | X-Powered-By: PHP/8.3.x |
expose_php = Off στο php.ini |
| Κεφαλίδα HTTP του διακομιστή ιστού | Server: nginx/1.x ή Server: Apache/2.4.x (Debian) |
server_tokens off; αντίστοιχα ServerTokens Prod |
| Σελίδες σφάλματος του διακομιστή ιστού | γραμμή έκδοσης κάτω από σελίδες 404 ή 500 | οι ίδιες ρυθμίσεις, στον Apache επιπλέον ServerSignature Off |
| Κεφαλίδες της εφαρμογής | δικές τους ενδείξεις X-Powered-By από frameworks |
fastcgi_hide_header αντίστοιχα Header unset |
| Αρχεία στο webroot | δοκιμαστικά αρχεία phpinfo(), αρχεία readme και changelog |
διαγραφή ή αποκλεισμός |
| Μηνύματα σφάλματος της PHP | διαδρομές και λεπτομέρειες έκδοσης στον περιηγητή | display_errors = Off |
Τα δοκιμαστικά αρχεία με phpinfo() είναι εδώ η πιο γόνιμη πηγή για τους επιτιθέμενους. Αποκαλύπτουν όχι μόνο την έκδοση αλλά ολόκληρη τη διαμόρφωση· περισσότερα στο άρθρο Αρχεία phpinfo(): γιατί πρέπει να εξαφανιστούν.
Απενεργοποίηση του expose_php στο php.ini
Σύμφωνα με το εγχειρίδιο της PHP, το expose_php είναι από προεπιλογή ενεργοποιημένο και μπορεί να αλλάξει μόνο στο php.ini, όχι στο pool, όχι με .htaccess και όχι κατά την εκτέλεση. Ορίστε την τιμή γι' αυτό στο php.ini κάθε τρόπου λειτουργίας που σερβίρει ιστοτόπους, δηλαδή σε Debian και Ubuntu για παράδειγμα στο /etc/php/<version>/fpm/ και ενδεχομένως στο /etc/php/<version>/apache2/.
; php.ini του SAPI ιστού, μετά επανεκκίνηση του PHP-FPM ή του Apache
expose_php = Off
Αν εκτελούνται παράλληλα πολλές εκδόσεις PHP, καθεμία χρειάζεται τη δική της καταχώριση. Η επανεκκίνηση της αντίστοιχης υπηρεσίας είναι υποχρεωτική, επειδή η PHP διαβάζει το php.ini μόνο κατά την εκκίνηση.
Συντόμευση των κεφαλίδων Server σε Nginx και Apache
Το Nginx αναφέρει από προεπιλογή την έκδοσή του στην κεφαλίδα Server και στις σελίδες σφάλματος. Με το server_tokens off; μένει μόνο το όνομα του προϊόντος. Επιπλέον, μια κεφαλίδα X-Powered-By που ορίζει η ίδια η εφαρμογή μπορεί να φιλτραριστεί με fastcgi_hide_header. Σύμφωνα με την τεκμηρίωση του Nginx, το Nginx αποκρύπτει από μόνο του μόνο τα Status και X-Accel-…, όχι το X-Powered-By.
# στο μπλοκ http, ισχύει για όλους τους ιστοτόπους
server_tokens off;
fastcgi_hide_header X-Powered-By;
Στον Apache το ServerTokens ελέγχει την κεφαλίδα Server και ταυτόχρονα τη γραμμή έκδοσης κάτω από τις σελίδες σφάλματος. Η ρύθμιση ισχύει, σύμφωνα με την τεκμηρίωση του Apache, μόνο σε επίπεδο διακομιστή και όχι ανά VirtualHost. Επειδή οι απαντήσεις του PHP-FPM μέσω mod_proxy_fcgi καταλήγουν σε άλλον πίνακα κεφαλίδων από τις απαντήσεις του ίδιου του διακομιστή, ορίστε την αφαίρεση και στις δύο παραλλαγές.
# διαμόρφωση σε επίπεδο διακομιστή, π.χ. /etc/apache2/conf-available/security.conf
ServerTokens Prod
ServerSignature Off
# απαιτεί mod_headers
<IfModule mod_headers.c>
Header unset X-Powered-By
Header always unset X-Powered-By
</IfModule>
Ελέγξτε τη διαμόρφωση πριν από την επαναφόρτωση με nginx -t αντίστοιχα apachectl configtest. Πώς ενεργοποιείτε μέσω κεφαλίδων ενεργή προστασία για τους επισκέπτες, για παράδειγμα με HSTS ή Content-Security-Policy, περιγράφει ο οδηγός Κεφαλίδες ασφαλείας για ιστότοπους.
Έτσι ελέγχετε το αποτέλεσμα απ' έξω
Ελέγξτε μετά τη μετάβαση κάθε domain ξεχωριστά, αν είναι δυνατό και μια σελίδα σφάλματος. Οι παρακάτω εντολές στέλνουν μόνο κανονικά αιτήματα στους δικούς σας ιστοτόπους:
# Κεφαλίδες της αρχικής σελίδας
curl -sI https://www.example.de/ | grep -iE '^(server|x-powered-by):'
# Κεφαλίδες μιας σελίδας που δεν υπάρχει
curl -sI https://www.example.de/gibt-es-nicht-4711 | grep -iE '^(server|x-powered-by):'
Αναμένεται κεφαλίδα Server χωρίς αριθμό έκδοσης και κανένα X-Powered-By. Αν εξακολουθεί να εμφανίζεται έκδοση PHP, συνήθως είναι ενεργό άλλο php.ini ή μια υπηρεσία δεν έχει ακόμη επανεκκινηθεί. Αν μπροστά από τον διακομιστή βρίσκεται CDN, ελέγξτε επιπλέον απευθείας τον διακομιστή προέλευσης, εφόσον είναι προσβάσιμος.
Κρατήστε παρ' όλα αυτά εσωτερικά την έκδοση PHP: στο αρχείο καταγραφής διακομιστών σας, με την κατάσταση πακέτων και την ημερομηνία του τελευταίου ελέγχου. Την κατάσταση των patches την αποδεικνύετε μέσω του διακομιστή, όπως περιγράφεται στο Σωστός έλεγχος της έκδοσης PHP και της κατάστασης των patches.
Τι προσφέρει η απόκρυψη και τι όχι
Με ειλικρίνεια, η απενεργοποίηση των ενδείξεων έκδοσης είναι ένα μικρό μέτρο με μικρό κόστος. Μειώνει την πιθανότητα να εμφανιστείτε σε στοχευμένες αναζητήσεις για συγκεκριμένες εκδόσεις και περιορίζει τις πληροφορίες που παίρνει ένας επιτιθέμενος χωρίς κόπο.
Δεν προστατεύει όμως από αυτοματοποιημένες επιθέσεις που στέλνουν απλώς τα αιτήματά τους σε κάθε προσβάσιμο διακομιστή. Πώς εξελίσσονται τέτοιες μαζικές σαρώσεις, περιγράφει το άρθρο Μαζικές σαρώσεις για PHP χωρίς patch. Κατά του PHP2Shell βοηθά μόνο η ενημέρωση σε PHP 8.5.12, 8.4.27, 8.3.36 ή 8.2.35 αντίστοιχα σε επιβεβαιωμένο backport, ακολουθούμενη από επανεκκίνηση όλων των διεργασιών PHP.
Μια παρενέργεια είναι αντίθετα εξαιρετικά χρήσιμη: όποιος απενεργοποιεί προς τα έξω τις ενδείξεις έκδοσης πρέπει να καταγράφει σωστά τις εκδόσεις του εσωτερικά. Σε μια κατάσταση όπως το PHP2Shell, ακριβώς αυτή η επισκόπηση αποφασίζει πόσο γρήγορα θα γνωρίζετε ποιοι διακομιστές επηρεάζονται.
Η απόκρυψη έχει επομένως νόημα ως μέρος μιας βασικής σκλήρυνσης και όχι ως μεμονωμένο μέτρο. Ανήκει στην ίδια λίστα ελέγχου με τις απενεργοποιημένες εξόδους σφαλμάτων, τα διαγραμμένα δοκιμαστικά αρχεία και τις κλειδωμένες τιμές διαμόρφωσης.
Πώς βοηθά συγκεκριμένα η PHP SOS;
- Καταγραφή των σημείων εύρεσης: Ελέγχουμε κεφαλίδες, σελίδες σφάλματος και webroot όλων των domains για ενδείξεις έκδοσης και ξεχασμένα δοκιμαστικά αρχεία.
- Προσαρμογή της διαμόρφωσης: Ορίζουμε
expose_php, κεφαλίδες Server και φίλτρα κεφαλίδων σε κάθε έκδοση PHP και κάθε διακομιστή ιστού και επανεκκινούμε ελεγχόμενα τις υπηρεσίες. - Εσωτερική τεκμηρίωση της κατάστασης patches: Τεκμηριώνουμε εκδόσεις και καταστάσεις πακέτων εκεί που ανήκουν, στο αρχείο καταγραφής και όχι στην κεφαλίδα HTTP.
- Ενσωμάτωση στη σκλήρυνση: Το μέτρο αποτελεί μέρος της σκλήρυνσης διακομιστή για διακομιστές ιστού PHP.
Συχνές ερωτήσεις
Κάνει το expose_php = Off τον διακομιστή μου ασφαλή;
Όχι. Η ρύθμιση αφαιρεί μόνο την ένδειξη έκδοσης από την κεφαλίδα HTTP. Μια ευάλωτη έκδοση PHP παραμένει ευάλωτη και οι αυτοματοποιημένες επιθέσεις δοκιμάζουν συχνά τα αιτήματά τους ούτως ή άλλως σε κάθε προσβάσιμο διακομιστή. Αφαιρούν όμως από τους επιτιθέμενους μια εύκολη προεπιλογή και μειώνουν την ορατότητα σε μηχανές αναζήτησης διακομιστών.
Μπορώ να ορίσω το expose_php στο pool FPM ή με .htaccess;
Σύμφωνα με το εγχειρίδιο της PHP, το expose_php μπορεί να αλλάξει μόνο στο php.ini. Ορίστε την τιμή γι' αυτό στο php.ini κάθε SAPI ιστού και επανεκκινήστε στη συνέχεια το PHP-FPM ή τον Apache.
Γιατί βλέπω X-Powered-By παρά το expose_php = Off;
Τότε συνήθως η ίδια η εφαρμογή ή ένα framework ορίζει την κεφαλίδα ή είναι ενεργό άλλο php.ini. Αφαιρέστε επιπλέον την κεφαλίδα στον διακομιστή ιστού: με fastcgi_hide_header στο Nginx ή Header unset στον Apache.
Πώς ελέγχω την κατάσταση των patches όταν η έκδοση δεν είναι πλέον ορατή;
Μέσω του ίδιου του διακομιστή: διαχειριστής πακέτων, changelog του πακέτου με τους αριθμούς CVE και χρόνος εκκίνησης των διεργασιών PHP. Η ένδειξη στην κεφαλίδα HTTP δεν αποτελούσε ούτως ή άλλως απόδειξη, επειδή οι διανομές εφαρμόζουν συχνά backports χωρίς νέο αριθμό έκδοσης.