PHP2Shell: Warum es zu den kritischen PHP-Lücken kommen konnte
Am 21. Oktober 2026 hat das PHP-Team per Notfallupdate zwei kritische Sicherheitslücken geschlossen, die unter dem Namen PHP2Shell bekannt wurden: CVE-2026-109618 und CVE-2026-109619. Beide erreichen einen CVSS-Score von 9,2 und erlauben im schlimmsten Fall Remote Code Execution ohne Authentifizierung. Das Besondere daran: Der Fehler steckt nicht in WordPress, einem Plugin oder einer Anwendung – sondern leider im PHP-Interpreter selbst, also in dem Programm, das deinen PHP-Code überhaupt ausführt. Dein eigener Code kann also fehlerfrei sein und dein Server ist trotzdem angreifbar. Doch wie konnte es überhaupt so weit kommen? Die Antwort liegt in einer 20 Jahre alten Designentscheidung, wie PHP mit Speichermangel umgeht.
Warum PHP hier besonders anfällig ist
Um zu verstehen, warum ausgerechnet PHP von dieser Lücke getroffen hat, muss man wissen, wie der Interpreter unter der Haube arbeitet. PHP läuft auf Webservern meistens in einer von zwei Varianten: Bei mod_php ist PHP direkt als Modul in den Apache-Webserver eingebaut, bei PHP-FPM läuft PHP dagegen als eigener Dienst mit mehreren Prozessen, an die der Webserver die Anfragen weiterreicht. Beide haben gemeinsam, dass PHP-Prozesse wiederverwendet werden: Ein Prozess bearbeitet eine Anfrage, räumt auf und nimmt dann die nächste entgegen. Für jede Anfrage gibt es einen eigenen Speicherbereich, der am Ende wieder komplett freigegeben wird – und genau das funktioniert nur sicher, solange danach nichts mehr auf diesen freigegebenen Speicher verweist.
Jede Anfrage läuft dabei in drei Phasen ab: Beim Startup liest PHP die Daten der Anfrage ein (etwa Formulardaten oder Datei-Uploads), danach läuft dein Script, und am Ende folgt der Shutdown, in dem aufgeräumt wird. Beide PHP2Shell-Lücken entstehen genau an den Übergängen zwischen diesen Phasen, also nicht in deinem Code, sondern in PHPs eigener Verwaltungslogik. Betroffen sind laut PHP-Team sämtliche Installationen, die Web-Anfragen ausliefern: PHP-FPM, Apache mit mod_php, php-cgi, FrankenPHP und LiteSpeed.
Der Kern des Problems: Der "Bailout" bei Speichermangel
Die eigentliche Ursache beider Lücken ist ein und dieselbe Designentscheidung. PHP begrenzt den Speicher pro Anfrage standardmäßig auf 128 MB. Wird dieses Limit überschritten, hat PHP bisher keinen sauberen Fehler zurückgegeben, sondern einen sogenannten Bailout ausgelöst – einen Sprungbefehl in C (ein longjmp()), der die gerade laufende Funktion sofort verlässt und direkt zur Fehlerbehandlung springt.
Das Problem: Die Funktion kommt dabei nie dazu, ihre Arbeit zu Ende zu bringen. Sie hat vielleicht bereits eingetragen, dass es eine neue Datenstruktur gibt, diese Struktur aber noch nicht vollständig befüllt. Später verlässt sich PHP darauf, dass alles, was eingetragen ist, auch gültig ist. So bleibt ein unvollständiger, "kaputter" Zustand im Speicher zurück, mit dem PHP danach weiterarbeitet.
Genau diese Mechanik macht sich die erste Lücke, CVE-2026-109618 ("RCE via OOM corruption"), zunutze: Wenn PHP einen Eintrag in ein internes Array einfügt, erhöht es zuerst den Zähler der Einträge und reserviert erst danach Speicher für den Namen des Eintrags. Bricht genau diese Reservierung wegen des Speicherlimits ab, sagt der Zähler, dass es einen Eintrag mehr gibt – aber dieser Eintrag wurde nie befüllt. Beim Aufräumen geht PHP alle gezählten Einträge durch und verarbeitet auch den leeren Eintrag, in dem noch alte Daten liegen. Wer diese Daten kontrolliert, kontrolliert, was PHP damit tut. Laut offiziellem Advisory kann mehrfach ausgelöster Speichermangel diesen Zustand zuverlässig herbeiführen und bis zur Remote Code Execution führen.
Damit der Angriff funktioniert, muss der Angreifer das Speicherlimit an genau der richtigen Stelle überschreiten – obwohl Uploads standardmäßig auf 8 MB begrenzt sind. Das Advisory beschreibt dafür mehrere Wege; ein Beispiel sind etwa Dateifelder mit leeren Dateinamen: Sie zählen nicht als Upload, aber PHP legt für jedes davon trotzdem mehrere Verwaltungseinträge an. Mit verschachtelten Feldnamen wächst dieser Aufwand stark, sodass laut den Entdeckern von Calif eine Anfrage unter 8 MB ausreicht, um mehr als 128 MB Speicher zu belegen. Der Angreifer kann damit steuern, an welcher Stelle PHP der Speicher ausgeht.
Am stärksten betroffen ist mod_php, weil dort der Angriff komplett während des Einlesens der Anfrage passiert – also bevor eine einzige Zeile deiner Anwendung läuft. mod_php räumt danach trotzdem auf und verarbeitet die kaputten Daten. PHP-FPM beendet in dieser Situation dagegen den ganzen Prozess, wodurch die unvollständigen Daten verschwinden. Vollständige Codeausführung wurde vom PHP-Team gegen mod_php mit Standardeinstellungen demonstriert, gegen FPM bei dieser Lücke nicht.
Die zweite Lücke: Use-after-free über mehrere Anfragen
Eng verwandt, aber mit anderem Angriffsweg kommt CVE-2026-109619 ("RCE via stale global state") daher. PHP hat globale Variablen, die zwischen Anfragen erhalten bleiben, aber während einer Anfrage auf deren Speicher zeigen. Diese Verweise müssen am Ende jeder Anfrage zurückgesetzt werden. Bricht ein Fehler – etwa wieder der Bailout – die Anfrage vorher ab, bleibt der Verweis bestehen und zeigt auf Speicher, der bereits freigegeben ist. Greift die nächste Anfrage darauf zu, spricht man von einem Use-after-free. Laut F5 kann dieser globale Zustand auf Anfrage-Speicher verweisen, obwohl dieser längst freigegeben wurde, wodurch eine spätere Anfrage diesen veralteten Zustand verarbeitet.
Der wichtigste Einstiegspunkt dafür ist session.upload_progress, eine kaum bekannte Funktion für Fortschrittsbalken bei Uploads. Sie ist standardmäßig aktiviert und speichert schon Daten in der Session, während PHP die Anfrage noch einliest, also bevor deine Anwendung überhaupt startet. Der Angriff läuft dann so ab: In der ersten Anfrage startet ein Upload, session.upload_progress legt Daten an, und dann überschreitet der Angreifer das Speicherlimit. PHP gibt den Speicher frei, setzt aber die Session-Verweise nicht zurück. Eine zweite Anfrage an denselben Prozess erreicht den Upload-Progress-Code und arbeitet mit diesen veralteten Verweisen weiter. Die Forscher von Wiz haben daraus zusätzlich ein Datenleck gebaut: PHP schickt Inhalte aus dem freigegebenen Speicher als Session-Cookie an den Angreifer zurück – darin können Passwörter oder API-Schlüssel aus fremden Anfragen stehen, und diese Informationen braucht der Angreifer, um den Use-after-free zuverlässig zur Codeausführung auszubauen. Auch gegen PHP-FPM wurde diese Lücke ausgenutzt, dort braucht der Angreifer allerdings eine passende Stelle in der Anwendung, an der PHP gespeicherte Session-Daten lädt.
Bemerkenswert ist in diesem Zusammenhang die Historie des Grundproblems – denn eigentlich hätte das alles schon viel früher auffallen müssen. Laut Calif fand Stefan Esser bereits 2004 eine ähnliche Lücke über das Speicherlimit. Im Jahr 2020 wurde ein verwandter Fehler gemeldet und als harmlos eingestuft, 2024 fand dann ein Sicherheitsforscher das Problem erneut, konnte aber nicht beweisen, dass es ausnutzbar ist. Erst im Jahr 2026 führten Calif, Wiz und OpenAI mit Hilfe von KI-Modellen genau diesen Beweis – wobei die KI den Fehler nicht selbst gefunden, sondern die aufwendige Arbeit der Ausnutzbarkeit beschleunigt hat. Die offizielle Veröffentlichung war ursprünglich für den 22. Oktober geplant; weil am 20. Oktober Details, ein Screenshot des Exploit-Tools und ein kurzes Video leakt wurden, veröffentlichte PHP den Patch einen Tag früher.
Was du jetzt konkret tun solltest
Die einzige vollständige Lösung ist ein Update auf PHP 8.5.12, 8.4.27, 8.3.36 oder 8.2.35 – oder auf ein Paket deiner Linux-Distribution, das den Fix enthält. Danach musst du PHP-FPM neu starten, weil die laufenden Prozesse sonst weiter die alte Version ausführen. Für PHP 8.1 und älter gibt es keine regulären Updates mehr; das PHP-Team hat aber minimale Source-Backports für PHP 7.4, 8.0 und 8.1 bereitgestellt.
Wer nicht sofort patchen kann, findet im offiziellen Advisory Teilmaßnahmen:
- Gegen CVE-2026-109618: das Speicherlimit pro Anfrage absalten (memory_limit=-1, am besten via php_admin_value in der FPM-Pool- oder Apache-Konfiguration) – das klingt unlogisch, nimmt dem Angreifer aber den vorhersehbaren Abbruch, den er braucht. Zusätzlich ein niedriges post_max_size setzen (8 MB ohne Uploads, 32 MB mit) und das Speicherlimit über das Betriebssystem, etwa per cgroup, begrenzen.
- Gegen CVE-2026-109619: session.upload_progress.enabled=0 setzen und danach alle PHP-Prozesse neu starten.
Beides sind laut PHP-Kernentwicklerin Gina Peter Banyard ausdrücklich nur Teilmaßnahmen und kein Ersatz für das Update – keine der Mitigationen blockt alle Angriffspfade vollständig. Der Patch selbst entfernt den Bailout bei Speichermangel komplett: Wird das Limit überschritten, darf die laufende Funktion ihre Arbeit sauber beenden, und PHP bricht erst danach ab. Bei einem zweiten, höheren Limit wird der Prozess sofort beendet, ohne irgendetwas aufzuräumen. Dadurch kann kein unvollständiger Zustand mehr zurückbleiben.
Der aktuelle Stand zur Ausnutzung ist gemischt: Cloudflare hat bereits Angriffsversuche beobachtet und watchTowr meldet Angriffe über sein Honeypot-Netzwerk, während andere Stellen bis zur Veröffentlichung keine bestätigten Fälle verzeichnen. Bei solchen großen Lücken tauchen zudem regelmäßig gefälschte Exploits auf, die den Rechner desjenigen infizieren, der sie startet – solchen Code solltest du nur lesen oder in einer isolierten virtuellen Maschine ausführen.
PHP2Shell ist also kein Fehler in einer einzelnen Anwendung, sondern ein Designfehler darin, wie PHP mit Speichermangel umgeht und dieser galt 20 Jahre lang als zu kompliziert, um ihn auszunutzen. Mit rund 5,1 Millionen öffentlich erreichbaren PHP-Hosts allein laut VirusTotal-Schätzungen zeigt der Fall zwei Dinge: Erstens muss jeder, der PHP im Betrieb hat, jetzt die Version prüfen und aktualisieren – auch wenn der eigene Code sauber ist. Zweitens zeigt der Fall der Branche, dass ein bekannter Fehler nicht mehr als harmlos gelten kann, nur weil er schwer auszunutzen ist – spätestens seit KI-Modelle die mühsame Exploit-Entwicklung massiv beschleunigen können.