Na kratko: php_admin_value in php_admin_flag nastavitve PHP v poolu PHP-FPM ali v konfiguraciji Apache nastavita tako, da jih aplikacije ne morejo spremeniti ne z ini_set() ne prek .htaccess. php.net prav to zahteva za prehodne ukrepe PHP2Shell, na primer za memory_limit=-1. Po nastavitvi je treba storitev znova zagnati, vrednost pa preveriti v spletnem kontekstu.
Zakaj »nastavljeno« ne pomeni »zaklenjeno«
V dneh po 21. oktobru 2026 so številni skrbniki prehodne ukrepe php.net zapisali v svoj php.ini. Pri tem je pogosto utonila ena podrobnost priporočila: memory_limit=-1 naj bo nastavljen tako, da ga aplikacije ne morejo prepisati. php.net za to izrecno navaja php_admin_value v poolu FPM ali v konfiguraciji Apache.
Razlog je preprost. Številni CMS, trgovine in ogrodja nastavljajo svoje vrednosti, na primer višjo pomnilniško mejo za uvoze. Če je vrednost samo v php.ini, jo aplikacija ob naslednjem klicu prepiše. Zaščitni ukrep potem obstaja na papirju, ne pa v tekočem procesu.
To ne zadeva samo PHP2Shell. Vsako utrjevanje, od izklopljenih izpisov napak do meja nalaganja, je tako močno kot njegova najšibkejša raven.
Kdo sploh sme spreminjati nastavitve PHP
PHP pozna štiri načine spreminjanja. Vsaka nastavitev ima enega od njih, ta pa določa, na katerih mestih jo je mogoče nastaviti. Pomeni izvirajo iz priročnika PHP.
| Način | Kje je mogoče vrednost nastaviti | Primeri |
|---|---|---|
INI_USER |
v skriptu z ini_set() in v .user.ini |
nekaj izvajalnih vrednosti |
INI_PERDIR |
php.ini, .htaccess, httpd.conf, .user.ini |
post_max_size, session.upload_progress.enabled |
INI_SYSTEM |
samo php.ini ali httpd.conf |
file_uploads, disable_functions |
INI_ALL |
povsod, tudi z ini_set() |
memory_limit, display_errors, open_basedir |
Nevarne so predvsem vrednosti INI_ALL: spremeniti jih je mogoče iz vsakega skripta. Vrednosti INI_PERDIR sicer ni mogoče spremeniti z ini_set(), lahko pa prek .htaccess pri mod_php ali .user.ini pri PHP-FPM. Kdor ima pravice pisanja v spletnem korenu, torej tudi vnesena koda, lahko takšne datoteke ustvari.
php_admin_value v poolu FPM in v Apache
Pri PHP-FPM so vrednosti v datoteki poola. Priročnik PHP navaja: vrednosti, nastavljenih s php_admin_value in php_admin_flag, ni mogoče prepisati z ini_set(). Za vrednosti vklop/izklop vzemite php_admin_flag, za vse druge php_admin_value.
; /etc/php/8.3/fpm/pool.d/seite1.conf (izsek)
[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 po php.net sodi v konfiguracijo samo skupaj z mejo pomnilnika prek vsebnika ali cgroup. Kako to uspe s systemd, piše v prispevku Nastavitev pomnilniških mej s systemd in cgroups.
Pri Apache z mod_php direktive sodijo v konfiguracijo strežnika ali VirtualHost. Po priročniku PHP v .htaccess niso dovoljene in ko so enkrat nastavljene, jih ne more spremeniti ne .htaccess ne 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>
Dve podrobnosti iz priročnika: za izbris prej nastavljene vrednosti kot vrednost uporabite none. In konstante PHP, kot je E_ALL, v konfiguraciji Apache nimajo pomena; za error_reporting morate tam navesti številsko vrednost.
Katere vrednosti zakleniti
Vsaka nastavitev ne mora biti zaklenjena. Smiselno je to za vse, kar zadeva varnost ali služi kot prehodni ukrep:
- Prehodne vrednosti PHP2Shell iz php.net:
memory_limit,post_max_size,upload_max_filesize,session.upload_progress.enabledin na PHP 8.5fatal_error_backtraces. - Izpis napak in beleženje:
display_errors,display_startup_errors,log_errors,error_log. - Dostop do datotek in izolacija:
open_basedir,upload_tmp_dir,session.save_path. - Omrežni dostopi iz PHP:
allow_url_includein, če jo aplikacija ne potrebuje,allow_url_fopen. - Zaklenjene funkcije prek
disable_functions, ki v poolu po priročniku seznam iz php.ini dopolnijo, ne pa nadomestijo. Podrobnosti v vodniku Pravilna uporaba disable_functions.
Pri session.upload_progress.enabled je zaklepanje še posebej pomembno, ker bi se vrednost sicer lahko znova vklopila prek .user.ini. Več o tem pod Izklop session.upload_progress: pravilno in trajno.
Preverjanje, ali zaklep deluje
Po vsaki spremembi storitev znova zaženite in vrednost preverite v spletnem kontekstu. Kratka, takoj izbrisana preverjalna datoteka pokaže, ali pool vrednost drži, tudi če jo aplikacija želi spremeniti:
<?php
// Preverjalna datoteka: kratko naložiti, enkrat odpreti prek domene, takoj izbrisati
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";
Pričakovana sta -1 in »blockiert«. Če je izpis »MÖGLICH«, vrednost ni nastavljena prek php_admin_value ali pa storitev še ni bila znova zagnana. Preverjanje ponovite za vsak pool in vsako različico PHP.
Zaklenjene vrednosti zabeležite centralno, na primer v predlogi poola ali v upravljanju konfiguracije. Nadzorne plošče gostovanja ročno spremenjene datoteke poolov ob naslednjem shranjevanju deloma prepišejo; tam vrednosti sodijo v polja, ki jih nadzorna plošča predvideva.
Kako PHP svoje konfiguracijske ravni ureja v celoti, pojasnjuje Pojasnilo datoteke php.ini: zgradba, ravni in prednost. Popolni prehodni ukrepi so pod Takojšnji ukrepi, če popravka še ne morete namestiti.
Sklep: šele zaklenjeno je res nastavljeno
Prehodni ukrepi php.net za PHP2Shell so v zavest prinesli razlikovanje, ki je bilo prej pogosto spregledano: vrednost v php.ini je pri številnih nastavitvah samo predlog, vrednost v php_admin_value pa zahteva. Pri udobnih vrednostih, kot je časovni pas, razlika ni pomembna. Pri varnostnih nastavitvah in prehodnih ukrepih odloča o tem, ali ukrep v tekočem delovanju sploh deluje.
Napor je obvladljiv: peščica vrstic na pool ali VirtualHost, en ponovni zagon, kratko preverjanje. Seznam zaklenjenih vrednosti naj ostane majhen in utemeljen, da razvijalci razumejo, zakaj njihova aplikacija vrednosti ne sme spremeniti. In seznam vzdržujte v predlogah, da ga nove spletne strani podedujejo samodejno.
Kako PHP SOS pomaga konkretno?
- Branje ravni: za vsako spletno stran ugotovimo, katere vrednosti iz php.ini, poola, Apache,
.htaccessali.user.inidejansko veljajo. - Nastavitev zaklepov: varnostno pomembne vrednosti in prehodne ukrepe PHP2Shell vnesemo kot
php_admin_valueoziromaphp_admin_flagin storitve znova zaženemo. - Preizkus aplikacije: preverimo, ali aplikacija z zaklenjenimi vrednostmi teče brez napak, in ovrednotimo dnevnik napak.
- Vzdrževanje predlog: v okviru utrjevanja strežnikov vrednosti prevzamemo v predloge poolov in dokumentacijo.
Pogosta vprašanja
Kakšna je razlika med php_value in php_admin_value?
Obe nastavita nastavitev PHP. Vrednosti iz php_value lahko aplikacija pozneje spet spremeni, na primer z ini_set() ali prek .htaccess. Vrednosti iz php_admin_value in php_admin_flag so po priročniku PHP zaklenjene za ini_set(), pri Apache tudi za .htaccess.
Ali lahko php_admin_value zapišem v datoteko .htaccess?
Ne. Po priročniku PHP php_admin_value v datotekah .htaccess ni dovoljen. Sodi v konfiguracijo strežnika Apache ali VirtualHost, pri PHP-FPM v datoteko poola.
Kaj se zgodi, če aplikacija poskuša spremeniti zaklenjeno vrednost?
Klic ini_set() spodleti in vrne false, zaklenjena vrednost ostane. Dobro programirane aplikacije se s tem spopadejo. Po prehodu vseeno preverite dnevnik napak in najpomembnejše funkcije.
Ali moram po spremembi v poolu znova zagnati?
Da. PHP-FPM datoteke poolov prebere ob zagonu ali ob ponovnem nalaganju storitve. Pri Apache z mod_php enako velja za konfiguracijo strežnika. Brez ponovnega zagona stara vrednost teče naprej.
Ali je mogoče disable_functions v poolu razširiti?
Da, s posebnostjo: po priročniku PHP disable_functions v poolu FPM vrednosti iz php.ini ne prepiše, ampak jih dopolni. Pool lahko torej zaklene dodatne funkcije, ne more pa nobene sprostiti.