Röviden: Amikor egy böngésző PHP-oldalt kér, a webszerver fogadja a kérést, és egy felületen (SAPI) keresztül továbbadja a PHP-nek. A PHP a szkriptet bájtkóddá fordítja, a Zend Engine-ben végrehajtja, az eredményt, többnyire HTML-t, pedig visszaadja a webszervernek. Ezután a kérés állapotát feltakarítják, hogy a következő tisztán indulhasson.
Mi történik, amikor valaki megnyitja a weboldalát?
A látogatónak ez egy kattintás. A szerveren ezredmásodpercek alatt sok lépés zajlik le. Aki ismeri ezt a folyamatot, jobban érti, miért olyan fontosak a frissítések, az újraindítások és a konfiguráció, és miért nyom többet a latban egy magában a PHP-ban lévő rés, mint egy bővítményben lévő.
A PHP-kézikönyv három összetevőt nevez meg, amelyek egy PHP-weboldalhoz szükségesek: a PHP-értelmezőt (CGI-ként vagy szervermodulként), egy webszervert és egy böngészőt. Az értelmező az a program, amely a PHP-kódot beolvassa és végrehajtja. Az üzemmódot az határozza meg, hogyan kapcsolódik a webszerverhez.
Hogyan működik a PHP? Egy kérés hét lépése
- Kérés: A böngésző HTTP-kérést küld a szervernek, például
GET /kontakt.php. - Webszerver: Az Apache, az Nginx vagy a LiteSpeed fogadja a kérést. A statikus fájlokat, például a képeket maga szolgáltatja ki. A
.phpfájlokhoz meghívja a PHP-t. - Átadás a SAPI-n keresztül: A szerverfelület (SAPI) átadja a PHP-nek a kérés adatait, például a fejléceket, a paramétereket és az űrlapadatokat. PHP-FPM esetén ez a FastCGI protokollon keresztül történik, mod_php esetén közvetlenül az Apache-folyamatban. Részletek: A SAPI elmagyarázva.
- A kérés előkészítése: A PHP a kérés adatait olyan változókba teszi, mint a
$_GET, a$_POST, a$_COOKIEés a$_FILES, és memóriát foglal a kérésnek. - Fordítás: A szkriptet építőelemekre (tokenekre) bontja, ebből absztrakt szintaxisfa (AST), abból pedig opcode-ok keletkeznek, a PHP számára egyfajta gépi nyelv. Ha az OPcache aktív, ez a lépés kimarad, amennyiben a szkript már a gyorsítótárban van.
- Végrehajtás: A Zend Engine virtuális gépe feldolgozza az opcode-okat, adatbázisokat kérdez le, fájlokat olvas, és előállítja a kimenetet.
- Válasz és feltakarítás: A kimenet a SAPI-n keresztül visszakerül a webszerverhez, onnan pedig a böngészőhöz. Ezután a PHP felszabadítja a kérés memóriáját, és visszaállítja az állapotot.
Az AST a PHP 7 óta létezik. A hozzá tartozó RFC szerint korábban az elemző közvetlenül, beolvasás közben állította elő az opcode-okat; a három fázisra bontás egyszerűbben karbantarthatóvá tette a fordítót.
Példa: mit lát a szkript a kérésből
A következő ártalmatlan szkript megmutatja, milyen információkat kap a PHP a kérésből, és milyen üzemmódban fut:
<?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";
PHP-FPM-es szerveren a PHP_SAPI értéke fpm-fcgi, Apache és mod_php alatt apache2handler. Az ilyen ellenőrző fájlokat csak rövid időre, és soha ne tartósan tegye a nyilvános könyvtárba, mert a verziómegjelölések a támadóknak is segítenek a tájékozódásban.
Hol jön képbe a bájtkód-gyorsítótár és a JIT
Az 5. lépés fordítása időt vesz igénybe. Az OPcache a kézikönyv szerint előre lefordított bájtkódot tárol a közös memóriában, és így megkíméli a PHP-t attól, hogy minden kérésnél betöltse és szétbontsa a szkripteket. A PHP 8.0 óta emellett egy JIT-fordító is képes az opcode-okból valódi gépi kódot előállítani. A JIT-RFC szerint ez az OPcache szinte önálló része.
| Fázis | Eredmény | Gyorsítótárazzák? |
|---|---|---|
| Lexikális elemzés | tokenfolyam | nem |
| Szintaktikai elemzés | absztrakt szintaxisfa (AST) | nem |
| Fordítás | opcode-ok (op-tömbök fájlonként és függvényenként) | igen, az OPcache-ben |
| JIT (opcionális) | gépi kód | igen, az OPcache memóriájában |
| Végrehajtás | az oldal kimenete | nem |
A gyorsítótár csak a lefordított kódot érinti. Az egyes kérések adatait, például az űrlapbevitelt vagy a munkamenet-értékeket, az OPcache nem osztja meg.
Miért éppen ennél a folyamatnál támad a PHP2Shell
A két PHP2Shell-rés nem egy alkalmazást érint, hanem magát a folyamatot. A CVE-2026-109618 esetén egy memóriahiányos (out-of-memory) állapot megszakíthatja a PHP-t, miközben a kérés adatai még csak részben vannak előkészítve, vagyis a 4. lépésben. A következő feltakarításkor érvénytelen adatokat kezelhet a rendszer érvényesként.
A CVE-2026-109619 esetén egy kérés belső állapota a memória felszabadítása után is fennmaradhat. Egy későbbi kérés ugyanabban a workerben felhasználhatja, mielőtt visszaállítanák. Ez a 7. lépést, a feltakarítást érinti. A háttér a CVE-2026-109619 oldalon és a kérés életciklusáról szóló cikkben található.
Ebből következik: az alkalmazáskódban lévő védelmi intézkedések, például a biztonsági bővítmények, csak a 6. lépésben lépnek működésbe. A PHP-csapat szerint mod_php esetén még azelőtt bemutattak egy exploitot, hogy egyáltalán alkalmazáskód futna. Csak a PHP 8.5.12, 8.4.27, 8.3.36 vagy 8.2.35 verzióra való frissítés és az összes PHP-folyamat újraindítása hatásos, mert a hosszú életű workerek különben tovább a régi kódot hajtják végre.
Hogyan segít konkrétan a PHP SOS?
- A folyamat láthatóvá tétele: Megállapítjuk, hogy a szerverén valójában melyik üzemmód, melyik konfiguráció és melyik gyorsítótár aktív.
- Helyes frissítés: Telepítjük a PHP-frissítést, és az indítási időpontokból ellenőrizzük, hogy nem fut-e még régi folyamat.
- A rétegek védelme: A szerver-megerősítés keretében ott korlátozzuk a kérésméreteket, a memóriát és a jogokat, ahol hatnak: az alkalmazáskód előtt.
- Nyomok vizsgálata: A védelem nélkül elérhető szervereknél a feltörés jeleit keressük.
Gyakori kérdések
A PHP-kódot minden híváskor újrafordítja a rendszer?
Gyorsítótár nélkül igen: a PHP szétbontja a szkriptet, szintaxisfát épít, és abból opcode-okat állít elő. Aktív OPcache esetén az opcode-ok a közös memóriában vannak, és újra felhasználhatók, amíg a fájl nem változik.
Mi marad a memóriában egy kérés után?
Alapvetően a kérés állapotát a végén feltakarítják, hogy a következő kérés tisztán indulhasson. Tartósak csak az olyan dolgok, mint az OPcache vagy a perzisztens kapcsolatok. A CVE-2026-109619 éppen ennél a feltakarításnál támad.
Miért kell a PHP-t frissítés után újraindítani?
PHP-FPM és mod_php esetén a folyamatok tartósan futnak, és a régi programkódot töltötték be. A lemezen lévő új fájlok ezen nem változtatnak. Csak az újraindítás tölti be a javított kódot.
Biztonságosabb a PHP nélküli webszerver?
Kisebb a támadási felülete, mert nincs programlogika, amely a kérésekre reagál. Tisztán statikus tartalmaknál ez valódi lehetőség. Webshopokhoz, űrlapokhoz és bejelentkezésekhez viszont szerveroldali nyelv kell, és akkor a gondozása számít.