Trumpai: gyvoje svetainėje display_errors = Off priklauso php.ini kartu su display_startup_errors = Off, log_errors = On ir klaidų žurnalu už žiniatinklio šakninio katalogo ribų. Be to, CMS ir karkasai turi veikti produkciniu režimu, kitaip savų klaidų puslapių detales parodys jie. Užrakintos su php_admin_flag ir tikrinamos po kiekvieno atnaujinimo, klaidos lieka žurnale, o ne naršyklėje.
Ką išduoda vienas klaidos pranešimas
Įspėjimas puslapio viršuje, „Fatal error“ užuot užsakymo apžvalgos: tokie išvedimai atrodo nekenksmingi. Užpuolikui jie yra žemėlapis. Jie rodo pilnus failų kelius, duomenų bazių ir lentelių pavadinimus, naudojamas bibliotekas ir dažnai PHP versiją.
Būtent tokioje padėtyje kaip PHP2Shell, kai masiškai ieškoma pažeidžiamų serverių, serveris turėtų apie save atskleisti kuo mažiau. Tai neuždaro PHP interpretatoriaus spragos, bet apsunkina kiekvieną kitą žingsnį po įsilaužimo ir sunkina tikslines atakas prieš jūsų programą.
Be to, duomenų apsauga. Klaidų pranešimuose gali būti užklausų dalių, pavyzdžiui, el. pašto adresų iš formų. Kas pasirodo lankytojo naršyklėje, nebėra jūsų kontrolėje.
Numatytosios reikšmės nėra skirtos produkcijai
Daugelis mano, kad PHP klaidas paslepia pats. PHP vadovas sako kitaip: įtaisytoji display_errors numatytoji reikšmė yra 1, o display_startup_errors nuo PHP 8.0 taip pat numatytai įjungtas. Tik pateiktas šablonas php.ini-production abu nustato į Off. Vadovas display_errors aiškiai vadina kūrimo funkcija, kurios sistemose internete niekada nereikėtų naudoti.
Ar jūsų serveris naudoja produkcijos šabloną, nėra savaime suprantama. Konteinerių atvaizdai kartais paleidžiami visai be php.ini, hostingo skydeliai nustato savas reikšmes, o po perkėlimo mėgstama nukopijuoti kūrimo šabloną.
display_errors off: nustatymų apžvalga
Šios reikšmės prasmingos produkciniams serveriams. Konstantos, tokios kaip E_ALL, veikia tik php.ini; Apache konfigūracijoje, pasak PHP vadovo, jos neturi prasmės ir turi būti nurodytos skaičiumi.
| Nustatymas | Produkcija | Paskirtis |
|---|---|---|
display_errors |
Off |
jokių klaidų naršyklėje |
display_startup_errors |
Off |
jokių klaidų išvestyje PHP paleidimo metu |
log_errors |
On |
klaidas rašyti į žurnalą |
error_log |
kelias už žiniatinklio šakninio katalogo ribų | atskiras žurnalo failas kiekvienai svetainei ar baseinui |
error_reporting |
E_ALL |
registruoti visas klaidas, nerodyti |
html_errors |
Off |
paprastas tekstas vietoj HTML žurnaluose |
zend.exception_ignore_args |
On |
jokių funkcijų argumentų steko pėdsakuose |
fatal_error_backtraces |
0 iki atnaujinimo (tik PHP 8.5) |
pereinamoji priemonė pasak php.net |
zend.exception_ignore_args ypač vertingas. Be šio nustatymo steko pėdsakuose žurnaluose ir klaidų puslapiuose gali būti funkcijų iškvietimų argumentų, taigi ir slaptažodžių ar prieigos raktų (token), kurie kaip tik buvo apdorojami.
; žiniatinklio SAPI php.ini
display_errors = Off
display_startup_errors = Off
log_errors = On
error_log = /var/log/php/website-fehler.log
error_reporting = E_ALL
html_errors = Off
zend.exception_ignore_args = On
; tik PHP 8.5, pereinamoji priemonė iki atnaujinimo į 8.5.12:
; fatal_error_backtraces = 0
FPM baseine svarbiausias reikšmes papildomai užrakinkite, kad jokia programa jų vėl neįjungtų per ini_set():
; pvz., /etc/php/8.3/fpm/pool.d/seite1.conf
php_admin_flag[display_errors] = off
php_admin_flag[display_startup_errors] = off
php_admin_flag[log_errors] = on
php_admin_value[error_log] = /var/log/php/seite1-fehler.log
Po to iš naujo paleiskite atitinkamą PHP paslaugą. Kaip tiksliai veikia užrakinimas, paaiškina straipsnis php_admin_value: nustatymų užrakinimas nuo perrašymo. Pilną bazinę konfigūraciją rasite skyriuje Saugus php.ini konfigūravimas.
Antras jungiklis: programos derinimo režimas
PHP yra tik pusė reikalo. Šiuolaikiniai karkasai klaidas pagauna patys ir rodo savus, dažnai labai išsamius klaidų puslapius. Derinimo režimu juose yra šaltinio kodo ištraukų, konfigūracijos reikšmių ir kartais aplinkos kintamųjų. Šie puslapiai pasirodo net tada, kai display_errors PHP išjungtas.
Todėl kiekvienai programai patikrinkite jos pačios jungiklį. WordPress tai WP_DEBUG ir WP_DEBUG_DISPLAY faile wp-config.php, Laravel ir Symfony APP_DEBUG ir aplinka faile .env, kitose sistemose produkcinis režimas pagal gamintojo dokumentaciją. Gyvoje sistemoje derinimo režimas turi būti išjungtas visam laikui, net „tik trumpam išbandyti“ yra rizika.
Kaip programoje klaidos tvarkomos švariai, užuot jas slopinus, aprašo Klaidos ir išimtys PHP.
Kaip rasti klaidų išvedimus prieš kitiems juos radus
Vieno karto nustatyti nepakanka. Klaidų išvedimai sugrįžta po atnaujinimų, perkėlimų ar skydelio pakeitimų. Padeda trumpa patikros eiga:
- Patikrinti veiksmingas reikšmes žiniatinklio kontekste, ne tik komandinėje eilutėje, pavyzdžiui, trumpam padėtu, po to iš karto ištrintu patikros failu.
- Patikrinti kiekvienos programos derinimo režimą jos konfigūracijos faile.
- Pateiktuose puslapiuose ieškoti tipinių klaidų tekstų, kaip parodyta kodo bloke žemiau.
- Paieškos sistemoje su
site:užklausa jūsų domene ieškoti tokių terminų kaip „Fatal error“ ar „Warning“. - Patikrinti, ar klaidų žurnalas rašomas ir ar jis nėra žiniatinklio šakniniame kataloge.
# Pateiktuose puslapiuose ieškoti PHP klaidų tekstų (tik savo domenai)
for url in https://www.example.de/ https://www.example.de/kontakt/; do
curl -s "$url" | grep -E -o "(Fatal error|Warning|Notice|Deprecated|Stack trace)[^<]{0,80}" | head -3
done
# Ar klaidų žurnalas rašomas?
ls -l /var/log/php/
Klaidų slėpimas nepakeičia jų taisymo. Žurnalas, pilnas įspėjimų, yra užuomina apie priežiūros poreikį, o po įsilaužimo dažnai svarbus pėdsakas. Ką čia registruoti ir ko ne, aprašo Saugus registravimas: klaidų žurnalas be duomenų nutekėjimo.
Išvada: tyliai naršyklėje, šnekiai žurnale
Produkcinių serverių taisyklė paprasta: klaidos priklauso žurnalui, o ne svetainei. Praktikoje ji strigsta dėl numatytųjų reikšmių, kurios nėra skirtos produkcijai, dėl programų derinimo jungiklių ir dėl konfigūracijų, kurios po atnaujinimų ar perkėlimų grįžta atgal.
Kas išjungia display_errors ir display_startup_errors, užrakina reikšmes baseine, kontroliuoja programos derinimo režimą ir reguliariai tikrina rezultatą, uždaro vieną dažniausių nereikalingo informacijos atskleidimo šaltinių. Darbo kiekis mažas, poveikis išlieka, kol patikra lieka kiekvieno atnaujinimo dalimi.
Vieno dalyko neturėtų pamiršti: klaidų žurnalas nėra šiukšlių dėžė. Kas jį reguliariai skaito, atpažįsta klaidingus atnaujinimus, pasenusias funkcijas ir kartais net pirmuosius atakos pėdsakus gerokai anksčiau, nei ką nors pastebi klientai.
Kaip PHP SOS padeda konkrečiai?
- Patikrinti: nuskaitome veiksmingus klaidų nustatymus kiekvienai svetainei ir baseinui ir pateiktuose puslapiuose ieškome klaidų išvedimų.
- Perjungti: PHP ir programos nustatymus nustatome produkciniam veikimui ir užrakiname nuo perrašymo.
- Įrengti žurnalus: klaidų žurnalai yra už žiniatinklio šakninio katalogo ribų, rotuojami ir prieinami jūsų kūrėjams.
- Išlaikyti ilgam: saugumo priežiūros sutartyje nustatymus iš naujo tikriname po kiekvieno atnaujinimo.
Dažni klausimai
Ar display_errors PHP nėra išjungtas ir taip?
Ne automatiškai. Pasak PHP vadovo, įtaisytoji display_errors numatytoji reikšmė yra 1. Tik pateiktas šablonas php.ini-production nustato Off. Ar jūsų serveris naudoja šį šabloną, priklauso nuo distribucijos, skydelio ar konteinerio atvaizdo ir turėtų būti patikrinta.
Ar pakanka display_errors = Off, jei WordPress ar Laravel veikia derinimo režimu?
Ne. Daugelis CMS ir karkasų turi savus klaidų puslapius, kurie nepriklausomai nuo PHP gali rodyti detales. Todėl išjunkite ir programos derinimo režimą, pavyzdžiui, WP_DEBUG_DISPLAY WordPress arba APP_DEBUG Laravel ir Symfony.
Kur keliauja klaidos, kai jos nebeberodomos?
Su log_errors = On PHP jas rašo į failą, kurį nurodo error_log, arba į atitinkamo veikimo režimo žurnalą, pavyzdžiui, Apache ar PHP-FPM klaidų žurnalą. Failas turėtų būti už žiniatinklio šakninio katalogo ribų ir reguliariai rotuojamas.
Ką fatal_error_backtraces turi bendro su PHP2Shell?
Nustatymas egzistuoja nuo PHP 8.5 ir numatytai aktyvus. php.net įvardija fatal_error_backtraces=0 su vėlesniu paleidimu iš naujo kaip vieną iš pereinamųjų priemonių PHP 8.5, kol dar laukiama atnaujinimo į 8.5.12. Jis nepakeičia atnaujinimo.