Trumpai: php_admin_value ir php_admin_flag nustato PHP nustatymus PHP-FPM baseine arba Apache konfigūracijoje taip, kad programos jų negalėtų pakeisti nei per ini_set(), nei per .htaccess. Būtent to php.net reikalauja PHP2Shell pereinamosioms priemonėms, pavyzdžiui, memory_limit=-1. Nustačius paslaugą reikia paleisti iš naujo, o reikšmę verta patikrinti žiniatinklio kontekste.
Kodėl „nustatyta“ nereiškia „užrakinta“
Per dienas po 2026 m. spalio 21 d. daugelis administratorių php.net pereinamąsias priemones įrašė į savo php.ini. Viena rekomendacijos detalė dažnai pasimetė: memory_limit=-1 turi būti nustatytas taip, kad programos negalėtų jo perrašyti. php.net tam aiškiai nurodo php_admin_value FPM baseine arba Apache konfigūracijoje.
Priežastis paprasta. Daugelis CMS, parduotuvių ir karkasų nustato savas reikšmes, pavyzdžiui, didesnę atminties ribą importams. Jei reikšmė yra tik php.ini, programa ją perrašo per kitą kreipinį. Tada apsaugos priemonė egzistuoja popieriuje, bet ne veikiančiame procese.
Tai liečia ne tik PHP2Shell. Kiekvienas sutvirtinimas, nuo išjungtų klaidų išvedimų iki įkėlimo ribų, yra tiek stiprus, kiek stiprus jo silpniausias lygmuo.
Kas apskritai gali keisti PHP nustatymus
PHP turi keturis keitimo režimus. Kiekvienas nustatymas turi vieną iš jų, ir jis lemia, kuriose vietose nustatymą galima nustatyti. Reikšmės paimtos iš PHP vadovo.
| Režimas | Kur reikšmę galima nustatyti | Pavyzdžiai |
|---|---|---|
INI_USER |
scenarijuje per ini_set() ir .user.ini |
kelios vykdymo reikšmės |
INI_PERDIR |
php.ini, .htaccess, httpd.conf, .user.ini |
post_max_size, session.upload_progress.enabled |
INI_SYSTEM |
tik php.ini arba httpd.conf |
file_uploads, disable_functions |
INI_ALL |
visur, taip pat per ini_set() |
memory_limit, display_errors, open_basedir |
Pavojingiausios yra INI_ALL reikšmės: jas galima pakeisti iš bet kurio scenarijaus. INI_PERDIR reikšmių per ini_set() pakeisti negalima, bet galima per .htaccess su mod_php arba .user.ini su PHP-FPM. Kas turi rašymo teises žiniatinklio šakniniame kataloge, taigi ir įterptas kodas, gali sukurti tokius failus.
php_admin_value FPM baseine ir Apache
PHP-FPM reikšmės yra baseino faile. PHP vadovas nurodo: su php_admin_value ir php_admin_flag nustatytų reikšmių negalima perrašyti per ini_set(). Įjungimo-išjungimo reikšmėms naudokite php_admin_flag, visoms kitoms php_admin_value.
; /etc/php/8.3/fpm/pool.d/seite1.conf (ištrauka)
[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/
Pasak php.net, memory_limit=-1 į konfigūraciją priklauso tik kartu su atminties riba per konteinerį ar cgroup. Kaip tai pavyksta su systemd, aprašyta straipsnyje Atminties ribų nustatymas su systemd ir cgroups.
Apache su mod_php direktyvos priklauso serverio konfigūracijai arba VirtualHost. Pasak PHP vadovo, .htaccess jos neleidžiamos, o kartą nustatytų nei .htaccess, nei ini_set() pakeisti negali.
<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>
Dvi smulkmenos iš vadovo: norėdami ištrinti anksčiau nustatytą reikšmę, kaip reikšmę naudokite none. O PHP konstantos, tokios kaip E_ALL, Apache konfigūracijoje neturi prasmės; error_reporting ten reikia nurodyti skaitinę reikšmę.
Kurias reikšmes užrakinti
Ne kiekvieną nustatymą reikia užrakinti. Prasminga tai daryti viskam, kas liečia saugumą arba tarnauja kaip pereinamoji priemonė:
- php.net PHP2Shell pereinamosios reikšmės:
memory_limit,post_max_size,upload_max_filesize,session.upload_progress.enabledir PHP 8.5fatal_error_backtraces. - Klaidų išvedimas ir registravimas:
display_errors,display_startup_errors,log_errors,error_log. - Prieiga prie failų ir izoliacija:
open_basedir,upload_tmp_dir,session.save_path. - Tinklo kreipiniai iš PHP:
allow_url_includeir, jei programa to nereikalauja,allow_url_fopen. - Užblokuotos funkcijos per
disable_functions, kurios baseine, pasak vadovo, papildo php.ini sąrašą, o ne jį pakeičia. Detales rasite gide disable_functions teisingas naudojimas.
Su session.upload_progress.enabled užrakinimas ypač svarbus, nes kitaip reikšmė galėtų būti vėl įjungta per .user.ini. Daugiau apie tai skyriuje session.upload_progress išjungimas: teisingai ir visam laikui.
Patikrinti, ar užraktas veikia
Po kiekvieno pakeitimo paslaugą paleiskite iš naujo ir patikrinkite reikšmę žiniatinklio kontekste. Trumpas, iš karto vėl ištrinamas patikros failas parodo, ar baseinas išlaiko reikšmę, net kai programa nori ją pakeisti:
<?php
// Patikros failas: padėti trumpam, vieną kartą iškviesti per domeną, iš karto ištrinti
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";
Tikimasi -1 ir „blockiert“ (užblokuota). Jei išvestis „MÖGLICH“ (įmanoma), reikšmė nenustatyta per php_admin_value arba paslauga dar nepaleista iš naujo. Patikrą pakartokite kiekvienam baseinui ir kiekvienai PHP versijai.
Užrakintas reikšmes laikykite centralizuotai, pavyzdžiui, baseino šablone ar konfigūracijos valdyme. Hostingo skydeliai kartais perrašo rankiniu būdu pakeistus baseino failus kitą kartą išsaugodami; ten reikšmės priklauso skydelio numatytiems laukams.
Kaip PHP apskritai tvarko savo konfigūracijos lygius, paaiškina php.ini paaiškinimas: sandara, lygiai ir pirmenybė. Visos pereinamosios priemonės pateiktos skyriuje Skubios priemonės, kai dar negalite pataisyti.
Išvada: tik užrakinta reikšmė iš tikrųjų nustatyta
php.net pereinamosios priemonės dėl PHP2Shell atkreipė dėmesį į skirtumą, kuris anksčiau dažnai būdavo nepastebimas: reikšmė php.ini daugeliui nustatymų yra tik pasiūlymas, o reikšmė php_admin_value yra nurodymas. Patogumo reikšmėms, tokioms kaip laiko zona, skirtumas nesvarbus. Saugumo nustatymams ir pereinamosioms priemonėms jis lemia, ar priemonė apskritai veikia einamuoju režimu.
Darbo kiekis nedidelis: saujelė eilučių kiekvienam baseinui ar VirtualHost, paleidimas iš naujo, trumpa patikra. Užrakintų reikšmių sąrašą laikykite mažą ir pagrįstą, kad kūrėjai suprastų, kodėl jų programa negali pakeisti reikšmės. Ir prižiūrėkite sąrašą savo šablonuose, kad naujos svetainės jį paveldėtų automatiškai.
Kaip PHP SOS padeda konkrečiai?
- Nuskaityti lygius: kiekvienai svetainei nustatome, kurios reikšmės iš php.ini, baseino, Apache,
.htaccessar.user.iniiš tikrųjų galioja. - Nustatyti užraktus: saugumui svarbias reikšmes ir PHP2Shell pereinamąsias priemones įrašome kaip
php_admin_valuearbaphp_admin_flagir iš naujo paleidžiame paslaugas. - Išbandyti programą: tikriname, ar programa su užrakintomis reikšmėmis veikia be klaidų, ir analizuojame klaidų žurnalą.
- Prižiūrėti šablonus: serverio sutvirtinimo rėmuose reikšmes perkeliame į baseinų šablonus ir dokumentaciją.
Dažni klausimai
Kuo skiriasi php_value ir php_admin_value?
Abu nustato PHP nustatymą. Reikšmes iš php_value programa vėliau gali vėl pakeisti, pavyzdžiui, per ini_set() ar .htaccess. Pasak PHP vadovo, reikšmės iš php_admin_value ir php_admin_flag užrakintos nuo ini_set(), o Apache atveju ir nuo .htaccess.
Ar php_admin_value galiu rašyti į .htaccess failą?
Ne. Pasak PHP vadovo, php_admin_value .htaccess failuose neleidžiamas. Jis priklauso Apache serverio konfigūracijai arba VirtualHost, o PHP-FPM atveju baseino failui.
Kas atsitinka, kai programa bando pakeisti užrakintą reikšmę?
ini_set() iškvietimas nepavyksta ir grąžina false, užrakinta reikšmė lieka. Gerai suprogramuotos programos su tuo susitvarko. Po perėjimo vis tiek patikrinkite klaidų žurnalą ir svarbiausias funkcijas.
Ar po pakeitimo baseine reikia paleisti iš naujo?
Taip. PHP-FPM baseino failus skaito paleidžiant arba iš naujo įkeliant paslaugą. Apache su mod_php tas pats galioja serverio konfigūracijai. Be paleidimo iš naujo toliau veikia sena reikšmė.
Ar disable_functions baseine galima išplėsti?
Taip, su ypatumu: pasak PHP vadovo, disable_functions FPM baseine neperrašo php.ini reikšmių, o jas papildo. Taigi baseinas gali užblokuoti daugiau funkcijų, bet nė vienos negali atblokuoti.