Na kratko: Ko brskalnik zahteva stran PHP, spletni strežnik zahtevo sprejme in jo prek vmesnika (SAPI) preda PHP. PHP skripto prevede v bajtno kodo, jo izvede v Zend Engine in rezultat, praviloma HTML, vrne spletnemu strežniku. Nato se stanje zahteve počisti, da naslednja začne čisto.
Kaj se zgodi, ko nekdo odpre vašo spletno stran?
Za obiskovalca je to klik. Na strežniku se v milisekundah odvije veliko korakov. Kdor pozna ta potek, bolje razume, zakaj so posodobitve, ponovni zagoni in konfiguracija tako pomembni ter zakaj ranljivost v samem PHP tehta več kot ranljivost v vtičniku.
Priročnik PHP našteva tri sestavine, potrebne za spletno stran v PHP: interpreter PHP (kot CGI ali strežniški modul), spletni strežnik in brskalnik. Interpreter je program, ki kodo PHP prebere in izvede. Kako je povezan s spletnim strežnikom, določa način delovanja.
Kako deluje PHP? Sedem korakov ene zahteve
- Zahteva: brskalnik strežniku pošlje zahtevo HTTP, na primer
GET /kontakt.php. - Spletni strežnik: Apache, Nginx ali LiteSpeed zahtevo sprejmejo. Statične datoteke, kot so slike, izdajo sami. Za datoteke
.phppokličejo PHP. - Predaja prek SAPI: vmesnik strežnika (SAPI) PHP preda podatke zahteve, kot so glave, parametri in podatki obrazcev. Pri PHP-FPM se to zgodi prek protokola FastCGI, pri mod_php neposredno v procesu Apache. Podrobnosti na strani SAPI razložen.
- Priprava zahteve: PHP podatke zahteve shrani v spremenljivke, kot so
$_GET,$_POST,$_COOKIEin$_FILES, ter za zahtevo rezervira pomnilnik. - Prevajanje: skripta se razčleni na gradnike (tokene), iz njih nastane abstraktno sintaktično drevo (AST) in iz njega opcode, nekakšen strojni jezik za PHP. Če je OPcache aktiven, se ta korak preskoči, kadar skripta že leži v predpomnilniku.
- Izvajanje: navidezni stroj Zend Engine obdela opcode, poizveduje po podatkovnih zbirkah, bere datoteke in ustvarja izpis.
- Odgovor in čiščenje: izpis gre prek SAPI nazaj spletnemu strežniku in od tam brskalniku. Nato PHP sprosti pomnilnik zahteve in ponastavi stanje.
AST obstaja od PHP 7. Po pripadajočem RFC je razčlenjevalnik prej opcode ustvarjal neposredno med branjem; delitev na tri faze je prevajalnik naredila lažje vzdržljiv.
Primer: kaj skripta vidi od zahteve
Naslednja neškodljiva skripta pokaže, katere informacije PHP prejme od zahteve in v katerem načinu teče:
<?php
header('Content-Type: text/plain; charset=utf-8');
echo 'Betriebsart (SAPI): ' . PHP_SAPI . "\n";
echo 'PHP-Version: ' . PHP_VERSION . "\n";
echo 'Methode: ' . ($_SERVER['REQUEST_METHOD'] ?? '-') . "\n";
echo 'Speicher in dieser Anfrage: ' . memory_get_usage() . " Bytes\n";
Na strežniku s PHP-FPM PHP_SAPI izpiše vrednost fpm-fcgi, pod Apacheem z mod_php apache2handler. Takšnih preizkusnih datotek ne puščajte v javnem imeniku trajno, ampak le za kratek čas, saj podatki o različici pomagajo tudi napadalcem pri orientaciji.
Kje v igro vstopita predpomnilnik bajtne kode in JIT
Prevajanje v koraku 5 vzame čas. OPcache po priročniku shrani predhodno prevedeno bajtno kodo v skupni pomnilnik in PHP tako prihrani nalaganje in razčlenjevanje skript ob vsaki zahtevi. Od PHP 8.0 lahko dodatno prevajalnik JIT iz opcode ustvari pravo strojno kodo. Po RFC za JIT je skoraj samostojen del OPcache.
| Faza | Rezultat | Ali se predpomni? |
|---|---|---|
| Leksikalna analiza | tok tokenov | ne |
| Razčlenjevanje | abstraktno sintaktično drevo (AST) | ne |
| Prevajanje | opcode (polja op za datoteko in funkcijo) | da, v OPcache |
| JIT (neobvezno) | strojna koda | da, v pomnilniku OPcache |
| Izvajanje | izpis strani | ne |
Predpomnilnik zadeva samo prevedeno kodo. Podatki posamezne zahteve, na primer vnosi v obrazce ali vrednosti seje, se prek OPcache ne delijo.
Zakaj PHP2Shell posega ravno v ta potek
Obe ranljivosti PHP2Shell ne zadevata ene aplikacije, ampak sam potek. Pri CVE-2026-109618 lahko stanje Out of Memory PHP prekine, medtem ko so podatki zahteve šele delno pripravljeni, torej v koraku 4. Pri naknadnem čiščenju se lahko neveljavni podatki obravnavajo kot veljavni.
Pri CVE-2026-109619 lahko notranje stanje zahteve ostane, potem ko je pomnilnik že sproščen. Poznejša zahteva v istem workerju ga lahko uporabi, preden se ponastavi. To zadeva korak 7, čiščenje. Ozadje je na strani CVE-2026-109619 in v prispevku o življenjskem ciklu zahteve.
Iz tega sledi: zaščitni ukrepi v kodi aplikacije, na primer varnostni vtičniki, zaležejo šele v koraku 6. Pri mod_php so po navedbah ekipe PHP exploit pokazali celo, preden sploh teče koda aplikacije. Učinkovita je samo posodobitev PHP na 8.5.12, 8.4.27, 8.3.36 ali 8.2.35 in ponovni zagon vseh procesov PHP, ker dolgoživi workerji sicer še naprej izvajajo staro kodo.
Kako PHP SOS pomaga konkretno?
- Prikaz poteka: ugotovimo, kateri način delovanja, katera konfiguracija in kateri predpomnilnik so na vašem strežniku dejansko aktivni.
- Pravilna posodobitev: namestimo posodobitev PHP in prek časov zagona preverimo, da ne teče več noben star proces.
- Zavarovanje plasti: v okviru utrjevanja strežnika omejimo velikost zahtev, pomnilnik in pravice tam, kjer učinkujejo: pred kodo aplikacije.
- Preverjanje sledi: pri nezaščiteno dosegljivih strežnikih iščemo znake vdora.
Pogosta vprašanja
Ali se koda PHP prevede znova ob vsakem klicu?
Brez predpomnilnika da: PHP skripto razčleni, zgradi sintaktično drevo in iz njega ustvari opcode. Z vklopljenim OPcache opcode ležijo v skupnem pomnilniku in se ponovno uporabijo, dokler se datoteka ni spremenila.
Kaj po zahtevi ostane v pomnilniku?
Načeloma se stanje zahteve ob koncu počisti, da naslednja zahteva začne čisto. Dolgoživi so samo elementi, kot sta OPcache ali trajne povezave. Prav pri tem čiščenju poseže CVE-2026-109619.
Zakaj je treba PHP po posodobitvi znova zagnati?
Pri PHP-FPM in mod_php procesi tečejo trajno in imajo naloženo staro programsko kodo. Nove datoteke na disku tega ne spremenijo. Šele ponovni zagon naloži popravljeno kodo.
Ali je spletni strežnik brez PHP varnejši?
Ima manj napadalne površine, ker na zahteve ne odziva nobena programska logika. Za povsem statične vsebine je to resnična možnost. Za spletne trgovine, obrazce in prijave pa je potreben jezik na strani strežnika, in takrat šteje njegovo vzdrževanje.