PHP2Shell: Kritische Sicherheitslücke in PHP – und warum wir auch unsere Docker-Container nicht vergessen dürfen

Kaum vergeht eine Woche, ohne dass eine neue Sicherheitslücke für Aufmerksamkeit in der IT-Welt sorgt. Dieses Mal trifft es mit PHP eine der am weitesten verbreiteten Technologien im Web.

Unter dem Namen PHP2Shell wurden am 21. Oktober 2026 zwei kritische Schwachstellen veröffentlicht, die es Angreifern unter bestimmten Voraussetzungen ermöglichen, ohne vorherige Authentifizierung eigenen Code auf betroffenen Servern auszuführen.

Das ist natürlich erst einmal keine erfreuliche Nachricht. Gleichzeitig haben mich die vergangenen Stunden aber auch positiv überrascht. Denn sowohl die PHP-Entwickler selbst als auch zahlreiche Open-Source-Projekte und Hersteller haben in beeindruckender Geschwindigkeit reagiert.

Ich möchte daher nicht nur kurz auf die Sicherheitslücken eingehen, sondern insbesondere zeigen, warum sich ein Blick auf die eigene Infrastruktur – einschließlich aller Docker-Container – lohnt. Und warum die schnelle Reaktion vieler Entwickler durchaus einmal ein ausdrückliches Lob verdient.

Was steckt hinter PHP2Shell?

PHP2Shell bezeichnet gleich zwei Sicherheitslücken im Kern des PHP-Interpreters:

  • CVE-2026-109618: Remote Code Execution durch fehlerhafte Speicherbehandlung bei Out-of-Memory-Situationen
  • CVE-2026-109619: Remote Code Execution durch die Weiterverwendung von Speicherzuständen aus vorherigen Anfragen

Beide Schwachstellen wurden mit einem CVSS-v4.0-Score von 9,2 (Critical) bewertet.

Vereinfacht gesagt können speziell präparierte HTTP-Anfragen dazu führen, dass PHP intern mit Speicherbereichen arbeitet, die sich in einem ungültigen Zustand befinden oder bereits freigegeben wurden.

Im schlimmsten Fall können Angreifer dadurch eigenen Code mit den Berechtigungen des jeweiligen PHP-Prozesses ausführen.

Das Besondere und gleichzeitig Gefährliche daran: Die Schwachstellen befinden sich nicht in einer bestimmten Webanwendung, sondern direkt in PHP selbst.

Es spielt somit zunächst keine Rolle, ob beispielsweise WordPress, phpIPAM, eine selbst entwickelte Anwendung oder eine andere PHP-basierte Lösung eingesetzt wird.

Besonders kritisch sind Installationen, bei denen PHP direkt als Apache-Modul (mod_php) ausgeführt wird. Hier konnte eine Ausnutzung bereits vor der eigentlichen Ausführung des Anwendungscodes demonstriert werden.

Aber auch PHP-FPM und andere Betriebsarten müssen berücksichtigt werden.

Wichtig ist dabei: Eine besonders abgesicherte Anwendung, ein vorgeschalteter Reverse Proxy oder eine vorgeschaltete Authentifizierung machen einen verwundbaren PHP-Interpreter nicht automatisch sicher.

Welche PHP-Versionen sind betroffen?

Bereits am 21. Oktober 2026 hat das PHP-Projekt Sicherheitsupdates bereitgestellt.

PHP-VersionAbgesicherte Version
PHP 8.58.5.12 oder neuer
PHP 8.48.4.27 oder neuer
PHP 8.38.3.36 oder neuer
PHP 8.28.2.35 oder neuer
PHP 8.1 und älterEnd of Life – Hersteller-Backports prüfen oder aktualisieren

Bei älteren PHP-Versionen ist Vorsicht geboten. Diese erhalten vom offiziellen PHP-Projekt keine regulären Sicherheitsreleases mehr. Einige Linux-Distributionen und Hersteller bieten allerdings weiterhin Sicherheitsupdates durch sogenannte Backports an.

Dabei werden Sicherheitskorrekturen in eine ältere PHP-Version übernommen, ohne zwangsläufig deren Versionsnummer zu verändern.

Die bloße Versionsnummer ist daher nicht in jedem Fall ein eindeutiger Nachweis für den tatsächlichen Patchstand.

Wie kann ich meine eingesetzte PHP-Version prüfen?

Bevor wir uns Gedanken über Updates machen, müssen wir zunächst wissen, wo überhaupt PHP eingesetzt wird.

Und genau das ist in gewachsenen IT-Infrastrukturen manchmal gar nicht so einfach.

PHP unter Linux prüfen

Auf einem klassischen Linux-System lässt sich die PHP-Version zunächst über die Konsole ermitteln:

php -v

Die Ausgabe zeigt beispielsweise:

PHP 8.3.36 (cli)

Zusätzlich empfiehlt es sich, installierte PHP-Pakete zu überprüfen.

Unter Debian beziehungsweise Ubuntu:

dpkg -l 'php*' | grep '^ii'

Unter RHEL-basierten Distributionen:

rpm -qa | grep -E '^php'

Wichtig: Die PHP-Version der Kommandozeile muss nicht zwingend mit der Version übereinstimmen, die der Webserver verwendet.

Gerade wenn mehrere PHP-Versionen oder unterschiedliche PHP-FPM-Pools eingesetzt werden, sollte deshalb auch die tatsächliche Konfiguration der jeweiligen Webanwendung betrachtet werden.

Bei distributionsseitig gepatchten Paketen ist außerdem der Sicherheitsstatus des Paketbetreibers relevant.

PHP unter Windows prüfen

Auch unter Windows kann die Version direkt über die Eingabeaufforderung oder PowerShell geprüft werden:

php -v

Um herauszufinden, welche PHP-Installation über den Suchpfad erreichbar ist:

where.exe php

Falls PHP nicht im Suchpfad hinterlegt ist, muss die entsprechende php.exe direkt im Installationsverzeichnis aufgerufen werden.

Bei IIS-Umgebungen sollte zusätzlich geprüft werden, welche PHP-Version tatsächlich über FastCGI beziehungsweise den jeweiligen Handler verwendet wird.

PHP unter Plesk prüfen

Wer einen Webserver mit Plesk betreibt, hat möglicherweise mehrere PHP-Versionen parallel installiert.

Die verwendeten Versionen lassen sich in Plesk unter Tools & Einstellungen → PHP-Einstellungen beziehungsweise in den PHP-Einstellungen der einzelnen Domains einsehen.

Alternativ kann auf einem Plesk-Linux-Server folgender Befehl verwendet werden:

plesk bin php_handler --list

Eine konkrete PHP-Version lässt sich beispielsweise so prüfen:

/opt/plesk/php/8.3/bin/php -v

Interessant ist hier auch die Reaktion von Plesk auf PHP2Shell: Bereits kurz nach der Veröffentlichung standen aktualisierte PHP-Pakete bereit.

Für ältere PHP-Versionen wie 7.4, 8.0 und 8.1 hat Plesk unter Linux sogar zusätzliche Sicherheitskorrekturen veröffentlicht. Die Versionsnummer bleibt dabei unverändert. Entscheidend ist das Build-Datum vom 21. Oktober 2026.

Auch die von Plesk selbst verwendete PHP-Laufzeit wurde durch entsprechende Plesk-Updates abgesichert.

Und was ist eigentlich mit unseren Docker-Containern?

Kommen wir zu dem Punkt, der in meinen Augen bei solchen Sicherheitsmeldungen häufig unterschätzt wird.

Docker!

Container sind inzwischen aus vielen IT-Infrastrukturen nicht mehr wegzudenken. Auch in meinem eigenen Homelab betreibe ich zahlreiche Anwendungen in Docker-Containern.

Das ist komfortabel, flexibel und macht die Bereitstellung vieler Dienste erstaunlich einfach.

Allerdings entsteht dabei manchmal ein trügerisches Sicherheitsgefühl.

Ein Docker-Container ist schließlich kein automatisch sicherer Raum, in dem Sicherheitslücken keine Rolle mehr spielen.

Ganz im Gegenteil!

Viele Anwendungen bringen ihre komplette Laufzeitumgebung bereits innerhalb des Container-Images mit. Dazu gehören beispielsweise PHP, Webserver, Bibliotheken und weitere Abhängigkeiten.

Das bedeutet konkret:

Nur weil mein Docker-Host vollständig aktualisiert ist, müssen meine Docker-Container noch lange nicht auf einem aktuellen Stand sein.

Ein Container kann beispielsweise weiterhin eine verwundbare PHP-Version enthalten, obwohl das darunterliegende Linux-System längst alle verfügbaren Updates installiert hat.

Und selbst ein Neustart des Containers löst dieses Problem nicht. Solange das verwendete Container-Image unverändert bleibt, bleibt auch die enthaltene PHP-Version unverändert.

Wie finde ich heraus, welche Container PHP verwenden?

Zunächst können alle laufenden Container angezeigt werden:

docker ps --format "table {{.Names}}\t{{.Image}}"

Anschließend lässt sich die PHP-Version eines einzelnen Containers beispielsweise mit folgendem Befehl prüfen:

docker exec CONTAINERNAME php -v

Bei PHP-FPM-basierten Images kann alternativ folgender Befehl funktionieren:

docker exec CONTAINERNAME php-fpm -v

Allerdings bringt nicht jeder Container eine Shell oder die entsprechenden PHP-Binaries unter diesen Namen mit.

Und genau hier wird die Prüfung etwas aufwendiger.

Mein kleines Docker-Prüfskript

Da ich selbst eine größere Anzahl an Docker-Containern betreibe, wollte ich nicht jeden einzelnen Container manuell überprüfen.

Also habe ich mir ein kleines Bash-Skript erstellt, das die laufenden Docker-Container durchgeht und versucht, vorhandene PHP-Installationen beziehungsweise deren Versionsstände zu ermitteln.

Die Ergebnisse werden übersichtlich ausgegeben, sodass sich mögliche Kandidaten für eine weitere Überprüfung schnell identifizieren lassen.

Dabei ist eine Unterscheidung besonders wichtig: Wenn sich ein Container nicht untersuchen lässt, beispielsweise weil er keine Shell mitbringt, darf daraus nicht automatisch geschlossen werden, dass PHP vorhanden oder nicht vorhanden ist.

Ein solcher Container muss separat bewertet werden.

Das Skript ist damit kein vollwertiger Vulnerability-Scanner, aber ein praktisches Hilfsmittel, um sich schnell einen ersten Überblick über die eigene Docker-Umgebung zu verschaffen.

Das Skript ist damit kein vollwertiger Vulnerability-Scanner, aber ein praktisches Hilfsmittel, um sich schnell einen ersten Überblick über die eigene Docker-Umgebung zu verschaffen.

#!/usr/bin/env bash

printf "%-40s %-10s %s\n" "CONTAINER" "PHP" "DETAILS"
printf '%s\n' "------------------------------------------------------------------------------------------"

while IFS= read -r container; do
    name=$(docker inspect --format '{{.Name}}' "$container" 2>/dev/null)
    name=${name#/}

    status="UNKNOWN"
    details="Unable to inspect"

    # Try PHP directly (works even without a shell).
    result=$(docker exec "$container" php -v 2>/dev/null)
    rc=$?

    if [ "$rc" -eq 0 ] && [ -n "$result" ]; then
        status="YES"
        details=$(printf '%s\n' "$result" | head -n 1)
    else
        # Check PHP-FPM binaries directly.
        for binary in php-fpm php-fpm8.5 php-fpm8.4 php-fpm8.3 php-fpm8.2 php-fpm8.1 php-fpm7.4; do
            result=$(docker exec "$container" "$binary" -v 2>/dev/null)
            if [ "$?" -eq 0 ] && [ -n "$result" ]; then
                status="YES"
                details=$(printf '%s\n' "$result" | head -n 1)
                break
            fi
        done
    fi

    if [ "$status" != "YES" ]; then
        # A successful shell execution can establish whether PHP
        # is available in the container's normal executable paths.
        for shell in sh /bin/sh /bin/bash; do
            result=$(docker exec "$container" "$shell" -c '
                for cmd in php php-fpm php-fpm8.5 php-fpm8.4 php-fpm8.3 php-fpm8.2 php-fpm8.1 php-fpm7.4; do
                    if command -v "$cmd" >/dev/null 2>&1; then
                        "$cmd" -v 2>&1 | head -n 1
                        exit 0
                    fi
                done
                exit 10
            ' 2>/dev/null)
            rc=$?

            if [ "$rc" -eq 0 ]; then
                status="YES"
                details=$(printf '%s\n' "$result" | head -n 1)
                break
            elif [ "$rc" -eq 10 ]; then
                status="NO"
                details="Not detected"
                break
            fi
        done
    fi

    if [ "$status" = "UNKNOWN" ]; then
        details="Unable to verify (no shell or execution failed)"
    fi

    printf "%-40s %-10s %s\n" "$name" "$status" "$details"

done < <(docker ps -q)

Hier die Ausgabe meiner Docker-Container:

Docker-Images müssen tatsächlich aktualisiert werden

Sobald ein Hersteller oder Entwickler ein aktualisiertes Container-Image veröffentlicht, muss dieses natürlich auch verwendet werden.

Bei Docker Compose kann das beispielsweise so aussehen:

docker compose pull
docker compose up -d

Damit werden neue Images für die definierten Dienste abgerufen und Container bei Bedarf neu erstellt.

Bei selbst erstellten Images ist gegebenenfalls zusätzlich ein Rebuild mit einer aktualisierten Basis erforderlich.

Wichtig ist außerdem, nach dem Update zu überprüfen, ob wirklich eine abgesicherte PHP-Version beziehungsweise ein entsprechend gepatchtes Hersteller-Image eingesetzt wird.

Ein erfolgreich abgeschlossener Image-Download bedeutet schließlich noch nicht automatisch, dass die Sicherheitslücke geschlossen wurde.

Ein großes Lob an die Open-Source-Community!

Bei aller berechtigten Sorge über kritische Sicherheitslücken möchte ich an dieser Stelle auch einmal etwas Positives hervorheben.

Ich finde es wirklich bemerkenswert, wie schnell viele Open-Source-Entwickler auf PHP2Shell reagiert haben.

In meiner eigenen Umgebung konnte ich beobachten, dass für zahlreiche der von mir eingesetzten Container bereits innerhalb weniger Stunden nach Bekanntwerden der Schwachstellen aktualisierte Images beziehungsweise entsprechende Patches bereitgestellt wurden.

Zwei Beispiele, welche ich selbst einsetze:

phpIPAM, eine Open-Source-Lösung für das IP-Adressmanagement, und WallOS, mit dem sich Abonnements und wiederkehrende Kosten verwalten lassen. Beide nutzen PHP im Backend.

Für beide Projekte konnte ich innerhalb kürzester Zeit entsprechende Updates feststellen.

Das ist alles andere als selbstverständlich.

Hinter vielen Open-Source-Projekten stehen schließlich keine riesigen Entwicklungsabteilungen mit eigenen Security-Response-Teams.

Häufig sind es einzelne Entwickler oder kleine Teams, die solche Projekte mit viel Leidenschaft pflegen – nicht selten neben ihrer regulären beruflichen Tätigkeit.

Umso beeindruckender finde ich es, wenn auf eine kritische Sicherheitsmeldung so schnell reagiert wird.

Natürlich gehört die Behebung von Sicherheitslücken grundsätzlich zu den Aufgaben einer verantwortungsvollen Softwareentwicklung.

Aber man sollte dabei nicht vergessen, wie viel Arbeit hinter einem vermeintlich kleinen Update stecken kann: Abhängigkeiten aktualisieren, Kompatibilität prüfen, neue Container-Images bauen, testen und schließlich veröffentlichen.

Und das teilweise innerhalb weniger Stunden!

Genau dieses Engagement zeigt für mich eine der großen Stärken der Open-Source-Community.

Es zeigt, dass sich zahlreiche Entwickler ihrer Verantwortung gegenüber den Anwendern und Betreibern ihrer Software bewusst sind.

Auch Plesk hat schnell reagiert

Neben meinen Docker-Containern betreibe ich auch einen vServer, auf dem Plesk zum Einsatz kommt.

Auch hier war die Reaktion erfreulich schnell.

Innerhalb weniger Stunden standen entsprechende Sicherheitsupdates zur Verfügung, mit denen sich die betroffenen PHP-Komponenten aktualisieren ließen.

Für mich zeigt das sehr schön, wie wichtig ein funktionierender Security- und Updateprozess sowohl bei kommerzieller Software als auch bei Open-Source-Projekten ist.

Wenn Sicherheitslücken von dieser Tragweite bekannt werden, zählt schlichtweg jede Stunde.

Entwickler liefern die Patches – einspielen müssen wir sie selbst

So erfreulich die schnellen Reaktionen der Entwickler und Hersteller auch sind, eine Sache darf dabei nicht vergessen werden:

Ein bereitgestelltes Sicherheitsupdate schützt noch kein einziges System, solange es nicht installiert wird.

Und hier liegt die Verantwortung bei uns als Administratoren, Betreibern und Anwendern.

Wir müssen wissen, welche Software wir einsetzen, welche Abhängigkeiten vorhanden sind und wie sich diese zuverlässig aktualisieren lassen.

Gerade bei Docker ist es schnell passiert, dass ein Container über Monate zuverlässig seinen Dienst verrichtet und dabei völlig aus dem Blickfeld verschwindet.

Nach dem Motto: Läuft doch alles, warum sollte ich etwas ändern?

Das funktioniert allerdings nur so lange gut, bis eine kritische Sicherheitslücke bekannt wird.

Deshalb gehört für mich zu einem verantwortungsvollen Betrieb nicht nur die eigentliche Bereitstellung einer Anwendung, sondern auch deren kontinuierliche Pflege.

Regelmäßige Updates, ein Überblick über die eingesetzten Container-Images, das Beobachten von Sicherheitsmeldungen und eine gelegentliche Überprüfung der tatsächlich verwendeten Softwareversionen sollten selbstverständlich sein.

Und bei kritischen Sicherheitslücken wie PHP2Shell gilt: Nicht irgendwann beim nächsten geplanten Wartungsfenster reagieren, sondern das Risiko kurzfristig bewerten und notwendige Updates priorisiert einspielen.

Weiterführende Informationen

Schreibe einen Kommentar