Die erste Frage bei PHP2Shell lautet nicht “welche Anwendung ist betroffen”, sondern “welche PHP-Version läuft da eigentlich gerade”. Die Lücke steckt nicht in WordPress, Nextcloud oder Laravel, sondern in der PHP-Engine selbst. Ein sauberer Anwendungscode hilft dir hier nicht.
Hinter dem Namen stecken zwei Schwachstellen, CVE-2026-109618 und CVE-2026-109619, beide mit CVSS v4.0 9.2 bewertet. Betroffen ist jede PHP-Installation, die Webanfragen bedient, also PHP-FPM, Apache mit mod_php, php-cgi, FrankenPHP und LiteSpeed. Das gilt für den gemieteten vServer genauso wie für den Docker-Container im Homelab oder das Shared-Hosting-Paket. Wie schnell sich das Ganze tatsächlich ausnutzen lässt, wird unterschiedlich eingeschätzt, dazu unten mehr. Patchen musst du in jedem Fall.
Was steckt hinter CVE-2026-109618 und CVE-2026-109619?
Beide Fehler haben dieselbe Wurzel. Wenn PHP mitten in einer Anfrage in einen Fatal Error läuft, etwa weil das memory_limit erreicht ist, bricht die Engine die Anfrage per longjmp() ab, ohne den Stack ordentlich abzubauen. Danach läuft Aufräumcode über Strukturen, die nur halb aufgebaut sind oder deren Speicher schon freigegeben wurde.
- CVE-2026-109618 (Speichermangel): Ein Out-of-Memory-Fehler beim Verarbeiten der Anfrage hinterlässt Daten, die als gültig behandelt werden, obwohl sie es nicht sind. Das Heap-Material der gleichen Anfrage wird beim Shutdown weiterverarbeitet.
- CVE-2026-109619 (veralteter globaler Zustand): Ein Modul behält einen Zeiger auf Speicher, der der Anfrage gehörte und längst freigegeben ist. Die nächste Anfrage auf demselben Worker greift darauf zu. Das ist ein klassischer Use-after-free und kann auch Speicherinhalte preisgeben.
Der Knackpunkt: Der kritische Teil läuft bevor dein Anwendungscode überhaupt startet. Beim Hochladen von Multipart-Daten pflegt PHP den Session-Fortschritt (session.upload_progress), und genau dort wurden die überzeugendsten Angriffspfade gezeigt. Dazu kommen OPcache (geteilter Speicher zwischen Workern) und, ab PHP 8.5, die Backtraces bei Fatal Errors.
Entdeckt wurde das Ganze weitgehend unabhängig voneinander von Calif und Wiz, beide mit KI-Unterstützung bei der Analyse. Eine Teilmenge der Fehler soll sogar schon 2024 einem PHP-Entwickler aufgefallen sein, damals ohne Exploit und ohne Einigung auf einen Fix. Die Spur reicht im Code bis PHP 5.4 zurück, auch wenn nicht jede alte Version einzeln getestet wurde. Die offiziellen Details stehen in den PHP-Advisories GHSA-w8hw-w9fx-j79w und GHSA-6wmf-4rv5-p3rp.
Wie gefährlich ist das wirklich?
Hier gehen die Einschätzungen auseinander. CrowdStrike beschreibt, dass eine einzelne anonyme Anfrage auf einem mod_php-Worker Befehle ausführen kann. Sansec dagegen fand heraus, dass viele öffentliche Proof-of-Concepts gegen eine Standard-Installation gar nicht laufen und oft eine zusätzliche Local-File-Inclusion-Lücke in der Anwendung brauchen. Die Analyse von CrowdStrike verweist außerdem darauf, dass der Speicherlimit-Pfad nur greift, wenn memory_limit deutlich kleiner als das Vierfache von post_max_size ist. Mit den Standardwerten (8 MB und 128 MB) ist er demnach nicht erreichbar. Das hilft dir allerdings nur, wenn du die Werte nie angefasst hast. Auf Shared Hosting lässt sich post_max_size pro Verzeichnis setzen.
Belegt ist: Amazon hat schon am 17. Oktober, vier Tage vor der Veröffentlichung, einen Angriffsversuch in seinen Honeypots gesehen. Cloudflare meldete ebenfalls frühe Angriffe. Mein Fazit zur Lage: nicht in Panik verfallen, aber auch nicht darauf wetten, dass dein Setup “schon irgendwie sicher” ist. Code läuft im Kontext des Webserver-Benutzers, also nicht automatisch als root. Aus Config-Dateien kommen trotzdem Datenbankzugänge und API-Keys heraus.
Bist du betroffen?
Betroffen sind alle PHP-Linien unterhalb dieser Stände:
| PHP-Linie | Verwundbar | Gepatcht ab |
|---|---|---|
| 8.2 | vor 8.2.35 | 8.2.35 |
| 8.3 | vor 8.3.36 | 8.3.36 |
| 8.4 | vor 8.4.27 | 8.4.27 |
| 8.5 | vor 8.5.12 | 8.5.12 |
| 7.4, 8.0, 8.1 und älter | immer | nur Backports (siehe unten) |
Die Linien 7.4, 8.0 und 8.1 sind upstream am Ende ihrer Lebenszeit. Das PHP-Team hat dafür Source-Patches veröffentlicht, offizielle Binärpakete gibt es nicht. Wer so alt unterwegs ist, braucht ein Distributions-Paket mit Backport oder muss auf eine gepflegte Linie wechseln.
Welches PHP bedient wirklich deine Seite?
Der häufigste Denkfehler: php -v zeigt nur die CLI-Version. Der Webserver kann ein ganz anderes PHP nutzen. Prüf deshalb den tatsächlichen Dienst:
php -v
php-fpm8.3 -v # Versionsnummer an deine Installation anpassen
apache2ctl -M | grep -i php
systemctl list-units --type=service | grep -i phpBei Containern zählt die Version im laufenden Container, nicht der Tag deines Basis-Images:
docker exec <container> php -vZwei Stolpersteine: Bei Plesk reicht es nicht, die Website-Handler zu aktualisieren, die Panel-Oberfläche läuft auf einer eigenen PHP-Runtime. Und bei Admin-Tools wie phpMyAdmin oder Webmail auf demselben Server läuft oft ein anderes PHP als bei der Hauptseite.
Backports richtig lesen
Debian, Ubuntu, RHEL und Co. patchen oft, ohne die Upstream-Nummer zu ändern. Ein 8.1.2 kann also gepatcht sein. Entscheidend ist der Changelog-Eintrag mit der CVE-ID:
# Debian/Ubuntu
zgrep -il "CVE-2026-109618" /usr/share/doc/php*/changelog.Debian.gz
# RHEL, AlmaLinux, Rocky
rpm -q --changelog php | grep -i CVE-2026-109618Kein Treffer heißt: kein Backport mit dieser CVE-Referenz, also nicht als gepatcht ansehen. Das offizielle Docker-Image php bekommt für 8.1 und älter übrigens keinen Fix.
Fix: PHP aktualisieren
Der einzige vollständige Weg ist das Update. Unter Debian/Ubuntu mit Paketquelle sieht das so aus:
sudo apt update && sudo apt install --only-upgrade 'php*'
sudo systemctl restart php8.3-fpm apache2Unter RHEL-Derivaten entsprechend:
sudo dnf update 'php*'
sudo systemctl restart php-fpm httpdDer Neustart gehört dazu, sonst läuft der alte Prozess im Speicher weiter. Bei Docker reicht ein docker pull nicht, der Container muss neu erstellt werden:
docker compose pull && docker compose up -d --force-recreateNutzt du das Repo von Remi, schau vorher nach: Es gab zum Veröffentlichungszeitpunkt noch keine Updates, weshalb die Betreuer zu Distributionspaketen oder einem Selbstbau geraten haben. Auf cPanel- und CloudLinux-Systemen liegen Backports bereit.
Sofort-Mitigation, wenn du nicht updaten kannst
Eine vollständige Entwarnung gibt es durch keine dieser Maßnahmen, sie verkleinern nur die Angriffsfläche. Jede Änderung braucht einen Neustart der Worker, ini_set() oder .user.ini reichen nicht.
; php.ini oder FPM-Konfiguration
session.upload_progress.enabled = 0
; nur PHP 8.5:
fatal_error_backtraces = 0Das schaltet die Session-Fortschrittsanzeige ab, die selten wirklich gebraucht wird, und schließt den Backtrace-Pfad. Den OPcache-Pfad decken die beiden Zeilen nicht ab. Weitere Bausteine:
- PHP-FPM:
pm.max_requests = 1bricht die Voraussetzung auf, dass ein späterer Request auf demselben Worker landet. Das kostet spürbar Performance. - Upload-Größen:
post_max_sizeklein halten (8 MB ohne Uploads) und am Reverse Proxy Limits für Request-Größe und Multipart-Felder setzen. - memory_limit = -1: wirkt gegen den OOM-Auslöser, entfernt aber den Schutz vor Speicherfressern. Nur kurzfristig und mit Monitoring, danach zurücksetzen.
- Multipart sperren: Wenn deine Seite keine Uploads braucht, kannst du
multipart/form-dataam Webserver mit 403 ablehnen. Formulare mit Dateianhang gehen dann natürlich kaputt, also testen. - WAF: Cloudflare hat Regeln für bekannte Angriffsmuster ausgerollt. Verlass dich nicht allein darauf, das ist eine zusätzliche Schicht.
Bei Systemen, die du weder patchen noch absichern kannst, empfiehlt das britische NCSC, sie vom Netz zu nehmen. Bei einem Hobby-Projekt ist das oft die ehrlichste Lösung.
Ausnutzung erkennen
Eine ernüchternde Nachricht: Im Anwendungs-Log siehst du nichts, der Server antwortet mit HTTP 200. Der einzige serverseitige Hinweis ist ein Eintrag wie PHP Fatal error: Allowed memory size of ... exhausted ... in Unknown on line 0. Das “Unknown on line 0” verrät, dass der Fehler vor dem ersten Script auftrat. Häufen sich solche Zeilen, schau genauer hin.
Weitere Anhaltspunkte: ungewöhnlich große Multipart-Requests, aufgeblähte PHPSESSID-Werte, Worker-Abstürze und, im Nachgang, Kindprozesse des Webservers (sh, curl, wget) sowie neue .php-Dateien in Upload- oder Cache-Verzeichnissen. Beim Thema GitHub-”Exploits” gilt: Finger weg. Mehrere vermeintliche PoCs sind Fakes mit Schadcode im Gepäck. Wenn du testen willst, nimm den Scanner von Searchlight Cyber oder prüf Version und Konfiguration, statt fremde Skripte auf Produktivsystemen auszuführen.
Fazit
PHP2Shell ist ein Update, das du nicht aufschieben solltest, auch wenn die Exploitability je nach Konfiguration schwankt. Die Lücke liegt unterhalb deiner Anwendung, und ältere Linien unter 8.2 bekommen keinen offiziellen Fix mehr. Mein Rat: Erst inventarisieren, welches PHP wirklich Webanfragen bedient, dann aktualisieren, Worker neu starten und die Version im laufenden Prozess gegenprüfen. Wo das heute nicht klappt, session.upload_progress.enabled = 0 setzen und die Upload-Limits straffen.
Häufige Fragen
Schützt mich PHP-FPM statt mod_php? ▾
Nur teilweise. Der Startpfad von FPM verhindert einen der Out-of-Memory-Wege, doch für den Session-Pfad wurde ein funktionierender Angriff auch gegen FPM gezeigt, sofern die Anwendung passende Operationen anbietet. Ein Wechsel von mod_php zu FPM ersetzt das Update also nicht.
Reicht session.upload_progress.enabled = 0 aus? ▾
Nein. Das schließt den prominentesten Auslöser, aber nicht den OPcache-Pfad und nicht jede Fatal-Error-Klasse. Betrachte es als Übergangslösung bis zum Update.
Woran merke ich, dass mein Hoster schon gepatcht hat? ▾
Frag nicht nach der Versionsnummer, sondern nach einem Backport mit CVE-Bezug. Auf Systemen mit Shell-Zugriff hilft der Changelog-Check oben. Bei Managed Hosting bleibt dir die Support-Anfrage, am besten mit konkreter Nennung beider CVE-IDs.
Mein WordPress ist aktuell. Bin ich damit raus? ▾
Nein. Die Lücke liegt in PHP, Plugin- und Core-Updates ändern daran nichts. WordPress, Joomla, Drupal und Nextcloud wurden als Demo-Ziele genannt, weil sie PHP nutzen, nicht weil sie Fehler hätten.
Warum hilft ein größeres memory_limit gegen den Angriff, wird aber trotzdem nicht empfohlen? ▾
Ein Angriff über Speichererschöpfung läuft ins Leere, wenn die Grenze nie erreicht wird. Dafür kann ein einzelner Request dann den gesamten Arbeitsspeicher beanspruchen und den Server lahmlegen. Du tauschst eine Lücke gegen eine andere, deshalb nur kurz und mit Überwachung.