Trenutno stanje: PHP2Shell. Dve kritični ranljivosti PHP (CVSS 9,2) omogočata izvedbo škodljive kode brez prijave. Popravki od 21. 10. 2026.Kaj je zdaj treba storiti →

Napake in izjeme v PHP

PHP pozna klasična sporočila o napakah in izjeme. Ta stran razlaga hierarhijo Throwable, čisto obravnavo napak, varne nastavitve za produkcijo in ukrep PHP2Shell za fatal_error_backtraces.

Stanje 5 min branjaZnanje o PHP

Na kratko: PHP težave sporoča na dva načina: kot klasične napake, na primer opozorila in namige, ki jih nadzira error_reporting, in kot izjeme, ki jih je mogoče ujeti z try in catch. Od PHP 7 tudi številne notranje napake sprožijo objekt razreda Error; skupaj z Exception implementira vmesnik Throwable. V produkciji velja: napake beležiti, jih nikoli ne prikazovati v brskalniku. Na PHP 8.5 med prehodne ukrepe zaradi PHP2Shell dodatno sodi fatal_error_backtraces=0.

Dva sveta: klasične napake in izjeme

PHP izvira iz časa, ko so se napake izpisovale predvsem kot sporočila: namigi (E_NOTICE), opozorila (E_WARNING), zastarele funkcije (E_DEPRECATED) in smrtne napake (E_ERROR). Številna od teh sporočil skripti dovolijo, da teče naprej, pogosto z napačnimi ali praznimi podatki.

Izjeme delujejo drugače. Prekinejo običajni potek in skočijo na naslednji ustrezni blok catch. Če ga ni, se skripta konča. Za odločevalce je razlika pomembna: tiho opozorilo lahko povzroči, da se naročilo shrani nepopolno, ne da bi kdo opazil. Izjema težavo naredi vidno in obravnavno.

Premalo cenjena korist klasičnih sporočil so namigi tipa E_DEPRECATED. Napovedujejo, da bo neko jezikovno sredstvo v prihodnji različici PHP izpadlo. Kdor jih zbira v dnevniku in redno ovrednoti, pred nadgradnjo ve, katera mesta je treba prilagoditi, in pri nujni varnostni vrzeli ni treba šele dolgo testirati.

Hierarhija Throwable

Vse, kar je mogoče vreči z throw in ujeti s catch, implementira Throwable. Pod njim sta dve veji:

Razred Namen Primeri podrazredov
Exception pričakovane napake aplikacije in razširitev ErrorException, PDOException, lastni razredi
Error notranje napake PHP TypeError, ValueError, ArgumentCountError, ArithmeticError, DivisionByZeroError, UnhandledMatchError

Lastni razredi napak izhajajo iz Exception, ne iz Error. Od PHP 8.0 večina notranjih funkcij pri neveljavnih parametrih sproži TypeError ali ValueError, namesto da bi samo izpisala opozorilo. strlen([]) je en tak primer.

try, catch in finally v praksi

<?php
declare(strict_types=1);

final class ZahlungFehlgeschlagen extends RuntimeException {}

function bezahlen(Bestellung $b, Zahlungsdienst $dienst, LoggerInterface $log): bool
{
    try {
        $dienst->belasten($b->betrag(), $b->referenz());
        return true;
    } catch (ZahlungFehlgeschlagen $e) {
        $log->warning('Zahlung abgelehnt', ['bestellung' => $b->id(), 'exception' => $e]);
        return false;
    } catch (TimeoutException | VerbindungsFehler) {
        // od PHP 8.0 je spremenljivka v bloku catch neobvezna
        $log->error('Zahlungsdienst nicht erreichbar', ['bestellung' => $b->id()]);
        return false;
    } finally {
        $dienst->verbindungSchliessen();
    }
}

Več razredov je mogoče z | združiti v enem bloku catch. Blok finally se izvede vedno, ne glede na to, ali je prišlo do napake. Od PHP 8.0 je throw tudi izraz in lahko stoji na primer za ??: $id = $_GET['id'] ?? throw new InvalidArgumentException('id fehlt');.

Globalni handlerji: set_error_handler in set_exception_handler

Dve funkciji ujameta to, kar bi sicer ušlo. set_exception_handler() registrira funkcijo za neujete Throwable. Po priročniku se skripta konča, ko je funkcija poklicana; primerna je torej za beleženje in nevtralno stran z napako, ne za nadaljnje delo.

Obnesel se je handler, ki popolno napako z uro in naključno oznako zapiše v dnevnik, obiskovalcu pa pokaže samo nevtralno stran s to oznako. Podpora lahko primer nato najde v dnevniku, ne da bi notranje podrobnosti prišle navzven.

set_error_handler() ujame klasične napake. Priročnik pokaže, kako jih pretvoriti v ErrorException, da se opozorila obravnavajo kot izjeme:

<?php
set_error_handler(function (int $nr, string $text, string $datei, int $zeile): bool {
    if (!(error_reporting() & $nr)) {
        return false; // izključeno z error_reporting
    }
    if ($nr === E_DEPRECATED || $nr === E_USER_DEPRECATED) {
        return false; // namigov na zastarelo ne stopnjevati
    }
    throw new ErrorException($text, 0, $nr, $datei, $zeile);
});

Smrtnih napak, kot je prekoračitev pomnilnika, na ta način ni mogoče ujeti. Kaj se ob prekoračitvi dogaja v ozadju, razlaga stran memory_limit in Out-of-Memory.

Konfiguracija izpisa napak in beleženja

Najpomembnejše nastavitve s privzetimi vrednostmi po priročniku:

Nastavitev Privzeto Priporočilo za produkcijo
error_reporting E_ALL od PHP 8.0.0 E_ALL
display_errors 1 Off
display_startup_errors 1 od PHP 8.0.0 Off
log_errors 0 On
error_log prazno (dnevnik spletnega strežnika oz. SAPI) lastna datoteka zunaj korena spleta (webroot)
fatal_error_backtraces 1, novo v PHP 8.5.0 začasno 0 (PHP2Shell)

Od PHP 8.2.0 error_log_mode določa pravice dostopa do datoteke dnevnika, privzeto 0644. Če dnevniki vsebujejo osebne podatke ali poti, je smiselna strožja vrednost, da jih drugi uporabniki na strežniku ne morejo brati. Z ignore_repeated_errors je mogoče enaka sporočila iz iste datoteke in vrstice strniti, da zanka napak dnevnika ne preplavi.

Priložena php.ini-production display_errors že nastavi na Off. Po priročniku ini_set('display_errors', ...) med izvajanjem ne vpliva na smrtne napake, sintaksne napake pa nastopijo, še preden se ini_set() sploh izvede. Te vrednosti zato sodijo v konfiguracijo strežnika. Ozadje je v prispevku Izklop izpisa napak v produkciji; kako voditi dnevnike brez uhajanja podatkov, pa v prispevku Varno beleženje.

Obravnava napak in PHP2Shell

Za PHP 8.5 php.net kot enega od prehodnih ukrepov proti PHP2Shell navaja nastavitev fatal_error_backtraces=0 in nato ponovni zagon PHP. Drugi ukrepi zadevajo memory_limit, post_max_size in session.upload_progress.enabled. Noben od njih ne nadomesti posodobitve na PHP 8.5.12, 8.4.27, 8.3.36 ali 8.2.35.

; samo PHP 8.5, v php.ini ali poolu FPM, nato znova zaženite vse workerje
fatal_error_backtraces = 0

Dnevniki napak so po PHP2Shell poleg tega pomembno dokazno gradivo. Če se od 20. 10. 2026 kopičijo napake pomnilnika ali prekinjeni workerji, to lahko kaže na poskuse napadov, lahko pa ima tudi neškodljive vzroke. Dnevnike shranite in jih ovrednotite skupaj z dnevniki dostopov, kot je opisano v vodniku Analiza dnevnikov spletnega strežnika po napadu.

Kako PHP SOS pomaga konkretno?

  • Preverimo veljavne nastavitve za izpis napak in beleženje pri vsaki spletni strani in jih nastavimo za produkcijo.
  • Prehodne ukrepe PHP2Shell nastavimo glede na različico PHP in znova zaženemo vse workerje.
  • Dnevnike napak in dostopov od 20. 10. 2026 zavarujemo in jih pregledamo glede nepravilnosti.
  • V okviru varnostnega nadzora javimo nenavadna kopičenja napak, namesto da bi se izgubila v dnevniku.

Pogosta vprašanja

Kakšna je razlika med Error in Exception?

Oba implementirata vmesnik Throwable. Exception je namenjen napakam, ki jih aplikacija pričakuje in obravnava, na primer neuspeli povezavi s podatkovno bazo. Error pomeni notranje napake PHP, kot sta TypeError ali deljenje z ničlo.

Ali naj bo display_errors v produkciji vklopljen?

Ne. Sporočila o napakah v brskalniku izdajo poti, poizvedbe in včasih dostopne podatke. V produkciji mora biti display_errors nastavljen na Off, log_errors pa na On, da napake pristanejo v dnevniku in ne pri obiskovalcu.

Ali je prekoračitev pomnilnika mogoče ujeti s try/catch?

Ne. Če skripta preseže memory_limit, jo PHP konča s smrtno napako, ki je ni mogoče ujeti kot izjemo. Pojavi se samo v dnevniku napak, če je log_errors aktiven.

Kaj je fatal_error_backtraces?

Nastavitev, ki obstaja od PHP 8.5.0 in smrtnim napakam doda sled klicev (backtrace). Privzeto je aktivna. Kot prehodni ukrep proti PHP2Shell php.net za PHP 8.5 navaja, da jo nastavite na 0 in nato znova zaženete PHP.

Viri

Takojšnji stik

Vsaka ura šteje. Pišite nam zdaj.

Na kratko opišite sistem, različico PHP in opažanje. Odzovemo se, razjasnimo stanje in delamo na daljavo, dokler incident ni zaključen in dokumentiran.

Takojšnja pomoč