Εν συντομία: Η Zend Engine είναι ο πυρήνας της PHP. Μεταφράζει τον κώδικα PHP σε opcodes, τα εκτελεί σε μια εικονική μηχανή και διαχειρίζεται παράλληλα μεταβλητές και μνήμη. Από την PHP 4 βρίσκεται σε κάθε εγκατάσταση PHP. Επειδή οι ευπάθειες του PHP2Shell βρίσκονται σε αυτόν τον πυρήνα, δεν βοηθούν plugins ή ενημερώσεις CMS, παρά μόνο μια ενημερωμένη PHP με επανεκκίνηση.
Τι είναι η Zend Engine;
Η Zend Engine είναι το τμήμα της PHP που κάνει την πραγματική δουλειά. Όλα τα υπόλοιπα, όπως η σύνδεση με τον διακομιστή ιστού ή οι επεκτάσεις για βάσεις δεδομένων, στηρίζονται πάνω της. Μπορεί να συγκριθεί με τον κινητήρα ενός αυτοκινήτου: το αμάξωμα και ο εξοπλισμός διαφέρουν, ο κινητήρας κινεί τα πάντα.
Σύμφωνα με το εγχειρίδιο της PHP, το όνομα σχηματίστηκε από τα μικρά ονόματα των δημιουργών Zeev Suraski και Andi Gutmans. Η μηχανή παρουσιάστηκε στα μέσα του 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 για το αφηρημένο συντακτικό δέντρο, τρεις φάσεις έως το bytecode:
- Lexer: αναλύει τον πηγαίο κώδικα σε tokens, για παράδειγμα λέξεις-κλειδιά, ονόματα μεταβλητών και συμβολοσειρές.
- Parser: χτίζει από τα tokens ένα αφηρημένο συντακτικό δέντρο (AST), που αποτυπώνει τη δομή του προγράμματος.
- Μεταγλωττιστής: παράγει από το AST op arrays, δηλαδή λίστες opcodes, ένα για κάθε αρχείο και συνάρτηση.
- Executor (Zend VM): εκτελεί τα opcodes. Σύμφωνα με το RFC του JIT, σε κάθε opcode αντιστοιχεί μια συνάρτηση χειρισμού (handler) που το εκτελεί.
- Διαχείριση μνήμης: δεσμεύει και ελευθερώνει μνήμη για κάθε αίτημα και παρακολουθεί παράλληλα το όριο του
memory_limit.
Τα tokens ενός σεναρίου μπορούν να γίνουν ορατά με την επέκταση 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. Με αυτά ακριβώς τα δομικά στοιχεία συνεχίζει να εργάζεται ο parser.
Πώς διαχειρίζεται η 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 των Dmitry Stogov και Zeev Suraski, αφορούσε πιο συμπαγείς δομές δεδομένων και μια εξυπνότερη αναπαράσταση των τιμών. Το RFC ανέφερε κέρδη απόδοσης 20 έως 110 τοις εκατό σε πραγματικές εφαρμογές.
OPcache και JIT: επεκτάσεις της μηχανής
Χωρίς κρυφή μνήμη η μηχανή μεταφράζει κάθε σενάριο εκ νέου σε κάθε αίτημα. Η OPcache κρατά έτοιμα τα έτοιμα opcodes στην κοινή μνήμη. Από την PHP 8.0 υπάρχει επιπλέον ένας μεταγλωττιστής JIT. Σύμφωνα με το RFC βασίζεται στο DynASM, ένα εργαλείο από το έργο LuaJIT, και παράγει κώδικα μηχανής απευθείας από το bytecode. Η εικονική μηχανή παραμένει αμετάβλητη· ο JIT αντικαθιστά μόνο τα σημεία εισόδου των handlers.
Για τους διαχειριστές αυτό σημαίνει: η OPcache και ο JIT επιταχύνουν τη μηχανή, αλλά δεν αλλάζουν τη συμπεριφορά της σε σφάλματα. Μια ευπάθεια στον πυρήνα παραμένει και με ενεργή κρυφή μνήμη.
Γιατί οι ευπάθειες στη μηχανή έχουν ιδιαίτερο βάρος
Οι δύο ευπάθειες του PHP2Shell βρίσκονται στον πυρήνα της PHP. Στο CVE-2026-109618 μια κατάσταση Out-of-Memory μπορεί να διακόψει τη μηχανή ενώ τα δεδομένα του αιτήματος έχουν αρχικοποιηθεί μόνο εν μέρει· κατά τον καθαρισμό, μη έγκυρα δεδομένα αντιμετωπίζονται τότε ως έγκυρα. Στο CVE-2026-109619 η εσωτερική κατάσταση παραμένει μετά την απελευθέρωση της μνήμης και μπορεί να χρησιμοποιηθεί από ένα μεταγενέστερο αίτημα στον ίδιο worker.
Οι διορθωμένες εκδόσεις 8.5.12, 8.4.27, 8.3.36 και 8.2.35 αλλάζουν σύμφωνα με το εγχειρίδιο της PHP και τη συμπεριφορά του ορίου μνήμης: το memory_limit είναι εκεί ένα ήπιο όριο, ενώ μια νέα ρύθμιση memory_hard_limit_percent ορίζει ένα αυστηρό ανώτατο όριο. Το εγχειρίδιο επισημαίνει ότι μια έκδοση που δεν γνωρίζει αυτή τη ρύθμιση επηρεάζεται από τις ευπάθειες. Σε διανομές με backports μετρά επιπλέον το changelog του πακέτου.
Η μηχανή είναι φορτωμένη σε κάθε διεργασία PHP. Μετά την ενημέρωση πρέπει γι' αυτό να γίνει επανεκκίνηση όλων των workers του PHP-FPM, των διεργασιών Apache με mod_php και των λοιπών υπηρεσιών PHP.
Τι συμβαίνει στο εσωτερικό σε περίπτωση έλλειψης μνήμης, περιγράφει το άρθρο memory_limit και Out-of-Memory. Η ένταξη της ίδιας της ευπάθειας βρίσκεται στη σελίδα CVE-2026-109618.
Πώς βοηθά συγκεκριμένα η PHP SOS;
- Έλεγχος έκδοσης και κατάστασης πακέτων: Εντοπίζουμε ποια κατάσταση της μηχανής εκτελείται πράγματι, συμπεριλαμβανομένων των backports της διανομής σας.
- Ενημέρωση και επανεκκίνηση: Μέσω της υπηρεσίας PHP-Patch εφαρμόζουμε την ενημέρωση και ελέγχουμε ότι δεν έχει απομείνει κανένα process με παλιό κώδικα.
- Λογικός ορισμός ορίων μνήμης: Συντονίζουμε το
memory_limit, το νέο αυστηρό όριο και τα όρια cgroup με την εφαρμογή σας. - Διερεύνηση ανωμαλιών: Αξιολογούμε καταρρεύσεις workers ή διεργασίες με κατάσταση εξόδου 137 και ελέγχουμε αν μπορεί να κρύβεται πίσω τους επίθεση.
Συχνές ερωτήσεις
Από πού πήρε το όνομά της η Zend Engine;
Το όνομα σχηματίζεται από τα μικρά ονόματα των δημιουργών της: Zeev Suraski και Andi Gutmans. Η μηχανή παρουσιάστηκε σύμφωνα με το εγχειρίδιο της PHP στα μέσα του 1999 και αποτέλεσε από την PHP 4.0, τον Μάιο του 2000, τον πυρήνα της PHP.
Είναι η Zend Engine ξεχωριστό προϊόν που πρέπει να εγκαταστήσω;
Όχι. Η Zend Engine αποτελεί σταθερό μέρος κάθε εγκατάστασης PHP. Όποιος ενημερώνει την PHP, ενημερώνει αυτόματα και τη μηχανή. Με εμπορικά προϊόντα της εταιρείας Zend δεν έχει καμία σχέση.
Τι είναι ένα opcode;
Ένα opcode είναι μία μεμονωμένη εντολή για την εικονική μηχανή της PHP, για παράδειγμα μια πρόσθεση, μια κλήση συνάρτησης ή μια ανάθεση. Ο μεταγλωττιστής μεταφράζει κάθε σενάριο σε μια ακολουθία τέτοιων εντολών, τις οποίες εκτελεί στη συνέχεια η μηχανή.
Τι σχέση έχει η Zend Engine με το memory_limit;
Η μηχανή διαχειρίζεται τη μνήμη κάθε αιτήματος και προσέχει το όριο του memory_limit. Από τις εκδόσεις ασφαλείας της 21.10.2026 αυτό το όριο είναι σύμφωνα με το εγχειρίδιο ένα ήπιο όριο, που συμπληρώνεται από ένα αυστηρό όριο μέσω του memory_hard_limit_percent.