Trenutno stanje: PHP2Shell. Dvije kritične PHP ranjivosti (CVSS 9.2) omogućuju zlonamjerni kod bez prijave. Zakrpe od 21. 10. 2026.Što sada učiniti →

Kako PHP stvara web-stranicu: put jednog zahtjeva

Što se događa između klika i gotove stranice: web-poslužitelj, SAPI, kompilator, OPcache i Zend VM u sedam koraka te zašto PHP2Shell napada upravo u tom slijedu.

Stanje 4 min čitanjaPHP znanje

Ukratko: Kada preglednik zatraži PHP stranicu, web-poslužitelj prima zahtjev i prosljeđuje ga PHP-u putem sučelja (SAPI). PHP skriptu prevodi u bytecode, izvršava ga u Zend Engineu i rezultat, najčešće HTML, vraća web-poslužitelju. Nakon toga se stanje zahtjeva čisti kako bi sljedeći počeo čist.

Što se događa kada netko otvori Vašu web-stranicu?

Za posjetitelje je to jedan klik. Na poslužitelju se u milisekundama odvija mnogo koraka. Tko poznaje taj slijed, bolje razumije zašto su ažuriranja, ponovna pokretanja i konfiguracija toliko važni i zašto ranjivost u samom PHP-u teže pogađa nego ranjivost u dodatku.

PHP priručnik navodi tri sastavnice potrebne za PHP web-stranicu: PHP interpreter (kao CGI ili modul poslužitelja), web-poslužitelj i preglednik. Interpreter je program koji čita i izvršava PHP kod. Kako je povezan s web-poslužiteljem, određuje način rada.

Kako radi PHP? Sedam koraka jednog zahtjeva

  1. Zahtjev: Preglednik poslužitelju šalje HTTP zahtjev, na primjer GET /kontakt.php.
  2. Web-poslužitelj: Apache, Nginx ili LiteSpeed primaju zahtjev. Statične datoteke poput slika isporučuju sami. Za .php datoteke pozivaju PHP.
  3. Predaja putem SAPI-ja: Sučelje poslužitelja (SAPI) predaje PHP-u podatke zahtjeva poput zaglavlja, parametara i podataka obrasca. Kod PHP-FPM-a to ide putem FastCGI protokola, kod mod_php-a izravno u Apacheovu procesu. Pojedinosti u članku SAPI objašnjen.
  4. Priprema zahtjeva: PHP podatke zahtjeva sprema u varijable poput $_GET, $_POST, $_COOKIE i $_FILES te rezervira memoriju za zahtjev.
  5. Prevođenje: Skripta se rastavlja na gradivne dijelove (tokene), iz njih nastaje apstraktno sintaktičko stablo (AST), a iz njega opcodeovi, svojevrsni strojni jezik za PHP. Ako je OPcache aktivan, ovaj se korak preskače kada se skripta već nalazi u predmemoriji.
  6. Izvršavanje: Virtualni stroj Zend Enginea obrađuje opcodeove, upućuje upite bazama podataka, čita datoteke i stvara izlaz.
  7. Odgovor i čišćenje: Izlaz putem SAPI-ja ide natrag web-poslužitelju, a odande pregledniku. Zatim PHP oslobađa memoriju zahtjeva i vraća stanje na početno.

AST postoji od PHP-a 7. Prema pripadajućem RFC-u parser je prije toga opcodeove stvarao izravno tijekom čitanja; podjela na tri faze učinila je kompilator lakšim za održavanje.

Primjer: što skripta vidi od zahtjeva

Sljedeća bezopasna skripta pokazuje koje podatke PHP dobiva iz zahtjeva i u kojem načinu rada radi:

<?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 poslužitelju s PHP-FPM-om PHP_SAPI ispisuje vrijednost fpm-fcgi, a pod Apacheom s mod_php-om apache2handler. Takve probne datoteke ostavljajte u javnom direktoriju samo kratko i nikad trajno, jer podaci o verziji pomažu i napadačima pri orijentaciji.

Gdje u igru ulaze predmemorija bytecodea i JIT

Prevođenje u koraku 5 troši vrijeme. OPcache prema priručniku pohranjuje unaprijed kompilirani bytecode u zajedničku memoriju i tako PHP-u štedi učitavanje i rastavljanje skripti pri svakom zahtjevu. Od PHP-a 8.0 dodatno JIT kompilator iz opcodeova može stvoriti pravi strojni kod. Prema JIT RFC-u gotovo je samostalan dio OPcachea.

Faza Rezultat Sprema li se u predmemoriju?
Leksička analiza niz tokena ne
Parsiranje apstraktno sintaktičko stablo (AST) ne
Kompiliranje opcodeovi (op-nizovi po datoteci i funkciji) da, u OPcacheu
JIT (neobavezno) strojni kod da, u memoriji OPcachea
Izvršavanje izlaz stranice ne

Predmemorija se odnosi samo na prevedeni kod. Podaci pojedinog zahtjeva, na primjer unosi u obrascu ili vrijednosti sesije, ne dijele se putem OPcachea.

Zašto PHP2Shell napada upravo u tom slijedu

Obje PHP2Shell ranjivosti ne pogađaju jednu aplikaciju, nego sam slijed. Kod CVE-2026-109618 stanje nedostatka memorije može prekinuti PHP dok su podaci zahtjeva tek djelomično pripremljeni, dakle u koraku 4. Pri naknadnom čišćenju nevaljani se podaci tada mogu tretirati kao valjani.

Kod CVE-2026-109619 unutarnje stanje zahtjeva može ostati sačuvano nakon oslobađanja memorije. Kasniji zahtjev u istom workeru može ga iskoristiti prije nego što se vrati na početno stanje. To se odnosi na korak 7, čišćenje. Pozadina je na stranici CVE-2026-109619 i u članku o životnom ciklusu zahtjeva.

Iz toga slijedi: zaštitne mjere u kodu aplikacije, na primjer sigurnosni dodaci, djeluju tek u koraku 6. Kod mod_php-a je prema PHP timu čak pokazan exploit prije nego što se uopće izvrši kod aplikacije. Djelotvorno je samo ažuriranje PHP-a na 8.5.12, 8.4.27, 8.3.36 ili 8.2.35 i ponovno pokretanje svih PHP procesa, jer dugovječni workeri inače nastavljaju izvršavati stari kod.

Kako PHP SOS konkretno pomaže?

  • Učiniti slijed vidljivim: Utvrđujemo koji su način rada, konfiguracija i predmemorija na Vašem poslužitelju stvarno aktivni.
  • Ispravno ažurirati: Instaliramo PHP ažuriranje i putem vremena pokretanja provjeravamo da više ne radi nijedan stari proces.
  • Osigurati slojeve: U okviru ojačavanja poslužitelja ograničavamo veličine zahtjeva, memoriju i prava ondje gdje djeluju: ispred koda aplikacije.
  • Provjeriti tragove: Kod nezaštićeno dostupnih poslužitelja tražimo znakove provale.

Česta pitanja

Prevodi li se PHP kod iznova pri svakom pozivu?

Bez predmemorije da: PHP rastavlja skriptu, gradi sintaktičko stablo i iz njega stvara opcodeove. S aktivnim OPcacheom opcodeovi se nalaze u zajedničkoj memoriji i ponovno se koriste dok se datoteka ne promijeni.

Što ostaje u memoriji nakon zahtjeva?

U načelu se stanje zahtjeva na kraju čisti kako bi sljedeći zahtjev počeo čist. Dugovječne su samo stvari poput OPcachea ili trajnih veza. Upravo na tom čišćenju napada CVE-2026-109619.

Zašto se PHP mora ponovno pokrenuti nakon ažuriranja?

Kod PHP-FPM-a i mod_php-a procesi rade neprekidno i učitali su stari programski kod. Nove datoteke na disku tu ništa ne mijenjaju. Tek ponovno pokretanje učitava ispravljeni kod.

Je li web-poslužitelj bez PHP-a sigurniji?

Ima manju površinu napada jer nikakva programska logika ne reagira na zahtjeve. Za isključivo statične sadržaje to je prava opcija. Ali za web-trgovine, obrasce i prijave treba jezik na strani poslužitelja, i tada je važno njegovo održavanje.

Izvori

Hitni kontakt

Svaki sat se računa. Pišite nam odmah.

Ukratko opišite sustav, verziju PHP-a i opažanje. Javit ćemo Vam se, razjasniti situaciju i raditi na daljinu dok incident nije zaključen i dokumentiran.

Hitna pomoć