Kurz gesagt: Wenn ein Browser eine PHP-Seite anfordert, nimmt der Webserver die Anfrage an und reicht sie über eine Schnittstelle (SAPI) an PHP weiter. PHP übersetzt das Skript in Bytecode, führt ihn in der Zend Engine aus und gibt das Ergebnis, meist HTML, an den Webserver zurück. Danach wird der Zustand der Anfrage aufgeräumt, damit die nächste sauber beginnt.
Was passiert, wenn jemand Ihre Website aufruft?
Für Besucher ist es ein Klick. Auf dem Server laufen in Millisekunden viele Schritte ab. Wer diesen Ablauf kennt, versteht besser, warum Updates, Neustarts und Konfiguration so wichtig sind und warum eine Lücke in PHP selbst schwerer wiegt als eine Lücke in einem Plugin.
Das PHP-Handbuch nennt drei Bestandteile, die für eine PHP-Website nötig sind: den PHP-Interpreter (als CGI oder Servermodul), einen Webserver und einen Browser. Der Interpreter ist das Programm, das PHP-Code liest und ausführt. Wie er mit dem Webserver verbunden ist, bestimmt die Betriebsart.
Wie funktioniert PHP? Sieben Schritte einer Anfrage
- Anfrage: Der Browser schickt eine HTTP-Anfrage, etwa
GET /kontakt.php, an den Server. - Webserver: Apache, Nginx oder LiteSpeed nehmen die Anfrage an. Statische Dateien wie Bilder liefern sie selbst aus. Für
.php-Dateien rufen sie PHP auf. - Übergabe über die SAPI: Die Server-Schnittstelle (SAPI) übergibt Anfragedaten wie Kopfzeilen, Parameter und Formulardaten an PHP. Bei PHP-FPM geschieht das über das FastCGI-Protokoll, bei mod_php direkt im Apache-Prozess. Details unter SAPI erklärt.
- Anfrage vorbereiten: PHP legt die Anfragedaten in Variablen wie
$_GET,$_POST,$_COOKIEund$_FILESab und reserviert Speicher für die Anfrage. - Übersetzen: Das Skript wird in Bausteine (Tokens) zerlegt, daraus entsteht ein abstrakter Syntaxbaum (AST) und daraus Opcodes, eine Art Maschinensprache für PHP. Ist der OPcache aktiv, wird dieser Schritt übersprungen, wenn das Skript bereits im Cache liegt.
- Ausführen: Die virtuelle Maschine der Zend Engine arbeitet die Opcodes ab, fragt Datenbanken, liest Dateien und erzeugt die Ausgabe.
- Antwort und Aufräumen: Die Ausgabe geht über die SAPI zurück an den Webserver und von dort an den Browser. Anschließend gibt PHP den Speicher der Anfrage frei und setzt den Zustand zurück.
Den AST gibt es seit PHP 7. Laut dem zugehörigen RFC erzeugte der Parser vorher die Opcodes direkt während des Einlesens; die Trennung in drei Phasen machte den Compiler einfacher wartbar.
Ein Beispiel: Was das Skript von der Anfrage sieht
Das folgende harmlose Skript zeigt, welche Informationen PHP aus der Anfrage erhält und in welcher Betriebsart es läuft:
<?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";
Auf einem Server mit PHP-FPM gibt PHP_SAPI den Wert fpm-fcgi aus, unter Apache mit mod_php apache2handler. Legen Sie solche Prüfdateien nur kurz und nie dauerhaft im öffentlichen Verzeichnis ab, denn Versionsangaben helfen auch Angreifern bei der Orientierung.
Wo der Bytecode-Cache und der JIT ins Spiel kommen
Das Übersetzen in Schritt 5 kostet Zeit. Der OPcache speichert laut Handbuch vorkompilierten Bytecode im gemeinsamen Speicher und erspart PHP damit das Laden und Zerlegen der Skripte bei jeder Anfrage. Seit PHP 8.0 kann zusätzlich ein JIT-Compiler aus Opcodes echten Maschinencode erzeugen. Laut JIT-RFC ist er ein nahezu eigenständiger Teil von OPcache.
| Phase | Ergebnis | Wird gecacht? |
|---|---|---|
| Lexing | Token-Strom | nein |
| Parsing | abstrakter Syntaxbaum (AST) | nein |
| Kompilieren | Opcodes (Op-Arrays je Datei und Funktion) | ja, im OPcache |
| JIT (optional) | Maschinencode | ja, im OPcache-Speicher |
| Ausführen | Ausgabe der Seite | nein |
Der Cache betrifft nur den übersetzten Code. Daten der einzelnen Anfrage, etwa Formulareingaben oder Session-Werte, werden nicht über den OPcache geteilt.
Warum PHP2Shell genau in diesem Ablauf ansetzt
Die beiden PHP2Shell-Lücken betreffen nicht eine Anwendung, sondern den Ablauf selbst. Bei CVE-2026-109618 kann ein Out-of-Memory-Zustand PHP unterbrechen, während Anfragedaten erst teilweise vorbereitet sind, also in Schritt 4. Beim anschließenden Aufräumen können ungültige Daten dann als gültig behandelt werden.
Bei CVE-2026-109619 kann interner Zustand einer Anfrage nach dem Freigeben des Speichers bestehen bleiben. Eine spätere Anfrage im selben Worker kann ihn nutzen, bevor er zurückgesetzt wird. Das betrifft Schritt 7, das Aufräumen. Hintergründe stehen auf der Seite CVE-2026-109619 und im Beitrag zum Request-Lebenszyklus.
Daraus folgt: Schutzmaßnahmen im Anwendungscode, etwa Sicherheits-Plugins, greifen erst in Schritt 6. Bei mod_php wurde laut PHP-Team sogar ein Exploit gezeigt, bevor überhaupt Anwendungscode läuft. Wirksam ist nur das PHP-Update auf 8.5.12, 8.4.27, 8.3.36 oder 8.2.35 und ein Neustart aller PHP-Prozesse, weil langlebige Worker sonst weiter den alten Code ausführen.
Wie hilft PHP SOS konkret?
- Ablauf sichtbar machen: Wir ermitteln, welche Betriebsart, welche Konfiguration und welcher Cache auf Ihrem Server tatsächlich aktiv sind.
- Richtig aktualisieren: Wir spielen das PHP-Update ein und prüfen über die Startzeiten, dass kein alter Prozess mehr läuft.
- Schichten absichern: Im Rahmen der Server-Härtung begrenzen wir Anfragegrößen, Speicher und Rechte dort, wo sie wirken: vor dem Anwendungscode.
- Spuren prüfen: Bei ungeschützt erreichbaren Servern suchen wir nach Anzeichen eines Einbruchs.
Häufige Fragen
Wird PHP-Code bei jedem Aufruf neu übersetzt?
Ohne Cache ja: PHP zerlegt das Skript, baut einen Syntaxbaum und erzeugt daraus Opcodes. Mit aktivem OPcache liegen die Opcodes im gemeinsamen Speicher und werden wiederverwendet, solange sich die Datei nicht geändert hat.
Was bleibt nach einer Anfrage im Speicher?
Grundsätzlich wird der Zustand einer Anfrage am Ende aufgeräumt, damit die nächste Anfrage sauber beginnt. Langlebig sind nur Dinge wie der OPcache oder persistente Verbindungen. Genau bei diesem Aufräumen setzt CVE-2026-109619 an.
Warum muss PHP nach einem Update neu gestartet werden?
Bei PHP-FPM und mod_php laufen Prozesse dauerhaft und haben den alten Programmcode geladen. Neue Dateien auf der Festplatte ändern daran nichts. Erst ein Neustart lädt den korrigierten Code.
Ist ein Webserver ohne PHP sicherer?
Er hat weniger Angriffsfläche, weil keine Programmlogik auf Anfragen reagiert. Für rein statische Inhalte ist das eine echte Option. Für Shops, Formulare und Anmeldungen braucht man aber eine serverseitige Sprache, und dann zählt deren Pflege.