Τρέχουσα κατάσταση: PHP2Shell. Δύο κρίσιμες ευπάθειες της PHP (CVSS 9.2) επιτρέπουν κακόβουλο κώδικα χωρίς σύνδεση. Patches από τις 21/10/2026.Τι πρέπει να γίνει τώρα →

php_admin_value: κλείδωμα ρυθμίσεων κατά της αντικατάστασης

Μια ρύθμιση ασφαλείας αξίζει λίγο, αν η εφαρμογή την αλλάζει ξανά με μία γραμμή κώδικα. Με τα php_admin_value και php_admin_flag ορίζετε δεσμευτικά τιμές για το PHP-FPM και τον Apache.

Ημερομηνία 6 λεπτά ανάγνωσηςΣκλήρυνση και διαμόρφωση

Εν ολίγοις: Τα php_admin_value και php_admin_flag ορίζουν ρυθμίσεις PHP στο pool του PHP-FPM ή στη διαμόρφωση του Apache έτσι ώστε οι εφαρμογές να μην μπορούν να τις αλλάξουν ούτε με ini_set() ούτε με .htaccess. Το php.net απαιτεί ακριβώς αυτό για τα μεταβατικά μέτρα του PHP2Shell, για παράδειγμα για το memory_limit=-1. Μετά τον ορισμό η υπηρεσία πρέπει να επανεκκινηθεί και η τιμή να ελεγχθεί στο πλαίσιο του web.

Γιατί «ορισμένο» δεν σημαίνει «κλειδωμένο»

Τις ημέρες μετά τις 21 Οκτωβρίου 2026 πολλοί διαχειριστές έγραψαν τα μεταβατικά μέτρα του php.net στο php.ini τους. Μια λεπτομέρεια της σύστασης συχνά χάθηκε: το memory_limit=-1 πρέπει να οριστεί έτσι ώστε οι εφαρμογές να μην μπορούν να το αντικαταστήσουν. Το php.net αναφέρει γι' αυτό ρητά το php_admin_value στο pool FPM ή στη διαμόρφωση του Apache.

Ο λόγος είναι απλός. Πολλά CMS, καταστήματα και frameworks ορίζουν τις δικές τους τιμές, για παράδειγμα υψηλότερο όριο μνήμης για εισαγωγές. Αν η τιμή βρίσκεται μόνο στο php.ini, η εφαρμογή την αντικαθιστά στην επόμενη κλήση. Το μέτρο προστασίας υπάρχει τότε στα χαρτιά, αλλά όχι στη διεργασία που εκτελείται.

Αυτό δεν αφορά μόνο το PHP2Shell. Κάθε σκλήρυνση, από τις απενεργοποιημένες εξόδους σφαλμάτων έως τα όρια ανεβάσματος, είναι τόσο ισχυρή όσο το πιο αδύναμο επίπεδό της.

Ποιος επιτρέπεται να αλλάζει ρυθμίσεις PHP

Η PHP γνωρίζει τέσσερις τρόπους αλλαγής. Κάθε ρύθμιση έχει έναν από αυτούς και καθορίζει σε ποια σημεία μπορεί να οριστεί. Οι σημασίες προέρχονται από το εγχειρίδιο της PHP.

Τρόπος Πού μπορεί να οριστεί η τιμή Παραδείγματα
INI_USER στο σενάριο με ini_set() και στο .user.ini λίγες τιμές εκτέλεσης
INI_PERDIR php.ini, .htaccess, httpd.conf, .user.ini post_max_size, session.upload_progress.enabled
INI_SYSTEM μόνο php.ini ή httpd.conf file_uploads, disable_functions
INI_ALL παντού, ακόμη και με ini_set() memory_limit, display_errors, open_basedir

Επικίνδυνες είναι κυρίως οι τιμές INI_ALL: μπορούν να αλλάξουν από οποιοδήποτε σενάριο. Οι τιμές INI_PERDIR δεν αλλάζουν μεν με ini_set(), αλλάζουν όμως μέσω ενός .htaccess με mod_php ή ενός .user.ini με PHP-FPM. Όποιος έχει δικαιώματα εγγραφής στο webroot, άρα και ο κώδικας που έχει εισαχθεί, μπορεί να δημιουργήσει τέτοια αρχεία.

php_admin_value στο pool FPM και στον Apache

Στο PHP-FPM οι τιμές βρίσκονται στο αρχείο του pool. Το εγχειρίδιο της PHP ορίζει: οι τιμές που ορίζονται με php_admin_value και php_admin_flag δεν μπορούν να αντικατασταθούν με ini_set(). Για τιμές ενεργοποίησης-απενεργοποίησης χρησιμοποιείτε php_admin_flag, για όλες τις άλλες php_admin_value.

; /etc/php/8.3/fpm/pool.d/seite1.conf (απόσπασμα)
[seite1]
user = seite1
group = seite1
listen = /run/php/seite1.sock

php_admin_value[memory_limit] = -1
php_admin_value[post_max_size] = 32M
php_admin_value[upload_max_filesize] = 24M
php_admin_flag[session.upload_progress.enabled] = off
php_admin_flag[display_errors] = off
php_admin_value[error_log] = /var/log/php/seite1-fehler.log
php_admin_value[open_basedir] = /var/www/seite1/:/tmp/seite1/

Το memory_limit=-1 ανήκει σύμφωνα με το php.net στη διαμόρφωση μόνο μαζί με όριο μνήμης μέσω container ή cgroup. Πώς επιτυγχάνεται αυτό με το systemd, αναφέρεται στο άρθρο Ορισμός ορίων μνήμης με systemd και cgroups.

Στον Apache με mod_php οι οδηγίες ανήκουν στη διαμόρφωση διακομιστή ή στο VirtualHost. Σύμφωνα με το εγχειρίδιο της PHP δεν επιτρέπονται στο .htaccess και, μόλις οριστούν, ούτε το .htaccess ούτε το ini_set() μπορούν να τις αλλάξουν.

<VirtualHost *:443>
    ServerName www.example.de
    DocumentRoot /var/www/seite1/public
    <IfModule php_module>
        php_admin_value memory_limit -1
        php_admin_value post_max_size 32M
        php_admin_value upload_max_filesize 24M
        php_admin_flag session.upload_progress.enabled off
        php_admin_flag display_errors off
    </IfModule>
</VirtualHost>

Δύο λεπτομέρειες από το εγχειρίδιο: για να διαγράψετε μια τιμή που ορίστηκε νωρίτερα, χρησιμοποιήστε none ως τιμή. Και οι σταθερές PHP όπως το E_ALL δεν έχουν νόημα στη διαμόρφωση του Apache· για το error_reporting πρέπει να δώσετε εκεί την αριθμητική τιμή.

Ποιες τιμές πρέπει να κλειδώσετε

Δεν χρειάζεται να κλειδωθεί κάθε ρύθμιση. Έχει νόημα για ό,τι αφορά την ασφάλεια ή χρησιμεύει ως μεταβατικό μέτρο:

  1. Οι μεταβατικές τιμές του php.net για το PHP2Shell: memory_limit, post_max_size, upload_max_filesize, session.upload_progress.enabled και στην PHP 8.5 fatal_error_backtraces.
  2. Έξοδος σφαλμάτων και καταγραφή: display_errors, display_startup_errors, log_errors, error_log.
  3. Πρόσβαση σε αρχεία και απομόνωση: open_basedir, upload_tmp_dir, session.save_path.
  4. Προσβάσεις δικτύου από την PHP: allow_url_include και, αν η εφαρμογή δεν το χρειάζεται, allow_url_fopen.
  5. Αποκλεισμένες συναρτήσεις μέσω disable_functions, που στο pool συμπληρώνουν σύμφωνα με το εγχειρίδιο τη λίστα του php.ini και δεν την αντικαθιστούν. Λεπτομέρειες στον οδηγό Σωστή χρήση του disable_functions.

Στο session.upload_progress.enabled το κλείδωμα είναι ιδιαίτερα σημαντικό, επειδή αλλιώς η τιμή θα μπορούσε να ενεργοποιηθεί ξανά μέσω ενός .user.ini. Περισσότερα στο Απενεργοποίηση του session.upload_progress: σωστά και μόνιμα.

Έλεγχος αν το κλείδωμα ισχύει

Μετά από κάθε αλλαγή επανεκκινείτε την υπηρεσία και ελέγχετε την τιμή στο πλαίσιο του web. Ένα σύντομο αρχείο ελέγχου που διαγράφεται αμέσως δείχνει αν το pool κρατά την τιμή, ακόμη κι όταν η εφαρμογή θέλει να την αλλάξει:

<?php
// Αρχείο ελέγχου: αφήστε το για λίγο, καλέστε το μία φορά μέσω του domain, διαγράψτε το αμέσως
header('Content-Type: text/plain');
$vorher = ini_get('memory_limit');
$versuch = @ini_set('memory_limit', '256M');
echo "memory_limit: $vorher\n";
echo 'Änderung per ini_set() ', ($versuch === false ? 'blockiert' : 'MÖGLICH'), "\n";

Αναμένεται -1 και «blockiert». Αν η έξοδος είναι «MÖGLICH», η τιμή δεν έχει οριστεί μέσω php_admin_value ή η υπηρεσία δεν έχει ακόμη επανεκκινηθεί. Επαναλάβετε τον έλεγχο για κάθε pool και κάθε έκδοση PHP.

Συμβουλή

Κρατήστε τις κλειδωμένες τιμές κεντρικά, για παράδειγμα σε ένα πρότυπο pool ή στη διαχείριση διαμόρφωσής σας. Οι πίνακες ελέγχου φιλοξενίας αντικαθιστούν εν μέρει χειροκίνητα αλλαγμένα αρχεία pool στην επόμενη αποθήκευση· εκεί οι τιμές ανήκουν στα πεδία που προβλέπει ο πίνακας.

Πώς οργανώνει συνολικά η PHP τα επίπεδα διαμόρφωσής της, εξηγεί το Το php.ini εξηγημένο: δομή, επίπεδα και προτεραιότητα. Τα πλήρη μεταβατικά μέτρα υπάρχουν στο Άμεσα μέτρα όταν δεν μπορείτε ακόμη να εφαρμόσετε patch.

Συμπέρασμα: μόνο το κλειδωμένο είναι πραγματικά ορισμένο

Τα μεταβατικά μέτρα του php.net για το PHP2Shell έφεραν στη συνείδηση μια διάκριση που πριν συχνά παραβλεπόταν: μια τιμή στο php.ini είναι για πολλές ρυθμίσεις απλώς πρόταση, μια τιμή στο php_admin_value είναι προδιαγραφή. Για ρυθμίσεις άνεσης όπως η ζώνη ώρας η διαφορά είναι αμελητέα. Για ρυθμίσεις ασφαλείας και μεταβατικά μέτρα αποφασίζει αν το μέτρο ισχύει καν στη λειτουργία.

Η προσπάθεια είναι διαχειρίσιμη: μια χούφτα γραμμές ανά pool ή VirtualHost, μια επανεκκίνηση, ένας σύντομος έλεγχος. Κρατήστε τη λίστα των κλειδωμένων τιμών μικρή και αιτιολογημένη, ώστε οι προγραμματιστές να κατανοούν γιατί η εφαρμογή τους δεν επιτρέπεται να αλλάξει μια τιμή. Και συντηρήστε τη λίστα στα πρότυπά σας, ώστε οι νέοι ιστότοποι να την κληρονομούν αυτόματα.

Πώς βοηθά συγκεκριμένα η PHP SOS;

  • Ανάγνωση των επιπέδων: Εντοπίζουμε για κάθε ιστότοπο ποιες τιμές από php.ini, pool, Apache, .htaccess ή .user.ini ισχύουν πραγματικά.
  • Ορισμός κλειδωμάτων: Καταχωρίζουμε τις τιμές που αφορούν την ασφάλεια και τα μεταβατικά μέτρα του PHP2Shell ως php_admin_value αντίστοιχα php_admin_flag και επανεκκινούμε τις υπηρεσίες.
  • Δοκιμή της εφαρμογής: Ελέγχουμε αν η εφαρμογή εκτελείται χωρίς σφάλματα με τις κλειδωμένες τιμές και αξιολογούμε το log σφαλμάτων.
  • Συντήρηση προτύπων: Στο πλαίσιο της σκλήρυνσης διακομιστή περνάμε τις τιμές σε πρότυπα pool και τεκμηρίωση.

Συχνές ερωτήσεις

Ποια είναι η διαφορά ανάμεσα στο php_value και στο php_admin_value;

Και τα δύο ορίζουν μια ρύθμιση PHP. Τις τιμές από το php_value μπορεί η εφαρμογή να τις αλλάξει αργότερα, για παράδειγμα με ini_set() ή .htaccess. Οι τιμές από το php_admin_value και το php_admin_flag είναι σύμφωνα με το εγχειρίδιο της PHP κλειδωμένες για το ini_set(), στον Apache και για το .htaccess.

Μπορώ να γράψω το php_admin_value σε αρχείο .htaccess;

Όχι. Σύμφωνα με το εγχειρίδιο της PHP, το php_admin_value δεν επιτρέπεται σε αρχεία .htaccess. Ανήκει στη διαμόρφωση διακομιστή του Apache ή στο VirtualHost, στο PHP-FPM στο αρχείο του pool.

Τι συμβαίνει όταν μια εφαρμογή θέλει να αλλάξει μια κλειδωμένη τιμή;

Η κλήση του ini_set() αποτυγχάνει και επιστρέφει false, η κλειδωμένη τιμή παραμένει. Οι καλά προγραμματισμένες εφαρμογές το διαχειρίζονται. Ελέγξτε παρ' όλα αυτά μετά τη μετάβαση το log σφαλμάτων και τις σημαντικότερες λειτουργίες.

Πρέπει να κάνω επανεκκίνηση μετά από αλλαγή στο pool;

Ναι. Το PHP-FPM διαβάζει τα αρχεία των pools κατά την εκκίνηση ή κατά την επαναφόρτωση της υπηρεσίας. Στον Apache με mod_php ισχύει το ίδιο για τη διαμόρφωση του διακομιστή. Χωρίς επανεκκίνηση εξακολουθεί να ισχύει η παλιά τιμή.

Μπορεί το disable_functions να επεκταθεί στο pool;

Ναι, με μια ιδιαιτερότητα: σύμφωνα με το εγχειρίδιο της PHP, το disable_functions στο pool FPM δεν αντικαθιστά τις τιμές από το php.ini, αλλά τις συμπληρώνει. Το pool μπορεί επομένως να αποκλείσει επιπλέον συναρτήσεις, αλλά δεν μπορεί να ελευθερώσει καμία.

Πηγές

Άμεση επικοινωνία

Κάθε ώρα μετράει. Γράψτε μας τώρα.

Περιγράψτε σύντομα το σύστημα, την έκδοση PHP και ό,τι παρατηρείτε. Θα επικοινωνήσουμε μαζί σας, θα διευκρινίσουμε την κατάσταση και θα εργαστούμε εξ αποστάσεως μέχρι το περιστατικό να κλείσει και να τεκμηριωθεί.

Άμεση βοήθεια