Εν συντομία: Όταν ένας browser ζητά μια σελίδα PHP, ο διακομιστής ιστού δέχεται το αίτημα και το παραδίδει μέσω μιας διεπαφής (SAPI) στην PHP. Η PHP μεταφράζει το σενάριο σε bytecode, το εκτελεί στη Zend Engine και επιστρέφει το αποτέλεσμα, συνήθως HTML, στον διακομιστή ιστού. Στη συνέχεια η κατάσταση του αιτήματος καθαρίζεται, ώστε το επόμενο να ξεκινά καθαρά.
Τι συμβαίνει όταν κάποιος επισκέπτεται τον ιστότοπό σας;
Για τους επισκέπτες είναι ένα κλικ. Στον διακομιστή εκτελούνται μέσα σε χιλιοστά του δευτερολέπτου πολλά βήματα. Όποιος γνωρίζει αυτή τη διαδικασία, κατανοεί καλύτερα γιατί οι ενημερώσεις, οι επανεκκινήσεις και η διαμόρφωση είναι τόσο σημαντικές και γιατί μια ευπάθεια στην ίδια την PHP έχει μεγαλύτερο βάρος από μια ευπάθεια σε ένα plugin.
Το εγχειρίδιο της PHP αναφέρει τρία συστατικά που απαιτούνται για έναν ιστότοπο PHP: τον διερμηνέα PHP (ως CGI ή μονάδα διακομιστή), έναν διακομιστή ιστού και έναν browser. Ο διερμηνέας είναι το πρόγραμμα που διαβάζει και εκτελεί κώδικα PHP. Ο τρόπος σύνδεσής του με τον διακομιστή ιστού καθορίζει τον τρόπο λειτουργίας.
Πώς λειτουργεί η PHP; Επτά βήματα ενός αιτήματος
- Αίτημα: Ο browser στέλνει στον διακομιστή ένα αίτημα HTTP, για παράδειγμα
GET /kontakt.php. - Διακομιστής ιστού: Ο Apache, ο Nginx ή το LiteSpeed δέχονται το αίτημα. Στατικά αρχεία όπως οι εικόνες τα παραδίδουν οι ίδιοι. Για αρχεία
.phpκαλούν την PHP. - Παράδοση μέσω SAPI: Η διεπαφή διακομιστή (SAPI) παραδίδει στην PHP δεδομένα του αιτήματος, όπως κεφαλίδες, παραμέτρους και δεδομένα φορμών. Στο PHP-FPM αυτό γίνεται μέσω του πρωτοκόλλου FastCGI, στο mod_php απευθείας στη διεργασία του Apache. Λεπτομέρειες στη σελίδα Το SAPI εξηγημένο.
- Προετοιμασία του αιτήματος: Η PHP τοποθετεί τα δεδομένα του αιτήματος σε μεταβλητές όπως
$_GET,$_POST,$_COOKIEκαι$_FILESκαι δεσμεύει μνήμη για το αίτημα. - Μετάφραση: Το σενάριο αναλύεται σε δομικά στοιχεία (tokens), από αυτά προκύπτει ένα αφηρημένο συντακτικό δέντρο (AST) και από αυτό τα opcodes, ένα είδος γλώσσας μηχανής για την PHP. Αν η OPcache είναι ενεργή, το βήμα αυτό παραλείπεται όταν το σενάριο βρίσκεται ήδη στην κρυφή μνήμη.
- Εκτέλεση: Η εικονική μηχανή της Zend Engine εκτελεί τα opcodes, ρωτά βάσεις δεδομένων, διαβάζει αρχεία και παράγει την έξοδο.
- Απάντηση και καθαρισμός: Η έξοδος επιστρέφει μέσω του SAPI στον διακομιστή ιστού και από εκεί στον browser. Κατόπιν η PHP ελευθερώνει τη μνήμη του αιτήματος και επαναφέρει την κατάσταση.
Το AST υπάρχει από την PHP 7. Σύμφωνα με το σχετικό RFC, ο parser παρήγαγε προηγουμένως τα opcodes απευθείας κατά την ανάγνωση· ο διαχωρισμός σε τρεις φάσεις έκανε τον μεταγλωττιστή ευκολότερο στη συντήρηση.
Ένα παράδειγμα: τι βλέπει το σενάριο από το αίτημα
Το παρακάτω ακίνδυνο σενάριο δείχνει ποιες πληροφορίες λαμβάνει η PHP από το αίτημα και σε ποιον τρόπο λειτουργίας εκτελείται:
<?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";
Σε διακομιστή με PHP-FPM το PHP_SAPI επιστρέφει την τιμή fpm-fcgi, στον Apache με mod_php την τιμή apache2handler. Τοποθετήστε τέτοια αρχεία ελέγχου στον δημόσιο κατάλογο μόνο για λίγο και ποτέ μόνιμα, διότι οι ενδείξεις έκδοσης βοηθούν και τους επιτιθέμενους στον προσανατολισμό τους.
Πού μπαίνουν η κρυφή μνήμη bytecode και ο JIT
Η μετάφραση στο βήμα 5 κοστίζει χρόνο. Η OPcache αποθηκεύει, σύμφωνα με το εγχειρίδιο, προμεταγλωττισμένο bytecode στην κοινή μνήμη και γλιτώνει έτσι την PHP από τη φόρτωση και ανάλυση των σεναρίων σε κάθε αίτημα. Από την PHP 8.0 ένας μεταγλωττιστής JIT μπορεί επιπλέον να παράγει από τα opcodes πραγματικό κώδικα μηχανής. Σύμφωνα με το RFC του JIT, αποτελεί ένα σχεδόν αυτόνομο τμήμα της OPcache.
| Φάση | Αποτέλεσμα | Αποθηκεύεται στην κρυφή μνήμη; |
|---|---|---|
| Λεκτική ανάλυση | ροή tokens | όχι |
| Συντακτική ανάλυση | αφηρημένο συντακτικό δέντρο (AST) | όχι |
| Μεταγλώττιση | opcodes (op arrays ανά αρχείο και συνάρτηση) | ναι, στην OPcache |
| JIT (προαιρετικά) | κώδικας μηχανής | ναι, στη μνήμη της OPcache |
| Εκτέλεση | έξοδος της σελίδας | όχι |
Η κρυφή μνήμη αφορά μόνο τον μεταφρασμένο κώδικα. Τα δεδομένα του εκάστοτε αιτήματος, όπως οι εισαγωγές φορμών ή οι τιμές συνεδρίας, δεν μοιράζονται μέσω της OPcache.
Γιατί το PHP2Shell στοχεύει ακριβώς αυτή τη διαδικασία
Οι δύο ευπάθειες του PHP2Shell δεν αφορούν μια εφαρμογή, αλλά την ίδια τη διαδικασία. Στο CVE-2026-109618 μια κατάσταση Out-of-Memory μπορεί να διακόψει την PHP ενώ τα δεδομένα του αιτήματος έχουν προετοιμαστεί μόνο εν μέρει, δηλαδή στο βήμα 4. Κατά τον επακόλουθο καθαρισμό, μη έγκυρα δεδομένα μπορεί τότε να αντιμετωπιστούν ως έγκυρα.
Στο CVE-2026-109619 η εσωτερική κατάσταση ενός αιτήματος μπορεί να παραμείνει μετά την απελευθέρωση της μνήμης. Ένα μεταγενέστερο αίτημα στον ίδιο worker μπορεί να τη χρησιμοποιήσει προτού επαναφερθεί. Αυτό αφορά το βήμα 7, τον καθαρισμό. Το υπόβαθρο βρίσκεται στη σελίδα CVE-2026-109619 και στο άρθρο για τον κύκλο ζωής του αιτήματος.
Από αυτό προκύπτει: τα μέτρα προστασίας στον κώδικα της εφαρμογής, όπως τα plugins ασφαλείας, ενεργοποιούνται μόλις στο βήμα 6. Στο mod_php επιδείχθηκε σύμφωνα με την ομάδα της PHP ακόμη και exploit προτού καν εκτελεστεί κώδικας της εφαρμογής. Αποτελεσματική είναι μόνο η ενημέρωση της PHP στις 8.5.12, 8.4.27, 8.3.36 ή 8.2.35 και η επανεκκίνηση όλων των διεργασιών PHP, επειδή οι μακροβίου διάρκειας workers διαφορετικά συνεχίζουν να εκτελούν τον παλιό κώδικα.
Πώς βοηθά συγκεκριμένα η PHP SOS;
- Ορατή διαδικασία: Εντοπίζουμε ποιος τρόπος λειτουργίας, ποια διαμόρφωση και ποια κρυφή μνήμη είναι πράγματι ενεργά στον διακομιστή σας.
- Σωστή ενημέρωση: Εφαρμόζουμε την ενημέρωση της PHP και ελέγχουμε μέσω των χρόνων εκκίνησης ότι δεν εκτελείται πλέον κανένα παλιό process.
- Θωράκιση των επιπέδων: Στο πλαίσιο της θωράκισης διακομιστή περιορίζουμε μεγέθη αιτημάτων, μνήμη και δικαιώματα εκεί όπου έχουν αποτέλεσμα: πριν από τον κώδικα της εφαρμογής.
- Έλεγχος για ίχνη: Σε διακομιστές που ήταν προσβάσιμοι χωρίς προστασία αναζητούμε ενδείξεις εισβολής.
Συχνές ερωτήσεις
Μεταφράζεται ο κώδικας PHP εκ νέου σε κάθε κλήση;
Χωρίς κρυφή μνήμη ναι: η PHP αναλύει το σενάριο, χτίζει ένα συντακτικό δέντρο και δημιουργεί από αυτό opcodes. Με ενεργή OPcache τα opcodes βρίσκονται στην κοινή μνήμη και επαναχρησιμοποιούνται όσο το αρχείο δεν έχει αλλάξει.
Τι παραμένει στη μνήμη μετά από ένα αίτημα;
Κατ' αρχήν η κατάσταση ενός αιτήματος καθαρίζεται στο τέλος, ώστε το επόμενο αίτημα να ξεκινά καθαρά. Μακροβίου διάρκειας είναι μόνο πράγματα όπως η OPcache ή οι μόνιμες συνδέσεις. Ακριβώς σε αυτόν τον καθαρισμό στοχεύει το CVE-2026-109619.
Γιατί πρέπει να γίνει επανεκκίνηση της PHP μετά από ενημέρωση;
Στο PHP-FPM και στο mod_php οι διεργασίες εκτελούνται μόνιμα και έχουν φορτώσει τον παλιό κώδικα του προγράμματος. Τα νέα αρχεία στον δίσκο δεν το αλλάζουν. Μόνο μια επανεκκίνηση φορτώνει τον διορθωμένο κώδικα.
Είναι ένας διακομιστής ιστού χωρίς PHP ασφαλέστερος;
Έχει μικρότερη επιφάνεια επίθεσης, επειδή καμία λογική προγράμματος δεν αντιδρά στα αιτήματα. Για αμιγώς στατικό περιεχόμενο αυτό είναι πραγματική επιλογή. Για e-shop, φόρμες και συνδέσεις χρηστών χρειάζεται όμως γλώσσα από την πλευρά του διακομιστή και τότε μετρά η συντήρησή της.