Aktuális helyzet: PHP2Shell. Két kritikus PHP-rés (CVSS 9,2) lehetővé teszi kártékony kód futtatását bejelentkezés nélkül. Javítások 2026. 10. 21. óta.Mi a teendő most →

A kérés életciklusa: indulás, végrehajtás, leállítás

Hogyan indítja a PHP a folyamatokat, hogyan dolgozza fel a kéréseket, és hogyan takarít közben. A MINIT-től az MSHUTDOWN-ig terjedő fázisokkal és a CVE-2026-109619-cel való kapcsolattal.

Állapot 5 perc olvasási időPHP-tudástár

Röviden: A PHP Request Lifecycle két szinten zajlik. Folyamatonként egyszer a PHP betölti a bővítményeit (MINIT fázis), és a végén ismét lebontja őket (MSHUTDOWN). Minden egyes kérésnek saját indítási és takarítási fázisa van (RINIT és RSHUTDOWN). Webes üzemben egy worker sok kérést dolgoz fel egymás után, ezért a PHP-nak két kérés között megbízhatóan vissza kell állítania a kérés teljes állapotát. Éppen ezen a határon volt a CVE-2026-109619, a második PHP2Shell-rés.

Két szint: a folyamat és a kérés

A nem műszaki olvasónak segít egy kép: egy PHP-worker olyan, mint egy hivatali ablak. Az ablakot reggel egyszer berendezik űrlapokkal, bélyegzőkkel és számítógéppel. Utána egymás után sok látogató érkezik. Minden látogató után az asztalnak üresnek kell lennie, hogy a következő ne lásson idegen iratokat.

A PHP ugyanígy dolgozik. Egy folyamat indításakor betölti azokat a bővítményeket és beállításokat, amelyek minden kérésre azonosak. Minden kérés ezután saját memóriát, saját változókat és saját kéradatokat kap, például $_GET, $_POST vagy $_FILES. A kérés végén a PHP felszabadítja ezt a memóriát. A PHP Internals Book tömören összefoglalja: a PHP minden kérés végén elfelejti a kérés memóriáját.

A PHP Request Lifecycle fázisainak áttekintése

A nevek a PHP belsejéből származnak; minden bővítmény beakaszkodhat ezekbe a fázisokba.

Fázis Mikor fut Milyen gyakran Tipikus feladat
MINIT (Module Init) a folyamat indulásakor folyamatonként egyszer bővítmények regisztrálása, ini-bejegyzések létrehozása, tartós adatok
GINIT a globálisok létrehozásakor folyamatonként, szálaknál szálanként egy bővítmény globális változóinak előkészítése
RINIT (Request Init) minden kérés elején kérésenként a kérés memóriájának és állapotának előkészítése
Végrehajtás közben kérésenként az Ön PHP-kódja fut
RSHUTDOWN minden kérés végén kérésenként a kérés erőforrásainak felszabadítása
PRSHUTDOWN az RSHUTDOWN után kérésenként, ritkán használt utolsó takarítási munkák
MSHUTDOWN a folyamat befejezésekor folyamatonként egyszer tartós adatok felszabadítása

A PHP Internals Book egyik fontos mondata a bővítményfejlesztőknek: a globálisok nem ürülnek ki automatikusan minden kérés után. Amit kérésenként frissnek kell lennie, azt az RINIT-ben kell visszaállítani. Ez a szabály megmutatja, miért biztonsági szempontból kritikus pont a két kérés közötti határ.

A kérés végén a sorrend szintén rögzített: először azok a shutdown-függvények futnak, amelyeket a register_shutdown_function()-nel regisztrált, aztán a destruktorok, majd kiürül a kimeneti puffer. Csak ezután jön az RSHUTDOWN.

Miért használják újra a workereket

A parancssorban egy folyamat pontosan egy kérést dolgoz fel, és véget ér. Webes üzemben ez túl lassú lenne. A PHP-FPM, az Apache mod_php-val, a LiteSpeed és a FrankenPHP ezért workereket tart készenlétben, amelyek sok kérést szolgálnak ki egymás után. A MINIT ilyenkor egyszer fut, az RINIT és az RSHUTDOWN ezerszer. Hogyan irányítja az FPM a workereit, azt a A PHP-FPM elmagyarázva oldal magyarázza.

A PHP-FPM-ben a pm.max_requests határozza meg, hány kérés után induljon újra egy worker. Az alapérték 0, vagyis korlátlan. A kézikönyv a beállítást a harmadik fél programkönyvtáraiban lévő memóriaszivárgások elleni eszközként nevezi meg:

; FPM-pool: a worker újraindítása 500 kérés után (memóriaszivárgások ellen)
pm = dynamic
pm.max_children = 20
pm.max_requests = 500

Még tovább megy a FrankenPHP worker módja: ott az egész alkalmazás egyszer bootol, és a memóriában marad. Az alkalmazás állapota ilyenkor PHP-szinten is túléli a kérést. A példa megmutatja a különbséget:

<?php
function anfrageZaehler(): int
{
    static $zaehler = 0;   // a klasszikus FPM-üzemben kérésenként újra 0
    return ++$zaehler;     // worker módban az érték a kéréseken át tovább számlál
}
echo anfrageZaehler();

Klasszikus üzemben a hívás mindig 1-et ír ki, mert a PHP elveti a kérés memóriáját. Worker módban az érték addig nő, amíg a worker él. A FrankenPHP dokumentációja ezért azt tanácsolja, hogy a kérésre vonatkozó állapotot tudatosan állítsák vissza a kérések között.

Hol támad a CVE-2026-109619

A CVE-2026-109619 nem az Ön alkalmazáskódját érinti, hanem magát a PHP-t. A php.net szerint a kéréshez tartozó belső állapot túlélhette a memóriájának felszabadítását. Egy későbbi kérés ugyanabban a workerben felhasználhatta, mielőtt az inicializálás visszaállította volna. A képben: az ablak asztalán ott maradt egy cetli, amelyet már el kellett volna takarítani. A kihasználás részleteit szándékosan nem tesszük közzé; a besorolás a CVE-2026-109619 oldalon található.

A php.net erre a résre vonatkozó átmeneti intézkedései megerősített utakon támadnak, nem jelentenek teljes védelmet:

  1. session.upload_progress.enabled=0 a php.ini-ben, az FPM-poolban vagy a szerverkonfigurációban, utána minden workert újra kell indítani; nem az ini_set()-tel vagy a .user.ini-vel.
  2. A PHP 8.5-ön emellett fatal_error_backtraces=0 és újraindítás.
  3. Kérésenként el kell távolítani az érvénytelen vagy elavult beállításokat, amelyek az inicializálás előtt üzeneteket váltanak ki. Az üzenetek puszta elrejtése a php.net szerint nem segít.
  4. Az alkalmazásban ki kell javítani a kívülről kiváltható végzetes hibákat és időtúllépéseket, a callbackekben, a feltöltés- és importfeldolgozásban is.

Az igazi megoldás a frissítés a PHP 8.5.12, 8.4.27, 8.3.36 vagy 8.2.35 verzióra. Mivel a hiba a futó workerben van, csak az összes folyamat újraindítása után hat; a lépéseket a A PHP-FPM és az összes worker újraindítása oldal tartalmazza.

Tipp

Az újraindítás után a ps -eo pid,lstart,cmd | grep php paranccsal ellenőrizze, hogy az összes PHP-folyamat a frissítés időpontja után indult-e el.

Mit jelent az életciklus az üzemeltetés és a fejlesztés számára

A modellből világos szabályok vezethetők le. Az adminisztrátoroknak: a frissítés csak akkor hatásos, ha már egyetlen folyamat sem fut régi kóddal. Minden hosszú életű workereket használó üzemmódnak dokumentált újraindításra van szüksége. A fejlesztőknek: a worker módokban futó kód nem hagyhat kérésre vonatkozó állapotot statikus változókban vagy singletonokban, például felhasználói adatokat vagy jogosultságokat. Mindkettőjüknek: a naplókat 2026. október 20-tól meg kell őrizni, hogy később megítélhető legyen, történt-e valami a javítás előtt.

Hogyan segít konkrétan a PHP SOS?

A PHP-javítási szolgáltatással a gyakorlatban megvalósítjuk a modellt:

  • Az üzemmód meghatározása: Megállapítjuk, hogy PHP-FPM, mod_php, LiteSpeed, FrankenPHP vagy php-cgi fut-e, és hogyan kezelik a workereket.
  • Frissítés és újraindítás: Telepítjük a javított verziót, és ellenőrzötten újraindítunk minden workert.
  • Folyamatellenőrzés: Az indítási idők és a verziók alapján igazoljuk, hogy nem maradt régi folyamat.
  • A worker módok ellenőrzése: Hosszú életű alkalmazásoknál megnézzük, hogy a kérésre vonatkozó állapot rendesen visszaáll-e.

Gyakori kérdések

Minden kéréshez új folyamatot indít a PHP?

A parancssorban igen, webes üzemben többnyire nem. A PHP-FPM, az Apache mod_php-val, a LiteSpeed vagy a FrankenPHP egy folyamattal sok kérést dolgoztat fel egymás után. A kérések között a PHP rendbe teszi a kérés állapotát.

Mi a különbség a MINIT és az RINIT között?

A MINIT egyszer fut le, amikor a PHP-folyamat elindul, és tartós szerkezeteket hoz létre. Az RINIT minden egyes kérés elején fut, és azt készíti elő, amire csak az adott kérésnek van szüksége.

Segít a pm.max_requests a CVE-2026-109619 ellen?

A php.net a gyakoribb worker-újraindításokat nem nevezi meg átmeneti intézkedésként. A beállítás csak azt korlátozza, hány kérést dolgoz fel egy worker az újraindulása előtt. A rés ellen a frissítés és az összes worker azt követő újraindítása segít.

Mi a FrankenPHP worker módja?

Worker módban az alkalmazás egyszer bootol, és a memóriában marad. Ez időt takarít meg, de a statikus változók, a globálisok és a gyorsítótárak megmaradnak a kérések között. A FrankenPHP dokumentációja szerint a kérésre vonatkozó állapotot ezért tudatosan vissza kell állítani.

Források

Azonnali kapcsolat

Minden óra számít. Írjon nekünk most.

Ismertesse röviden a rendszert, a PHP-verziót és a megfigyelését. Jelentkezünk, tisztázzuk a helyzetet, és távolról dolgozunk, amíg az incidens le nem zárul és dokumentálva nem lesz.

Azonnali segítség