# A kérés életciklusa: indulás, végrehajtás, leállítás

> A PHP Request Lifecycle érthetően: MINIT, RINIT, RSHUTDOWN, MSHUTDOWN, a workerek újrahasznosítása, és hogy a CVE-2026-109619 miért éppen itt támad.

Forrás: https://phpsos.de/hu/php/request-lebenszyklus/  
Állapot: 2026. 10. 25.  
Szolgáltató: PHP SOS, PHP-vészhelyzeti segítség és szerverbiztonság. Azonnali segítség WhatsAppon: https://wa.me/491736494914?text=%C3%9Cdv%C3%B6zl%C3%B6m%2C%20PHP%20SOS%21%20Seg%C3%ADts%C3%A9gre%20van%20sz%C3%BCks%C3%A9g%C3%BCnk%20a%20PHP-szerver%C3%BCnkkel.%20C%C3%A9g%3A%20%E2%80%A6%20Weboldal%3A%20%E2%80%A6

**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](https://phpsos.de/hu/php/php-fpm-erklaert/) 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:

```ini
; 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
<?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](https://phpsos.de/hu/php2shell/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](https://phpsos.de/hu/php2shell/php-fpm-neustart/) 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](https://phpsos.de/hu/leistungen/php-patch-service/) 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

- [php.net: Biztonsági közlemény, 2026. 10. 21.](https://www.php.net/)
- [PHP-kézikönyv: FPM-konfiguráció](https://www.php.net/manual/en/install.fpm.configuration.php)
- [PHP Internals Book: A PHP életciklusa](https://www.phpinternalsbook.com/)
