Lyhyesti: Live-sivustolla display_errors = Off kuuluu tiedostoon php.ini, yhdessä asetusten display_startup_errors = Off, log_errors = On ja verkkojuuren ulkopuolella olevan virhelokin kanssa. Lisäksi CMS:ien ja kehysten on pyörittävä tuotantotilassa, muuten niiden omat virhesivut näyttävät yksityiskohdat. Kun asetus on lukittu komennolla php_admin_flag ja tarkistettu jokaisen päivityksen jälkeen, virheet pysyvät lokissa selaimen sijaan.
Mitä yksi ainoa virheilmoitus paljastaa
Varoitus sivun yläreunassa, ”Fatal error” tilausyhteenvedon sijaan: tällaiset tulosteet näyttävät harmittomilta. Hyökkääjälle ne ovat kartta. Ne näyttävät täydelliset tiedostopolut, tietokantojen ja taulujen nimet, käytetyt kirjastot ja usein PHP-version.
Juuri PHP2Shellin kaltaisissa tilanteissa, joissa haavoittuvia palvelimia etsitään massoittain, palvelimen pitäisi paljastaa itsestään mahdollisimman vähän. Se ei sulje aukkoa PHP-tulkissa, mutta vaikeuttaa jokaista murron jälkeistä askelta ja tekee kohdennetuista hyökkäyksistä sovellustanne vastaan työläämpiä.
Lisäksi tulee tietosuoja. Virheilmoitukset voivat sisältää osia pyynnöistä, esimerkiksi lomakkeiden sähköpostiosoitteita. Se, mikä ilmestyy kävijän selaimeen, ei ole enää teidän hallinnassanne.
Oletusarvot eivät ole tarkoitettu tuotantoon
Moni olettaa, että PHP piilottaa virheet itsestään. PHP-käsikirja sanoo muuta: display_errors-asetuksen sisäänrakennettu oletusarvo on 1, ja display_startup_errors on PHP 8.0:sta lähtien myös oletuksena päällä. Vasta mukana tuleva mallipohja php.ini-production asettaa molemmat arvoon Off. Käsikirja kutsuu display_errors-asetusta nimenomaisesti kehitystoiminnoksi, jota ei pidä koskaan käyttää internetissä olevilla järjestelmillä.
Se, käyttääkö palvelimenne tuotantomallipohjaa, ei ole itsestään selvää. Konttikuvat käynnistyvät osin täysin ilman php.ini-tiedostoa, hosting-paneelit asettavat omia arvojaan, ja muuton jälkeen kopioidaan mielellään kehitysmallipohja.
display_errors off: asetukset yhdellä silmäyksellä
Seuraavat arvot ovat järkeviä tuotantopalvelimille. Vakiot kuten E_ALL toimivat vain tiedostossa php.ini; Apachen asetuksissa niillä ei PHP-käsikirjan mukaan ole merkitystä, ja ne on annettava lukuna.
| Asetus | Tuotanto | Tarkoitus |
|---|---|---|
display_errors |
Off |
ei virheitä selaimessa |
display_startup_errors |
Off |
ei PHP:n käynnistysvirheitä tulosteessa |
log_errors |
On |
kirjoita virheet lokiin |
error_log |
polku verkkojuuren ulkopuolella | oma lokitiedosto sivustoa tai poolia kohden |
error_reporting |
E_ALL |
kirjaa kaikki virheet, älä näytä |
html_errors |
Off |
pelkkä teksti HTML:n sijaan lokeissa |
zend.exception_ignore_args |
On |
ei funktioargumentteja pinojäljissä |
fatal_error_backtraces |
0 päivitykseen asti (vain PHP 8.5) |
siirtymäajan toimenpide php.net:n mukaan |
zend.exception_ignore_args on erityisen arvokas. Ilman tätä asetusta pinojäljet lokeissa ja virhesivuilla voivat sisältää funktiokutsujen argumentit, siis myös salasanat tai tunnisteet, joita juuri käsiteltiin.
; verkko-SAPI:n 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
; vain PHP 8.5, siirtymäajan toimenpide päivitykseen 8.5.12 asti:
; fatal_error_backtraces = 0
FPM-poolissa lukitsette tärkeimmät arvot lisäksi, jotta mikään sovellus ei kytke niitä takaisin päälle funktiolla ini_set():
; esim. /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
Käynnistäkää sen jälkeen kyseinen PHP-palvelu uudelleen. Miten lukitseminen tarkalleen toimii, selittää kirjoitus php_admin_value: asetusten lukitseminen ylikirjoitukselta. Täydellisen perusasetuksen löydätte kohdasta php.ini turvalliseksi.
Toinen kytkin: sovelluksen debug-tila
PHP on vain puolet työstä. Nykyaikaiset kehykset sieppaavat virheet itse ja näyttävät omia, usein hyvin yksityiskohtaisia virhesivuja. Debug-tilassa ne sisältävät lähdekoodiotteita, asetusarvoja ja toisinaan ympäristömuuttujia. Nämä sivut ilmestyvät silloinkin, kun display_errors on PHP:ssä pois päältä.
Tarkistakaa siksi jokaisen sovelluksen oma kytkin. WordPressissä ne ovat WP_DEBUG ja WP_DEBUG_DISPLAY tiedostossa wp-config.php, Laravelissa ja Symfonyssa APP_DEBUG ja ympäristö .env-tiedostossa, muissa järjestelmissä tuotantotila valmistajan dokumentaation mukaan. Live-järjestelmässä debug-tilan kuuluu olla pysyvästi pois, ja myös ”vain hetkeksi testaamista varten” on riski.
Miten virheet käsitellään sovelluksessa siististi niitä tukahduttamatta, kuvaa Virheet ja poikkeukset PHP:ssä.
Näin löydätte virhetulosteet ennen kuin muut tekevät sen
Kertaasetus ei riitä. Virhetulosteet palaavat päivitysten, muuttojen tai paneelimuutosten jälkeen. Lyhyt tarkistuskulku auttaa:
- Tarkistakaa voimassa olevat arvot verkkokontekstissa, ei vain komentorivillä, esimerkiksi hetkeksi asetetulla ja heti poistetulla tarkistustiedostolla.
- Tarkistakaa jokaisen sovelluksen debug-tila sen asetustiedostossa.
- Käykää tarjoillut sivut läpi tyypillisten virhetekstien varalta, kuten alla olevassa koodilohkossa.
- Hakekaa hakukoneesta
site:-kyselyllä verkkotunnuksestanne termeillä kuten ”Fatal error” tai ”Warning”. - Tarkistakaa, kirjoitetaanko virhelokiin ja ettei se ole verkkojuuressa.
# Käy tarjoillut sivut läpi PHP-virhetekstien varalta (vain omat verkkotunnukset)
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
# Kirjoitetaanko virhelokiin?
ls -l /var/log/php/
Virheiden piilottaminen ei korvaa niiden korjaamista. Varoituksia täynnä oleva loki on merkki huoltotarpeesta, ja murron jälkeen se on usein tärkeä jälki. Mitä siinä kirjataan ja mitä ei, kuvaa Turvallinen lokitus: virheiden kirjaus ilman tietovuotoa.
Yhteenveto: hiljaa selaimessa, puheliaana lokissa
Sääntö tuotantopalvelimille on yksinkertainen: virheiden paikka on loki, ei verkkosivusto. Käytännössä se kompastuu oletusarvoihin, jotka eivät ole tarkoitettu tuotantoon, sovellusten debug-kytkimiin ja asetuksiin, jotka putoavat takaisin päivitysten tai muuttojen jälkeen.
Joka kytkee display_errors- ja display_startup_errors-asetukset pois, lukitsee arvot poolissa, tarkistaa sovelluksen debug-tilan ja kontrolloi tuloksen säännöllisesti, sulkee yhden yleisimmistä tarpeettoman tietojen paljastumisen lähteistä. Vaiva on pieni, vaikutus kestää niin kauan kuin tarkistus pysyy osana jokaista päivitystä.
Yksi seikka ei saisi hukkua: virheloki ei ole roskakori. Joka lukee sitä säännöllisesti, tunnistaa virheelliset päivitykset, vanhentuneet funktiot ja toisinaan myös hyökkäyksen ensimmäiset jäljet kauan ennen kuin asiakkaat huomaavat mitään.
Miten PHP SOS auttaa konkreettisesti?
- Tarkistus: Luemme voimassa olevat virheasetukset sivustoa ja poolia kohden ja käymme tarjoillut sivut läpi virhetulosteiden varalta.
- Muutos: Asetamme PHP:n ja sovellusten asetukset tuotantokäyttöön ja lukitsemme ne ylikirjoitukselta.
- Lokien perustaminen: Virhelokit ovat verkkojuuren ulkopuolella, niitä kierrätetään ja ne ovat kehittäjienne käytettävissä.
- Pysyvyys: Tietoturvahuoltosopimuksessa tarkistamme asetukset uudelleen jokaisen päivityksen jälkeen.
Usein kysytyt kysymykset
Eikö display_errors ole PHP:ssä muutenkin pois päältä?
Ei automaattisesti. PHP-käsikirjan mukaan display_errors:n sisäänrakennettu oletusarvo on 1. Vasta mukana tuleva mallipohja php.ini-production asettaa arvon Off. Käyttääkö palvelimenne tätä mallipohjaa, riippuu jakelusta, paneelista tai konttikuvasta, ja se pitäisi tarkistaa.
Riittääkö display_errors = Off, jos WordPress tai Laravel pyörii debug-tilassa?
Ei. Monet CMS:t ja kehykset tuovat mukanaan omat virhesivunsa, jotka voivat näyttää yksityiskohtia PHP:stä riippumatta. Kytkekää siksi pois myös sovelluksen debug-tila, esimerkiksi WP_DEBUG_DISPLAY WordPressissä tai APP_DEBUG Laravelissa ja Symfonyssa.
Minne virheet menevät, kun niitä ei enää näytetä?
Asetuksella log_errors = On PHP kirjoittaa ne tiedostoon, jonka error_log nimeää, tai kyseisen käyttötavan lokiin, esimerkiksi Apachen tai PHP-FPM:n virhelokiin. Tiedoston pitäisi olla verkkojuuren ulkopuolella ja sitä pitäisi kierrättää säännöllisesti.
Mitä fatal_error_backtraces liittyy PHP2Shelliin?
Asetus on olemassa PHP 8.5:stä lähtien ja on oletuksena aktiivinen. php.net nimeää fatal_error_backtraces=0 ja sitä seuraavan uudelleenkäynnistyksen yhdeksi siirtymäajan toimenpiteeksi PHP 8.5:lle, kunnes päivitys versioon 8.5.12 on vielä tekemättä. Se ei korvaa päivitystä.