Praegune olukord: PHP2Shell. Kaks kriitilist PHP turvaauku (CVSS 9,2) lubavad kahjulikku koodi ilma sisselogimata. Paigad alates 21.10.2026.Mida nüüd teha →

Päringu elutsükkel: käivitus, täitmine, lõpetamine

Kuidas PHP käivitab protsesse, töötleb päringuid ja nende vahel koristab. Faasidega MINIT-ist MSHUTDOWN-ini ja seosega CVE-2026-109619-ga.

Seis Lugemisaeg 4 minPHP teadmised

Lühidalt: PHP Request Lifecycle'il on kaks taset. Üks kord protsessi kohta laeb PHP oma laiendused (faas MINIT) ja lammutab need lõpus uuesti (MSHUTDOWN). Iga üksiku päringu jaoks on oma käivitus- ja koristusfaas (RINIT ja RSHUTDOWN). Veebitöös töötleb worker paljusid päringuid järjest, seetõttu peab PHP kahe päringu vahel kogu päringu seisundi usaldusväärselt lähtestama. Just sellel piiril asus CVE-2026-109619, teine PHP2Shelli turvaauk.

Kaks taset: protsess ja päring

Mitte-tehnikule aitab pilt: PHP worker on nagu ametiasutuse teenindusaken. Aken seatakse hommikul ühe korra sisse, vormide, templite ja arvutiga. Seejärel tulevad järjest paljud külastajad. Pärast iga külastajat peab laud olema tühi, et järgmine ei näeks võõraid dokumente.

PHP töötab samamoodi. Protsessi käivitamisel laeb see laiendused ja sätted, mis on kõigi päringute jaoks samad. Iga päring saab seejärel oma mälu, oma muutujad ja oma päringuandmed, nagu $_GET, $_POST või $_FILES. Päringu lõpus vabastab PHP selle mälu. PHP Internals Book võtab selle lühidalt kokku: PHP unustab päringu mälu iga päringu lõpus.

PHP Request Lifecycle'i faasid ülevaatlikult

Nimed pärinevad PHP sisemusest; iga laiendus võib end nendesse faasidesse haakida.

Faas Millal käivitub Kui tihti Tüüpiline ülesanne
MINIT (Module Init) protsessi käivitamisel üks kord protsessi kohta laiendite registreerimine, ini-kirjete loomine, püsivad andmed
GINIT globaalide loomisel protsessi kohta, lõimede puhul lõime kohta laiendi globaalsete muutujate ettevalmistamine
RINIT (Request Init) iga päringu alguses päringu kohta päringu mälu ja seisundi ettevalmistamine
Täitmine vahepeal päringu kohta teie PHP kood töötab
RSHUTDOWN iga päringu lõpus päringu kohta päringu ressursside vabastamine
PRSHUTDOWN pärast RSHUTDOWN-i päringu kohta, harva kasutatud viimased koristustööd
MSHUTDOWN protsessi lõpetamisel üks kord protsessi kohta püsivate andmete vabastamine

Oluline lause PHP Internals Book'ist laiendite arendajatele: globaale ei tühjendata pärast iga päringut automaatselt. Mis peab päringu kohta värske olema, tuleb RINIT-is lähtestada. See reegel näitab, miks piir kahe päringu vahel on turvakriitiline koht.

Ka päringu lõpus on järjekord fikseeritud: kõigepealt käivituvad shutdown-funktsioonid, mille olete registreerinud käsuga register_shutdown_function(), siis destruktorid, seejärel tühjendatakse väljundipuhver. Alles pärast seda järgneb RSHUTDOWN.

Miks workereid taaskasutatakse

Käsureal töötleb protsess täpselt ühe päringu ja lõpeb. Veebitöös oleks see liiga aeglane. PHP-FPM, Apache koos mod_php-ga, LiteSpeed ja FrankenPHP hoiavad seetõttu valmis workereid, mis teenindavad palju päringuid järjest. MINIT käivitub siis ühe korra, RINIT ja RSHUTDOWN tuhandeid kordi. Kuidas FPM oma workereid juhib, selgitab PHP-FPM selgitus.

PHP-FPM-is määrab pm.max_requests, mitme päringu järel worker uuesti käivitub. Vaikeväärtus on 0, ehk piiramatu. Käsiraamat nimetab säte vahendina kolmandate osapoolte teekide mälulekete vastu:

; FPM-pool: worker uuesti käivitada 500 päringu järel (mälulekete vastu)
pm = dynamic
pm.max_children = 20
pm.max_requests = 500

Veelgi kaugemale läheb FrankenPHP worker-režiim: seal käivitub kogu rakendus ühe korra ja jääb mällu. Rakenduse seisund jääb siis püsima ka PHP tasemel. Näide näitab vahet:

<?php
function anfrageZaehler(): int
{
    static $zaehler = 0;   // klassikalises FPM töös on päringu kohta jälle 0
    return ++$zaehler;     // worker-režiimis loeb väärtus päringute üle edasi
}
echo anfrageZaehler();

Klassikalises töös väljastab väljakutse alati 1, sest PHP viskab päringu mälu minema. Worker-režiimis väärtus kasvab seni, kuni worker elab. FrankenPHP dokumentatsioon soovitab seetõttu päringuga seotud seisund päringute vahel teadlikult lähtestada.

Kus CVE-2026-109619 rünnakut alustab

CVE-2026-109619 ei puuduta teie rakenduse koodi, vaid PHP-d ennast. php.net andmetel võis päringuga seotud sisemine seisund oma mälu vabastamise üle elada. Hilisem päring samas workeris võis seda kasutada, enne kui lähtestamine selle tagasi seadis. Pildis: teenindusakna lauale jäi paber, mis oleks pidanud juba ära koristatud olema. Ekspluateerimise üksikasju me teadlikult ei avalda; turvaaugu paigutust käsitleb CVE-2026-109619.

php.net ajutised meetmed selle turvaaugu vastu lähtuvad kinnitatud teedest, need ei ole täielik kaitse:

  1. session.upload_progress.enabled=0 php.ini-s, FPM-poolis või serveri seadistuses, seejärel kõik workerid uuesti käivitada; mitte kaudu ini_set() või .user.ini.
  2. PHP 8.5 puhul lisaks fatal_error_backtraces=0 ja taaskäivitus.
  3. Eemaldada päringu kohta kehtetud või iganenud sätted, mis tekitavad teateid enne lähtestamist. Teateid üksnes peitmine ei aita php.net järgi.
  4. Kõrvaldada rakenduses väljastpoolt esilekutsutavad fataalsed vead ja ajaületused, ka callback'ides ning üleslaadimise ja impordi töötluses.

Tegelik lahendus on uuendus versioonile PHP 8.5.12, 8.4.27, 8.3.36 või 8.2.35. Kuna viga on töötavas workeris, mõjub see alles kõigi protsesside taaskäivitusel; sammud on lehel PHP-FPM-i ja kõigi workerite taaskäivitamine.

Näpunäide

Kontrollige pärast taaskäivitust käsuga ps -eo pid,lstart,cmd | grep php, kas kõik PHP protsessid on käivitatud pärast uuenduse ajahetke.

Mida elutsükkel tähendab töö ja arenduse jaoks

Mudelist saab tuletada selged reeglid. Adminnidele: uuendus on mõjus alles siis, kui ükski vana koodiga protsess enam ei tööta. Iga pikaealiste workeritega töörežiim vajab dokumenteeritud taaskäivitust. Arendajatele: worker-režiimides töötav kood ei tohi jätta päringuga seotud seisundit staatilistesse muutujatesse ega singleton'idesse, näiteks kasutajaandmeid või õigusi. Mõlemale kehtib: säilitage logid alates 20.10.2026, et hiljem hinnata, kas enne paika midagi juhtus.

Kuidas PHP SOS konkreetselt aitab?

PHP paikamisteenusega viime mudeli praktikas ellu:

  • Töörežiimi tuvastamine: Selgitame välja, kas töötab PHP-FPM, mod_php, LiteSpeed, FrankenPHP või php-cgi ja kuidas workereid hallatakse.
  • Uuendus ja taaskäivitus: Paigaldame parandatud versiooni ja käivitame iga workeri kontrollitult uuesti.
  • Protsesside kontroll: Tõendame käivitusaegade ja versioonide põhjal, et ühtegi vana protsessi ei ole alles.
  • Worker-režiimide kontroll: Pikaealiste rakenduste puhul vaatame, kas päringuga seotud seisund lähtestatakse puhtalt.

Korduma kippuvad küsimused

Kas PHP käivitab iga päringu jaoks uue protsessi?

Käsureal jah, veebitöös enamasti mitte. PHP-FPM, Apache koos mod_php-ga, LiteSpeed või FrankenPHP laseb ühel protsessil töödelda paljusid päringuid järjest. Päringute vahel koristab PHP päringu seisundi.

Mis vahe on MINIT-il ja RINIT-il?

MINIT käivitub ühe korra, kui PHP protsess käivitub, ja loob püsivad struktuurid. RINIT käivitub iga üksiku päringu alguses ja valmistab ette selle, mida vajab ainult see päring.

Kas pm.max_requests aitab CVE-2026-109619 vastu?

php.net ei nimeta sagedasemaid workerite taaskäivitusi ajutise meetmena. Säte piirab ainult seda, mitu päringut worker töötleb, enne kui ta uuesti käivitub. Turvaaugu vastu aitab uuendus koos kõigi workerite järgneva taaskäivitusega.

Mis on FrankenPHP worker-režiim?

Worker-režiimis käivitub rakendus ühe korra ja jääb mällu. See säästab aega, kuid staatilised muutujad, globaalid ja vahemälud säilivad päringute vahel. FrankenPHP dokumentatsiooni järgi tuleb päringuga seotud seisund seetõttu teadlikult lähtestada.

Allikad

Kohene kontakt

Iga tund loeb. Kirjutage meile kohe.

Kirjeldage lühidalt süsteemi, PHP versiooni ja tähelepanekut. Võtame teiega ühendust, selgitame olukorra välja ja töötame kaugtööna, kuni intsident on lõpetatud ja dokumenteeritud.

Kohene abi