Trumpai: kai naršyklė paprašo PHP puslapio, žiniatinklio serveris priima užklausą ir per sąsają (SAPI) perduoda ją PHP. PHP paverčia skriptą baitkodu, vykdo jį Zend Engine ir grąžina rezultatą, dažniausiai HTML, žiniatinklio serveriui. Po to užklausos būsena sutvarkoma, kad kita užklausa prasidėtų švariai.
Kas vyksta, kai kas nors atidaro jūsų svetainę?
Lankytojui tai vienas paspaudimas. Serveryje per milisekundes įvyksta daug žingsnių. Kas šią eigą žino, geriau supranta, kodėl atnaujinimai, paleidimas iš naujo ir konfigūracija tokie svarbūs ir kodėl spraga pačiame PHP yra sunkesnė nei papildinio spraga.
PHP vadove nurodomos trys dalys, būtinos PHP svetainei: PHP interpretatorius (kaip CGI arba serverio modulis), žiniatinklio serveris ir naršyklė. Interpretatorius yra programa, kuri skaito ir vykdo PHP kodą. Kaip jis sujungtas su žiniatinklio serveriu, nusprendžia veikimo režimas.
Kaip veikia PHP? Septyni užklausos žingsniai
- Užklausa: naršyklė išsiunčia serveriui HTTP užklausą, pavyzdžiui,
GET /kontakt.php. - Žiniatinklio serveris: Apache, Nginx ar LiteSpeed priima užklausą. Statinius failus, tokius kaip paveikslėliai, pateikia patys.
.phpfailams iškviečia PHP. - Perdavimas per SAPI: serverio sąsaja (SAPI) perduoda PHP užklausos duomenis, tokius kaip antraštės, parametrai ir formų duomenys. PHP-FPM atveju tai vyksta per FastCGI protokolą, mod_php atveju tiesiogiai Apache procese. Išsamiau skyriuje SAPI paaiškinta.
- Užklausos paruošimas: PHP užklausos duomenis sudeda į kintamuosius, tokius kaip
$_GET,$_POST,$_COOKIEir$_FILES, ir rezervuoja užklausai atmintį. - Vertimas: skriptas suskaidomas į elementus (tokens), iš jų sukuriamas abstraktusis sintaksės medis (AST), o iš jo operacijų kodai (opcodes), tam tikra PHP mašininė kalba. Jei OPcache aktyvus, šis žingsnis praleidžiamas, kai skriptas jau yra talpykloje.
- Vykdymas: Zend Engine virtuali mašina apdoroja operacijų kodus, kreipiasi į duomenų bazes, skaito failus ir kuria išvestį.
- Atsakymas ir sutvarkymas: išvestis per SAPI grįžta žiniatinklio serveriui, o iš jo naršyklei. Po to PHP atlaisvina užklausos atmintį ir atstato būseną.
AST egzistuoja nuo PHP 7. Pasak su juo susijusio RFC, anksčiau analizatorius operacijų kodus kūrė tiesiogiai skaitydamas; padalijimas į tris fazes kompiliatorių padarė lengviau prižiūrimą.
Pavyzdys: ką skriptas mato iš užklausos
Šis nekenksmingas skriptas parodo, kokią informaciją PHP gauna iš užklausos ir kokiu režimu veikia:
<?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";
Serveryje su PHP-FPM PHP_SAPI išveda reikšmę fpm-fcgi, Apache su mod_php atveju apache2handler. Tokius patikros failus laikykite viešame kataloge tik trumpai ir niekada ilgam, nes versijos duomenys padeda ir užpuolikams orientuotis.
Kur įsijungia baitkodo talpykla ir JIT
Vertimas 5 žingsnyje kainuoja laiko. OPcache, pasak vadovo, saugo iš anksto sukompiliuotą baitkodą bendroje atmintyje ir taip PHP nereikia per kiekvieną užklausą įkelti bei išskaidyti skriptų. Nuo PHP 8.0 papildomai JIT kompiliatorius gali iš operacijų kodų sukurti tikrą mašininį kodą. Pasak JIT RFC, jis yra beveik savarankiška OPcache dalis.
| Fazė | Rezultatas | Ar talpinama? |
|---|---|---|
| Leksinė analizė (lexing) | elementų srautas | ne |
| Sintaksinė analizė (parsing) | abstraktusis sintaksės medis (AST) | ne |
| Kompiliavimas | operacijų kodai (op-masyvai kiekvienam failui ir funkcijai) | taip, OPcache |
| JIT (neprivaloma) | mašininis kodas | taip, OPcache atmintyje |
| Vykdymas | puslapio išvestis | ne |
Talpykla liečia tik išverstą kodą. Atskiros užklausos duomenys, pavyzdžiui, formų įvestys ar sesijų reikšmės, per OPcache nebendrinami.
Kodėl PHP2Shell kliūva būtent šioje eigoje
Abi PHP2Shell spragos liečia ne vieną programą, o pačią eigą. Esant CVE-2026-109618, atminties trūkumo būsena gali pertraukti PHP, kai užklausos duomenys paruošti tik iš dalies, t. y. 4 žingsnyje. Vėlesnio sutvarkymo metu neteisingi duomenys gali būti laikomi teisingais.
Esant CVE-2026-109619, vidinė užklausos būsena gali išlikti atlaisvinus atmintį. Vėlesnė užklausa tame pačiame darbiniame procese (worker) gali ją panaudoti, kol ji dar neatstatyta. Tai liečia 7 žingsnį, sutvarkymą. Pagrindas aprašytas puslapyje CVE-2026-109619 ir straipsnyje apie užklausos gyvavimo ciklą.
Iš to išplaukia: apsaugos priemonės programos kode, pavyzdžiui, saugumo papildiniai, suveikia tik 6 žingsnyje. Pasak PHP komandos, mod_php atveju netgi parodytas exploit dar prieš pradedant vykdyti programos kodą. Veiksmingas tik PHP atnaujinimas iki 8.5.12, 8.4.27, 8.3.36 ar 8.2.35 ir visų PHP procesų paleidimas iš naujo, nes ilgai veikiantys darbiniai procesai kitaip toliau vykdo senąjį kodą.
Kaip PHP SOS padeda konkrečiai?
- Eigos matomumas: nustatome, koks veikimo režimas, kokia konfigūracija ir kokia talpykla jūsų serveryje iš tikrųjų aktyvūs.
- Teisingas atnaujinimas: įdiegiame PHP atnaujinimą ir pagal paleidimo laikus patikriname, kad nebeveikia joks senas procesas.
- Sluoksnių apsauga: serverio sutvirtinimo rėmuose apribojame užklausų dydžius, atmintį ir teises ten, kur jos veikia: prieš programos kodą.
- Pėdsakų patikra: serveriuose, kurie buvo pasiekiami be apsaugos, ieškome įsilaužimo požymių.
Dažni klausimai
Ar PHP kodas verčiamas iš naujo per kiekvieną iškvietimą?
Be talpyklos taip: PHP suskaido skriptą, sukuria sintaksės medį ir iš jo sugeneruoja operacijų kodus (opcodes). Su aktyviu OPcache operacijų kodai laikomi bendroje atmintyje ir naudojami pakartotinai, kol failas nepakito.
Kas lieka atmintyje po užklausos?
Iš esmės užklausos būsena pabaigoje sutvarkoma, kad kita užklausa prasidėtų švariai. Ilgai išlieka tik tokie dalykai kaip OPcache ar pastovieji ryšiai. Būtent šiame sutvarkyme kliūva CVE-2026-109619.
Kodėl po atnaujinimo PHP reikia paleisti iš naujo?
PHP-FPM ir mod_php atveju procesai veikia nuolat ir yra įkėlę senąjį programos kodą. Nauji failai diske to nekeičia. Tik paleidimas iš naujo įkelia ištaisytą kodą.
Ar žiniatinklio serveris be PHP yra saugesnis?
Jis turi mažesnį atakos paviršių, nes jokia programos logika į užklausas nereaguoja. Grynai statiniam turiniui tai tikra galimybė. Tačiau parduotuvėms, formoms ir prisijungimams reikia serverio pusės kalbos, ir tada svarbi jos priežiūra.