Ajankohtainen tilanne: PHP2Shell. Kaksi kriittistä PHP-haavoittuvuutta (CVSS 9.2) sallii haittakoodin suorittamisen ilman kirjautumista. Korjaukset 21.10.2026 alkaen.Mitä nyt on tehtävä →

Zend Engine: PHP:n sydän

Zend Engine kääntää PHP-koodin opcode-käskyiksi ja suorittaa ne. Kun sen osat tuntee, ymmärtää, miksi ytimen haavoittuvuudet kuten PHP2Shell korjaa vain PHP-päivitys.

Tilanne Lukuaika 4 minPHP-tietoa

Lyhyesti: Zend Engine on PHP:n ydin. Se kääntää PHP-koodin opcode-käskyiksi, suorittaa ne virtuaalikoneessa ja hallinnoi samalla muuttujia ja muistia. PHP 4:stä lähtien se on ollut jokaisessa PHP-asennuksessa. Koska PHP2Shell-haavoittuvuudet ovat tässä ytimessä, lisäosat tai CMS-päivitykset eivät auta, vaan ainoastaan päivitetty PHP ja uudelleenkäynnistys.

Mikä Zend Engine on?

Zend Engine on se PHP:n osa, joka tekee varsinaisen työn. Kaikki muu, esimerkiksi yhteys verkkopalvelimeen tai tietokantalaajennukset, rakentuu sen päälle. Sitä voi verrata auton moottoriin: korit ja varusteet vaihtelevat, mutta moottori pyörittää kaikkea.

PHP-käsikirjan mukaan nimi on muodostettu kehittäjien Zeev Suraskin ja Andi Gutmansin etunimistä. Moottori esiteltiin vuoden 1999 puolivälissä, ja se oli PHP:n ydin PHP 4.0:sta lähtien, joka ilmestyi toukokuussa 2000. Sen jälkeen sitä on uudistettu perusteellisesti useita kertoja.

PHP-versio Moottori Tärkein muutos käsikirjan ja RFC:iden mukaan
PHP 4.0 (2000) Zend Engine ensimmäinen yhteinen ydin, parempi suorituskyky
PHP 5.0 (2004) Zend Engine 2.0 uusi olimalli
PHP 7.0 (2015) Zend Engine 3.0 PHPNG: tiiviimmät tietorakenteet, AST
PHP 8.0 (2020) jatkokehitys JIT-kääntäjä osana OPcachea

Osat: kääntäjä, virtuaalikone, muisti

Moottori työskentelee selvästi erotettujen vaiheiden kautta. PHP 7:stä lähtien abstraktia syntaksipuuta koskevan RFC:n mukaan tavukoodiin on kolme vaihetta:

  1. Lexer: pilkkoo lähdekoodin tokeneiksi, esimerkiksi avainsanoiksi, muuttujien nimiksi ja merkkijonoiksi.
  2. Parser: rakentaa tokeneista abstraktin syntaksipuun (AST), joka kuvaa ohjelman rakenteen.
  3. Kääntäjä: tuottaa AST:stä op-taulukoita eli opcode-luetteloita, yhden kutakin tiedostoa ja funktiota kohden.
  4. Suorittaja (Zend VM): käy opcodet läpi. JIT-RFC:n mukaan jokaiseen opcodeen kuuluu käsittelijäfunktio, joka suorittaa sen.
  5. Muistinhallinta: varaa ja vapauttaa muistia jokaiselle pyynnölle ja valvoo samalla memory_limit-asetuksen rajaa.

Komentosarjan tokenit voi tehdä näkyviksi Tokenizer-laajennuksella. Se on harmitonta ja opettavaista:

<?php
$code = '<?php $summe = 2 + 3; echo $summe;';
foreach (token_get_all($code) as $token) {
    if (is_array($token)) {
        echo token_name($token[0]), ': ', trim($token[1]), "\n";
    } else {
        echo 'Zeichen: ', $token, "\n";
    }
}

Tuloste näyttää rivejä kuten T_VARIABLE: $summe tai T_LNUMBER: 2. Juuri näillä rakennuspalikoilla jäsennin jatkaa työtä.

Miten Zend Engine hallinnoi muuttujia?

Käsikirjan mukaan jokainen PHP-muuttuja on säiliössä nimeltä zval. Se sisältää tyypin ja arvon sekä hallintatietoja, muun muassa viitelaskurin (refcount). Laskuri kertoo, kuinka moni muuttujan nimi osoittaa samaan säiliöön.

<?php
$a = str_repeat('x', 10);
$b = $a;        // ei kopiointia, molemmat osoittavat samaan arvoon
$b .= 'y';      // vasta nyt kopioidaan (copy on write)
unset($a);      // laskuri pienenee, muisti vapautuu, kun se saavuttaa arvon 0

Kun laskuri saavuttaa nollan, moottori vapauttaa muistin. Olioiden välisiä kehäviittauksia varten on lisäksi roskienkerääjä (garbage collector). Lisää artikkelissa Muistinhallinta PHP:ssä.

PHP 7:n PHPNG-uudistus iski juuri tähän. Dmitry Stogovin ja Zeev Suraskin RFC:n mukaan tavoitteena olivat tiiviimmät tietorakenteet ja älykkäämpi arvojen esitys. RFC mainitsi 20–110 prosentin suorituskykyhyödyt todellisissa sovelluksissa.

OPcache ja JIT: moottorin laajennukset

Ilman välimuistia moottori kääntää jokaisen komentosarjan uudelleen jokaisella pyynnöllä. OPcache pitää valmiit opcodet valmiina jaetussa muistissa. PHP 8.0:sta lähtien mukana on lisäksi JIT-kääntäjä. RFC:n mukaan se perustuu DynASM:iin, LuaJIT-projektin työkaluun, ja tuottaa konekoodia suoraan tavukoodista. Virtuaalikone pysyy samana; JIT korvaa vain käsittelijöiden sisääntulopisteet.

Ylläpitäjälle tämä tarkoittaa: OPcache ja JIT nopeuttavat moottoria, mutta eivät muuta sen käyttäytymistä virhetilanteissa. Ytimen haavoittuvuus säilyy myös aktiivisella välimuistilla.

Miksi moottorin haavoittuvuudet painavat erityisen paljon

Kumpikin PHP2Shell-haavoittuvuus on PHP:n ytimessä. Haavoittuvuudessa CVE-2026-109618 Out-of-Memory-tila voi keskeyttää moottorin, kun pyyntötiedot on alustettu vasta osittain; siivouksessa virheellisiä tietoja käsitellään sitten kelvollisina. Haavoittuvuudessa CVE-2026-109619 sisäinen tila säilyy muistin vapauttamisen jälkeen, ja myöhempi pyyntö samassa worker-prosessissa voi käyttää sitä.

Korjatut versiot 8.5.12, 8.4.27, 8.3.36 ja 8.2.35 muuttavat PHP-käsikirjan mukaan myös muistirajan käyttäytymistä: memory_limit on niissä pehmeä raja, ja uusi asetus memory_hard_limit_percent määrittää kovan ylärajan. Käsikirja huomauttaa, että versio, joka ei tunne tätä asetusta, on haavoittuvuuksien piirissä. Backportteja käyttävissä jakeluissa ratkaisevaa on lisäksi paketin muutosloki.

Tärkeää

Moottori on ladattuna jokaisessa PHP-prosessissa. Päivityksen jälkeen kaikki PHP-FPM-workerit, mod_php:tä käyttävät Apache-prosessit ja muut PHP-palvelut on siksi käynnistettävä uudelleen.

Mitä sisäisesti tapahtuu muistin loppuessa, kuvaa artikkeli memory_limit ja Out-of-Memory. Itse haavoittuvuuden arviointi on sivulla CVE-2026-109618.

Miten PHP SOS auttaa konkreettisesti?

  • Version ja pakettitilan tarkistus: Selvitämme, mikä moottorin versio todella on käynnissä, jakelunne backportit mukaan lukien.
  • Päivitys ja uudelleenkäynnistys: PHP-päivityspalvelun kautta asennamme päivityksen ja varmistamme, ettei yksikään prosessi jää käyntiin vanhalla koodilla.
  • Muistirajojen järkevä asetus: Sovitamme memory_limit-asetuksen, uuden kovan rajan ja cgroup-rajat sovellukseenne.
  • Poikkeamien selvitys: Worker-prosessien kaatumiset tai prosessit, joiden poistumistila on 137, arvioimme ja tarkistamme, voiko niiden takana olla hyökkäys.

Usein kysytyt kysymykset

Mistä Zend Engine on saanut nimensä?

Nimi muodostuu kehittäjien etunimistä: Zeev Suraski ja Andi Gutmans. Moottori esiteltiin PHP-käsikirjan mukaan vuoden 1999 puolivälissä, ja se oli PHP:n ydin PHP 4.0:sta lähtien toukokuusta 2000.

Onko Zend Engine erillinen tuote, joka minun on asennettava?

Ei. Zend Engine on kiinteä osa jokaista PHP-asennusta. Kun PHP päivitetään, myös moottori päivittyy automaattisesti. Tällä ei ole mitään tekemistä Zend-yhtiön kaupallisten tuotteiden kanssa.

Mikä on opcode?

Opcode on yksittäinen käsky PHP:n virtuaalikoneelle, esimerkiksi yhteenlasku, funktiokutsu tai sijoitus. Kääntäjä muuntaa jokaisen komentosarjan tällaisten käskyjen jonoksi, jonka moottori sitten suorittaa.

Mitä tekemistä Zend Enginellä on memory_limit-asetuksen kanssa?

Moottori hallinnoi jokaisen pyynnön muistia ja valvoo samalla memory_limit-asetuksen rajaa. Käsikirjan mukaan 21.10.2026 julkaistuista tietoturvajulkaisuista alkaen tämä raja on pehmeä raja, jota täydentää kova raja asetuksella memory_hard_limit_percent.

Lähteet

Pikayhteys

Jokainen tunti on tärkeä. Kirjoittakaa meille nyt.

Kuvatkaa lyhyesti järjestelmä, PHP-versio ja havainnot. Otamme yhteyttä, selvitämme tilanteen ja työskentelemme etänä, kunnes tapaus on käsitelty loppuun ja dokumentoitu.

Pikaapu