Накратко: Zend Engine е ядрото на PHP. Тя превежда PHP кода в опкодове, изпълнява ги във виртуална машина и при това управлява променливите и паметта. От PHP 4 насам тя е в основата на всяка инсталация на PHP. Тъй като уязвимостите на PHP2Shell се намират в това ядро, не помагат нито добавки, нито актуализации на CMS, а само актуализиран PHP с рестартиране.
Какво е Zend Engine?
Zend Engine е частта от PHP, която върши същинската работа. Всичко останало, например връзката с уеб сървъра или разширенията за бази данни, се надгражда върху нея. Може да се сравни с двигателя на автомобила: каросерията и оборудването се различават, но двигателят задвижва всичко.
Според ръководството на PHP името е образувано от малките имена на разработчиците Зееб Сураски и Анди Гутманс. Машината е представена в средата на 1999 г. и от PHP 4.0, издаден през май 2000 г., е ядрото на PHP. Оттогава тя е преработвана основно няколко пъти.
| Версия на PHP | Машина | Най-важна промяна според ръководството и RFC |
|---|---|---|
| PHP 4.0 (2000 г.) | Zend Engine | първо общо ядро, по-добра производителност |
| PHP 5.0 (2004 г.) | Zend Engine 2.0 | нов обектен модел |
| PHP 7.0 (2015 г.) | Zend Engine 3.0 | PHPNG: по-компактни структури от данни, AST |
| PHP 8.0 (2020 г.) | Развитие | JIT компилатор като част от OPcache |
Компонентите: компилатор, виртуална машина, памет
Машината работи на ясно разделени етапи. От PHP 7 според RFC за абстрактното синтактично дърво до байткода има три фази:
- Лексер: разчленява изходния код на токени, например ключови думи, имена на променливи и низове.
- Парсер: изгражда от токените абстрактно синтактично дърво (AST), което отразява структурата на програмата.
- Компилатор: създава от AST op-масиви, т.е. списъци от опкодове, по един за всеки файл и функция.
- Изпълнител (Zend VM): обработва опкодовете. Според JIT-RFC към всеки опкод принадлежи функция-обработчик, която го изпълнява.
- Управление на паметта: резервира и освобождава памет за всяка заявка и при това следи границата от
memory_limit.
Токените на един скрипт могат да се покажат с разширението Tokenizer. Това е безобидно и поучително:
<?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";
}
}
Изходът показва записи като T_VARIABLE: $summe или T_LNUMBER: 2. Точно с тези градивни елементи парсерът продължава да работи.
Как Zend Engine управлява променливите?
Според ръководството всяка PHP променлива се намира в контейнер, наречен zval. Той съдържа тип и стойност, както и служебни данни, сред които брояч на референциите (refcount). Броячът показва колко имена на променливи сочат към един и същ контейнер.
<?php
$a = str_repeat('x', 10);
$b = $a; // без копиране, и двете сочат към една и съща стойност
$b .= 'y'; // едва сега се копира (copy on write)
unset($a); // броячът намалява, паметта се освобождава, когато стигне 0
Когато броячът достигне нула, машината освобождава паметта. За кръгови препратки между обекти има допълнително събирач на боклук (garbage collector). Повече по темата в статията Управление на паметта в PHP.
Преработката PHPNG за PHP 7 се насочва именно натам. Според RFC на Дмитрий Стогов и Зееб Сураски целта била по-компактни структури от данни и по-находчиво представяне на стойностите. RFC посочва ръст на производителността от 20 до 110 процента при реални приложения.
OPcache и JIT: разширения на машината
Без кеш машината превежда всеки скрипт наново при всяка заявка. OPcache държи готовите опкодове в споделената памет. От PHP 8.0 има допълнително JIT компилатор. Според RFC той се основава на DynASM, инструмент от проекта LuaJIT, и създава машинен код директно от байткода. Виртуалната машина при това остава непроменена; JIT заменя само входните точки на обработчиците.
За операторите това означава: OPcache и JIT ускоряват машината, но не променят поведението ѝ при грешки. Уязвимост в ядрото остава и при активен кеш.
Защо уязвимостите в машината тежат особено
Двете уязвимости на PHP2Shell се намират в ядрото на PHP. При CVE-2026-109618 състояние на изчерпана памет (out-of-memory) може да прекъсне машината, докато данните от заявката са инициализирани само частично; при почистването невалидни данни след това се третират като валидни. При CVE-2026-109619 вътрешно състояние остава след освобождаването на паметта и може да бъде използвано от по-късна заявка в същия работен процес.
Поправените версии 8.5.12, 8.4.27, 8.3.36 и 8.2.35 според ръководството на PHP променят и поведението на границата на паметта: memory_limit там е мека граница, а нова настройка memory_hard_limit_percent задава твърда горна граница. Ръководството посочва, че версия, която не познава тази настройка, е засегната от уязвимостите. При дистрибуции с backport корекции допълнително значение има дневникът на промените на пакета.
Машината е заредена във всеки PHP процес. Затова след актуализацията всички PHP-FPM работни процеси, процесите на Apache с mod_php и останалите PHP услуги трябва да бъдат рестартирани.
Какво се случва вътрешно при недостиг на памет, описва статията memory_limit и Out-of-Memory. Класификацията на самата уязвимост е на страницата CVE-2026-109618.
Как помага PHP SOS конкретно?
- Проверка на версията и състоянието на пакета: Установяваме кое състояние на машината действително работи, включително backport корекциите на Вашата дистрибуция.
- Актуализиране и рестартиране: Чрез услугата за PHP корекции внасяме актуализацията и контролираме да не остане процес със стар код.
- Смислено задаване на ограниченията на паметта: Съгласуваме
memory_limit, новата твърда граница и ограниченията на cgroup с Вашето приложение. - Разследване на необичайни случаи: Сривове на работни процеси или процеси със статус на изход 137 класифицираме и проверяваме дали зад тях може да стои атака.
Често задавани въпроси
Откъде идва името Zend Engine?
Името е съставено от малките имена на нейните разработчици: Зееб Сураски и Анди Гутманс. Според ръководството на PHP машината е представена в средата на 1999 г. и от PHP 4.0 през май 2000 г. е ядрото на PHP.
Zend Engine самостоятелен продукт ли е, който трябва да инсталирам?
Не. Zend Engine е неразделна част от всяка инсталация на PHP. Който актуализира PHP, автоматично актуализира и машината. С търговските продукти на фирмата Zend това няма нищо общо.
Какво е опкод?
Опкодът е отделна команда за виртуалната машина на PHP, например събиране, извикване на функция или присвояване. Компилаторът превежда всеки скрипт в последователност от такива команди, които машината след това обработва.
Какво общо има Zend Engine с memory_limit?
Машината управлява паметта на всяка заявка и следи границата от memory_limit. От изданията за сигурност от 21.10.2026 г. тази граница според ръководството е мека граница, допълнена от твърда граница чрез memory_hard_limit_percent.