LW IT Solutions logo LW IT Solutions logo LW IT Solutions
« Blog-Übersicht /Web Entwicklung / PHP2Shell: Was jetzt schützt und warum ungepatchte...
Diesen Artikel in anderen Sprachen lesen:

PHP2Shell: Was jetzt schützt und warum ungepatchte Websites bleiben

PHP2Shell: Was jetzt schützt und warum ungepatchte Websites bleiben

Management Summary

PHP2Shell bezeichnet kritische Fehler in PHP, der Software hinter vielen Websites. Schutz entsteht erst, wenn die jeweilige Website tatsächlich mit korrigierter Software läuft. Ein installiertes Update oder eine funktionierende Anmeldung belegen das allein nicht. Vergessene Installationen und unklare Wartungszuständigkeiten können Lücken offenlassen. Der Beitrag verbindet Bestandsaufnahme, geprüfte Aktualisierung und Untersuchung früherer Angriffe. Ein Update beseitigt keine bereits vorhandenen Einbruchsspuren.

Inhalt
  1. Neue Lage: Angriffsversuche schon vor der Veröffentlichung
  2. Was hinter PHP2Shell steckt
  3. Welche Updates schützen?
  4. Vom Paketupdate zum geschützten Betrieb
  5. Was ohne Update passieren kann
  6. Werden die Updates wirklich überall installiert?
  7. Wie viele Websites bleiben bedroht?
  8. Linux-Praxis: zuerst die tatsächlich verwendete Installation erfassen
  9. PHP 8.4 über APT aktualisieren
  10. PHP 8.5 über APT aktualisieren
  11. Warum „PHP aktualisiert“ noch nicht „PHP aktiv korrigiert“ bedeutet
  12. PHP 7.4: ein Sicherheits-Backport statt unveränderter 7.4.33
  13. Angriffsspuren: mehrere Signale zusammen betrachten
  14. PHP2Shell in den Logs erkennen: Verdacht ist noch kein Nachweis
  15. Erste Log-Abfragen unter Linux
  16. Logging gezielt verbessern, ohne Formularinhalte zu sammeln
  17. Schutz während eines noch offenen Updates
  18. Bei konkreten Einbruchsspuren: Patch und Vorfall getrennt behandeln
  19. Fragen und Antworten
  20. Quellen

Stand: 25. Oktober 2026. PHP führt auf dem Server den Programmcode vieler Websites aus, etwa von WordPress. Zwei kritische Fehler in PHP können unter bestimmten Bedingungen fremde Befehle ohne Anmeldung ermöglichen. Die Bezeichnung dafür lautet PHP2Shell. Updates für beide Fehler liegen seit dem 21. Oktober vor. Entscheidend ist, ob die Website bereits das korrigierte PHP verwendet. Der Hinweis vom 23. Oktober zu einem weiteren Session-Fehler ist unten getrennt erklärt. [1] [6]

Neue Lage: Angriffsversuche schon vor der Veröffentlichung

AWS beobachtete am 17. Oktober 2026 einen PHP2Shell-Angriffsversuch, noch vor der öffentlichen Bekanntgabe. Die Beobachtung stammt aus MadPot: absichtlich erreichbaren Ködersystemen, die Angriffe aufzeichnen. Bei weiteren Versuchen blieb offen, ob ein echter Zielserver erfolgreich angegriffen worden wäre. Daraus folgt keine weltweite Opferzahl. Bei betroffenen Installationen reicht eine Untersuchung ab dem Veröffentlichungstag deshalb nicht aus. AWS: eigene Beobachtungen und Grenzen

Was hinter PHP2Shell steckt

Die Fehler tragen die Kennungen CVE-2026-109618 und CVE-2026-109619. CVE-Nummern ordnen Sicherheitslücken eindeutig zu. Beim ersten Fehler kann PHP nach Speichermangel unvollständig angelegte Daten als gültig behandeln. Beim zweiten bleiben Verweise auf bereits freigegebenen Speicher zurück; eine spätere Anfrage kann diese Verweise verwenden. Beide Fehler liegen in PHP selbst. [3] [4]

Auch alte PHP-Reihen gehören zur Prüfung. cPanel nennt betroffene Versionen ab PHP 5 und führt korrigierte Ausgaben eigener Pakete auf. Der Wechsel von PHP 7 auf irgendeine PHP-8-Version reicht daher nicht als Nachweis. Benötigt wird die konkrete Paketversion mit bestätigter Behebung beider Fehler. [7]

Bei Apache mit mod_php läuft PHP direkt im Webserver. Dort ist ein Angriff bestätigt, der schon vor dem Code der Website greift. Bei PHP-FPM bearbeiten getrennte PHP-Prozesse die Anfragen; solche Prozesse heißen Worker und werden in Pools zusammengefasst. Auch für FPM meldet die PHP Foundation bestätigte Codeausführung, abhängig von der Anwendung. Eine WordPress-Anmeldung schützt daher nicht zuverlässig vor diesen PHP-Fehlern. [2]

Welche Updates schützen?

Die offiziellen Updates für die beiden Fehler sind 8.2.35, 8.3.36, 8.4.27 und 8.5.12. Innerhalb der jeweiligen Reihe ist dieser oder ein neuerer korrigierter Stand nötig. PHP 8.1 und ältere Reihen erhalten keine regulären PHP-Veröffentlichungen mehr. Für 7.4, 8.0 und 8.1 gibt es ausnahmsweise kleine Quellcode-Korrekturen. Anbieter können die Korrekturen in ältere Pakete übernehmen; das heißt Backport. Daraus entsteht kein allgemeiner neuer Support für alte PHP-Reihen. [1]

Bei einem Backport kann die ursprüngliche PHP-Versionsnummer gleich bleiben. Die zusätzliche Paketrevision kennzeichnet dann die geänderte Anbieterausgabe. Deshalb zählen die vollständige Paketbezeichnung und die Bestätigung für beide CVEs. Weder eine alte Basisnummer noch die Angabe „PHP 8“ reicht allein zur Bewertung. [7]

Zusätzlicher Hinweis vom 23. Oktober: Session-Konfiguration

PHP beschreibt unter CVE-2026-115560 einen weiteren, ungewöhnlichen Fall: Die Einstellung session.serialize_handler verwendet php_binary oder php_serialize, die Anwendung wechselt mit ini_set() vor session_start() auf php, und Upload-Fortschritt bleibt aktiviert. Diese Namen bezeichnen unterschiedliche Speicherformate für Sitzungsdaten. PHP empfiehlt bis zur nächsten regulären Fehlerkorrektur session.upload_progress.enabled=0. Anwendungen ohne einen solchen Formatwechsel zur Laufzeit können die Funktion laut PHP aktiviert lassen. Dieser zusätzliche Hinweis gilt neben den beiden Updates vom 21. Oktober; eine vollständige Meldung ist für die nächste Veröffentlichung angekündigt. PHP: Session-Hinweis vom 23. Oktober 2026

Vier Prüfschritte: Bestand erfassen, beide Lücken patchen, laufende Prozesse erneuern und den Webbetrieb prüfen
Ein Update ist erst im laufenden Webbetrieb wirksam.

Vom Paketupdate zum geschützten Betrieb

  1. Bestand erfassen: Domains, PHP-Pools, Container, alte Testinstallationen und eingebettete Verwaltungsoberflächen gehören zur Inventur.
  2. Korrektur belegen: Für jede Laufzeit sind Paketquelle, Revision und Behebung beider CVEs zu dokumentieren.
  3. Laufende Instanzen erneuern: PHP-Worker müssen den neuen Stand laden. Ein Container startet mit einem vorbereiteten Paket aus Programm und Laufzeit, dem Image. Für selbst gebaute Container ist ein neues Image mit korrigiertem PHP nötig; anschließend müssen neue Container daraus starten. Ein Update des umgebenden Servers ändert ein vorhandenes Image nicht. [8]
  4. Webbetrieb kontrollieren: Die Kommandozeile kann eine andere PHP-Installation verwenden als die Website. Erst die Zuordnung der Domain zur tatsächlich laufenden Version samt Funktionsprüfung schließt die Kontrolle ab.

Falls ein Patch kurzfristig unmöglich bleibt, empfiehlt ENISA die Prüfung einer Isolation öffentlich erreichbarer Anwendungen. Eine statische Wartungsseite vor PHP kann dabei den Betrieb sichtbar unterbrechen, ohne weitere Anfragen an die gefährdete Laufzeit weiterzugeben. Ein Wartungsplugin innerhalb derselben PHP-Anwendung erreicht dieses Ziel nicht zuverlässig. [5]

Die vorübergehenden Einstellungen schließen nur bestimmte Angriffswege. session.upload_progress.enabled=0 schaltet die Speicherung des Upload-Fortschritts in Sitzungsdaten ab. Das blockiert bestimmte Session-Angriffswege, ersetzt aber nicht die beiden Updates. Auch memory_limit=-1 behebt die Fehler nicht vollständig und kann Ausfälle durch hohen Speicherverbrauch begünstigen. Betriebssystemgrenzen über RLIMIT_AS oder RLIMIT_DATA sind dafür laut PHP ungeeignet: Eine fehlgeschlagene Speicherzuteilung kann den verwundbaren Ablauf weiterhin erreichen. Auch cgroups, mit denen Linux den Ressourcenverbrauch von Prozessgruppen begrenzt, reparieren den Fehler nicht vollständig. [3] [4]

Was ohne Update passieren kann

Der Ausgangspunkt ist Codeausführung mit den Rechten des Webprozesses, nicht automatisch voller Administratorzugriff (root). Daraus ergeben sich abhängig von Berechtigungen und erreichbaren Geheimnissen erhebliche Folgerisiken: ausgelesene Datenbankzugänge, gestohlene Kundendaten, veränderte Inhalte, eingeschleuste Schadsoftware oder missbrauchte Schnittstellenschlüssel. Weitere Angriffe auf interne Dienste sind möglich, sofern Netzwege und Rechte solche Zugriffe zulassen. [3]

Für einen Shop kann bereits eine veränderte Zahlungsseite schwerer wiegen als ein sichtbarer Ausfall. Dazu kommen Untersuchung, Wiederherstellung, Ausfallzeiten und Vertrauensverlust. Ein späterer Patch entfernt keine bereits eingerichtete Hintertür. Bei konkreten Einbruchsspuren gehören Isolation, Beweissicherung, Prüfung der Zugänge und Wiederherstellung aus einem vertrauenswürdigen Stand zur Reaktion.

Werden die Updates wirklich überall installiert?

Einschätzung: Ein schneller erster Rückgang der gefährdeten Installationen ist plausibel, ein vollständiger Abschluss innerhalb weniger Tage kaum. Zentral betreute Plattformen können viele Websites gleichzeitig korrigieren. Bei individuellen Servern hängt das Ergebnis an Zuständigkeiten, Paketverfügbarkeit, Kompatibilität und kontrollierten Neustarts. Google Cloud unterscheidet ausdrücklich zwischen automatisch aktualisierten Laufzeiten und Diensten, die mit einem korrigierten Image erneut gestartet werden müssen. [8]

Besonders hartnäckig dürfte der Restbestand werden: aufgegebene Projekte, alte Agenturinstallationen, Container ohne Wartungsprozess und Anwendungen mit Abhängigkeit von abgekündigten PHP-Reihen. Verzögerungen sind dabei nicht automatisch Nachlässigkeit einzelner Administratoren. Fehlende Budgets, unklare Verantwortung und ungeprüfte Altsoftware können einen technisch einfachen Patch organisatorisch blockieren. Eine konkrete weltweite Updatequote wäre derzeit Spekulation.

Wie viele Websites bleiben bedroht?

W3Techs meldet am 25. Oktober 2026 PHP bei 69,2 Prozent der Websites mit bekannter serverseitiger Programmiersprache. Innerhalb des erkannten PHP-Bestands entfallen 26,8 Prozent auf PHP 7 und 7,7 Prozent auf PHP 5: zusammen 34,5 Prozent. Diese Zahlen beschreiben die erkannte Verbreitung. Daraus lässt sich nicht ablesen, welche Websites die Sicherheitsupdates bereits erhalten haben. [9]

Eine belastbare absolute Restzahl lässt sich daraus nicht berechnen. Anbieter-Backports, unterschiedliche Konfigurationen, verdeckte Versionsangaben und mehrere Websites pro Server verhindern die direkte Gleichsetzung. Auch einzelne Webseiten, Domains und Server sind unterschiedliche Zähleinheiten.

Als reine Rechenillustration: Von einer Million tatsächlich betroffener Installationen blieben bei 95 Prozent erfolgreich abgeschlossenen Updates noch 50.000 ungepatcht. Das ist keine Messung und keine Prognose. Die Rechnung zeigt lediglich, warum selbst eine hohe Updatequote bei großer Verbreitung einen erheblichen Restbestand zulässt. Für die konkrete Website zählt der nachgewiesene Patchstand wesentlich mehr als jede globale Prozentzahl.

Linux-Praxis: zuerst die tatsächlich verwendete Installation erfassen

Die folgenden Paketbeispiele gelten für Debian-/Ubuntu-Systeme mit APT und bereits eingerichteten, vertrauenswürdigen Paketquellen. Die jeweilige PHP-Reihe muss dort schon installiert sein. RPM-Systeme, Hosting-Panels und selbst gebaute Container benötigen den passenden Anbieterablauf. Eine willkürlich ergänzte Fremdquelle wäre keine belastbare Reparaturstrategie.

Vor der Änderung sind eine wiederherstellbare Sicherung, die Zuordnung jeder Domain zum zuständigen PHP-Pool und ein kurzer Testplan nötig. Paketinstallationen können Dienste schon während der Installation neu starten. Das Wartungsfenster beginnt deshalb vor dem Installationsbefehl. Die folgende Liste zeigt unter anderem die Kommandozeilenfassung von PHP (CLI) und die laufenden Dienste. Zusätzlich bleibt zu prüfen, welche PHP-Fassung der Webserver für jede Website verwendet.

ShellLinux: PHP-Bestand erfassen
cat /etc/os-release
command -v php
php -v
php --ini
dpkg-query -W -f='${binary:Package}\t${Version}\n' 'php*' 'libapache2-mod-php*' 2>/dev/null
systemctl list-units --type=service --all | grep -E 'php.*fpm|apache2|nginx'
ps -eo pid,lstart,comm | grep -E 'php|apache2'

Eine Domain kann PHP 8.4 über FPM verwenden, während php in der Shell auf 8.5 zeigt. Weitere Kopien können in Containern, Hosting-Verzeichnissen und alten Testdiensten liegen. Ein Prüfnachweis benötigt pro Installation Paketquelle, vollständige Revision, Dienst beziehungsweise Container und die zugehörigen Websites.

PHP 8.4 über APT aktualisieren

Der Ablauf wählt bereits installierte Pakete der Reihe 8.4, einschließlich vorhandener Erweiterungen und des Apache-Moduls. Zuerst wird die vollständige Paketliste gelesen; ein Fehler dabei bricht den Ablauf ab. Danach folgt die Auswahl für 8.4. Die APT-Simulation verändert keine Pakete. „Kandidat“ bedeutet hier die Version, die APT installieren würde. Erforderlich ist mindestens PHP 8.4.27 oder ein für beide Fehler bestätigter Backport. Für Debian 13 ist 8.4.27-1~deb13u1 als korrigiert dokumentiert. APT-Dokumentation Debian: CVE-2026-109618 Debian: CVE-2026-109619

ShellPHP 8.4: Paketquelle und Upgradeplan
set -euo pipefail
branch=8.4
sudo apt-get update
package_rows=$(dpkg-query -W -f='${db:Status-Abbrev} ${binary:Package}\n')
selected_rows=$(awk -v branch="$branch" '
  $1 == "ii" && ($2 == "php" branch ||
    index($2, "php" branch ":") == 1 ||
    index($2, "php" branch "-") == 1 ||
    $2 == "libapache2-mod-php" branch ||
    index($2, "libapache2-mod-php" branch ":") == 1) { print $2 }
' <<< "$package_rows")
test -n "$selected_rows"
mapfile -t php_packages <<< "$selected_rows"

apt-cache policy "${php_packages[@]}"
sudo apt-get -s install --only-upgrade "${php_packages[@]}"

Erst nach Prüfung des Plans folgt die Installation. Unerwartete Entfernungen, Reihenwechsel oder weiterhin verwundbare Kandidaten sind Abbruchgründe. Der folgende Block gehört in dieselbe Bash-Sitzung wie der vorangehende und setzt einen vorhandenen FPM-Dienst voraus:

ShellPHP 8.4: Installation und FPM-Prüfung
sudo apt-get install --only-upgrade "${php_packages[@]}"
sudo /usr/sbin/php-fpm8.4 -t
sudo systemctl restart php8.4-fpm
systemctl is-active php8.4-fpm
/usr/bin/php8.4 -v
/usr/sbin/php-fpm8.4 -v

PHP 8.5 über APT aktualisieren

Für eine bestehende 8.5-Installation gilt derselbe Ablauf mit einem korrigierten Kandidaten ab 8.5.12 oder bestätigtem Anbieter-Backport. Ein Debian-13-Standardrepository stellt nicht allein deshalb PHP 8.5 bereit, weil eine neuere PHP-Reihe existiert. Falls kein passender Kandidat aus der bereits freigegebenen Quelle verfügbar ist, endet dieser Ablauf vor der Installation.

ShellPHP 8.5: Paketquelle und Upgradeplan
set -euo pipefail
branch=8.5
sudo apt-get update
package_rows=$(dpkg-query -W -f='${db:Status-Abbrev} ${binary:Package}\n')
selected_rows=$(awk -v branch="$branch" '
  $1 == "ii" && ($2 == "php" branch ||
    index($2, "php" branch ":") == 1 ||
    index($2, "php" branch "-") == 1 ||
    $2 == "libapache2-mod-php" branch ||
    index($2, "libapache2-mod-php" branch ":") == 1) { print $2 }
' <<< "$package_rows")
test -n "$selected_rows"
mapfile -t php_packages <<< "$selected_rows"

apt-cache policy "${php_packages[@]}"
sudo apt-get -s install --only-upgrade "${php_packages[@]}"

Auch hier gilt: Fortsetzung erst nach Prüfung, in derselben Bash-Sitzung und ausschließlich für einen vorhandenen FPM-Dienst.

ShellPHP 8.5: Installation und FPM-Prüfung
sudo apt-get install --only-upgrade "${php_packages[@]}"
sudo /usr/sbin/php-fpm8.5 -t
sudo systemctl restart php8.5-fpm
systemctl is-active php8.5-fpm
/usr/bin/php8.5 -v
/usr/sbin/php-fpm8.5 -v

Bei Apache mit mod_php muss stattdessen das Apache-Modul tatsächlich aktualisiert und Apache nach erfolgreicher Konfigurationsprüfung geordnet neu gestartet werden. Für Debian lautet die Prüfung sudo apache2ctl configtest. Ein reines FPM-Setup benötigt wegen eines PHP-Paketupdates keinen pauschalen nginx-Neustart. Eigene FPM-Master, dauerhaft laufende CLI-Dienste und Container müssen gesondert berücksichtigt werden. Ein Neustart kann laufende Anfragen unterbrechen; bei mehreren gleichwertigen Servern erfolgt die Umstellung nacheinander.

Warum „PHP aktualisiert“ noch nicht „PHP aktiv korrigiert“ bedeutet

Linux kann einen laufenden Prozess weiter mit einer alten, bereits ersetzten Programmdatei bedienen. Ein neu gestartetes php -v meldet dann den korrigierten Stand, während ein alter Worker unverändert weiterläuft. Die folgende rein lesende Kontrolle findet PHP-Prozesse mit gelöschter ausführbarer Datei:

ShellAlte PHP-Prozessdateien unter Linux finden
sudo bash <<'BASH'
for link in /proc/[0-9]*/exe; do
  target=$(readlink "$link" 2>/dev/null) || continue
  case "$target" in
    *php*"(deleted)"*)
      pid=${link#/proc/}
      pid=${pid%/exe}
      printf 'PID %s: %s\n' "$pid" "$target"
      ;;
  esac
done
BASH

Ein Treffer zeigt Prüfbedarf beim Dienst und dessen Version, keinen bewiesenen Einbruch. Auch eine leere Ausgabe beweist keinen vollständigen Schutz: Geladene Apache-Module, Bibliotheken und weitere PHP-Installationen fehlen in dieser Suche. Anschließend sind Anmeldung, Uploads, Formulare, Hintergrundaufträge und geplante Aufgaben der Anwendung zu testen. Eine öffentlich erreichbare phpinfo()-Seite würde unnötig Serverdetails zeigen. Geeignet sind geschützte interne Diagnosen und die Zuordnung des laufenden Prozesses zur geprüften Installation.

PHP 7.4: ein Sicherheits-Backport statt unveränderter 7.4.33

PHP 7.4 bleibt abgekündigt. Der bevorzugte Weg ist die Migration auf eine unterstützte Reihe oder eine bestätigte Sicherheitskorrektur aus dem verlängerten Support des bisherigen Anbieters (LTS). Für eine unvermeidbare Übergangsphase hat das PHP-Projekt einen minimalen Quellcode-Backport für beide PHP2Shell-Kennungen veröffentlicht. Das ist keine Wiederaufnahme des allgemeinen Supports und keine Zusage zur Behebung anderer Lücken.

Der am 25. Oktober geprüfte Quellstand (Commit) lautet 712e60f9edfd03f0960fc4fc3c2c375f42b90aa2. Der folgende Ablauf bindet den Quellstand ausdrücklich an diesen Commit. Ein bloßer Neubau des unveränderten Releases 7.4.33 enthält diese Änderung nicht. PHP: konkreter Sicherheits-Commit

Das Beispiel übersetzt PHP-Quellcode in ausführbare Programme für Kommandozeile und FPM. Dafür ist eine getrennte, kompatible Debian-/Ubuntu-Umgebung mit Git und CA-Zertifikaten nötig. Die Blöcke gehören in dieselbe Bash-Sitzung. Das Beispiel ist keine vollständig geprüfte Produktionsinstallation. Alte PHP-Quellen lassen sich nicht mit beliebigen aktuellen Systembibliotheken bauen.

ShellPHP 7.4: offiziellen Sicherheits-Commit festlegen
set -euo pipefail
workdir=$(mktemp -d "$HOME/php74-php2shell.XXXXXX")
cd "$workdir"
git init php-src
cd php-src
git remote add origin https://github.com/php/php-src.git
commit=712e60f9edfd03f0960fc4fc3c2c375f42b90aa2
git fetch --depth=1 origin "$commit"
git checkout --detach FETCH_HEAD
test "$(git rev-parse HEAD)" = "$commit"
git show -s --format='%H%n%s%n%b' HEAD

Die Mindestwerkzeuge und das isolierte Installationsziel folgen unten. --disable-all hält den Beispielumfang klein; das Ergebnis enthält insbesondere nicht automatisch alle für WordPress oder andere Anwendungen nötigen Erweiterungen. Die vorgesehenen Benutzer- und Gruppennamen www-data müssen in der Zielumgebung existieren. PHP: Unix-Installation · PHP: FPM-Buildoptionen

ShellPHP 7.4: minimales Build und Tests
sudo apt-get update
sudo apt-get install --no-install-recommends \
  build-essential autoconf bison re2c pkg-config \
  libxml2-dev libsqlite3-dev

./buildconf --force
prefix=/opt/php74-php2shell-712e60f9
test ! -e "$prefix"
./configure \
  --prefix="$prefix" \
  --with-config-file-path="$prefix/etc" \
  --with-config-file-scan-dir="$prefix/etc/conf.d" \
  --disable-all --enable-cli --enable-fpm --enable-session \
  --with-fpm-user=www-data --with-fpm-group=www-data \
  --without-pear
make -j2
NO_INTERACTION=1 REPORT_EXIT_STATUS=1 make test

Fehlgeschlagene oder unerwartet übersprungene wichtige Tests müssen geklärt sein. Erst danach folgt die Installation in das neue Zielverzeichnis, im Skript prefix genannt. /usr/bin/php und vorhandene Distributionspakete werden dabei nicht ersetzt:

ShellPHP 7.4: isoliert installieren und identifizieren
sudo make install
sudo install -d -m 0755 "$prefix/etc/conf.d"
sudo install -m 0644 php.ini-production "$prefix/etc/php.ini"
"$prefix/bin/php" -n -v
"$prefix/bin/php" --ini
"$prefix/sbin/php-fpm" -v
git rev-parse HEAD

Die Ausgabe kann weiterhin eine 7.4-Versionsnummer zeigen. Der Nachweis besteht deshalb aus dem geprüften Quellstand, dem Bauprotokoll und dem tatsächlich verwendeten Programm. Für die Website fehlen möglicherweise noch Erweiterungen, etwa Datenbanktreiber, mbstring, XML, cURL oder ZIP. Erweiterungen müssen zur binären Schnittstelle dieses PHP-Baus passen (ABI). Auch die Bauwerkzeuge phpize und php-config müssen aus genau dieser Installation stammen.

FPM-Konfiguration, Betriebskonto und Dateirechte benötigen eigene Tests. Ein separater Socket, also ein eigener Verbindungsendpunkt, und ein eigener Dienst trennen die neue von der alten Installation. Nach erfolgreichem Test mit php-fpm -t -y /pfad/zur/php-fpm.conf kann der Webserver gezielt auf den neuen Pool verweisen. Ein erfolgreicher Kommandozeilenaufruf allein stellt keine Website um. Scheitert die Umstellung, bleibt die Anwendung abgeschirmt; die alte verwundbare Fassung darf nicht einfach wieder öffentlich erreichbar werden.

Angriffsspuren: mehrere Signale zusammen betrachten

Datadog hat die Fehler im Labor reproduziert. Erfolgreiche Codeausführung muss weder einen Worker-Absturz noch einen auffälligen HTTP-Status erzeugen. Ein HTTP 200 ist daher kein Entwarnungssignal. Verdächtige Formularanfragen, Speicherfehler und unerwartete Kindprozesse gewinnen erst im zeitlichen Zusammenhang Aussagekraft. Ein einzelner Speichermangelfehler beweist noch keinen Angriff. Datadog Security Labs: eigene Analyse

Für eine Untersuchung sind Webserver-Protokolle, PHP-Fehler, gestartete Prozesse und unerwartete Dateiänderungen gemeinsam zu prüfen. Vor einer Bereinigung müssen vorhandene Belege gesichert sein. Vollständige Formularinhalte können Passwörter enthalten und gehören nicht pauschal in Protokolle. Eine Web Application Firewall (WAF) filtert Webanfragen, repariert aber PHP nicht. Zwei Ergebnisse sind getrennt festzuhalten: Das korrigierte PHP läuft, und mögliche frühere Zugriffe sind untersucht.

PHP2Shell in den Logs erkennen: Verdacht ist noch kein Nachweis

Es gibt keinen universellen Protokolleintrag „PHP2Shell erkannt“. Eine auffällige Anfrage, ein Softwarefehler und bestätigte fremde Befehle sind unterschiedliche Befunde. Stärker ist eine zusammenpassende Folge: ungewöhnliche Anfrage, Fehler im zuständigen PHP-Prozess und danach eine unerklärte Aktion. Fehlende Einträge können an abgeschalteter Aufzeichnung, bereits gelöschten alten Protokollen oder zu kurzer Aufbewahrung liegen.

BeobachtungEinordnungNächste Prüfung
Viele POST-Anfragen oder große UploadsAuch bei Importen und regulären Uploads üblichZielroute, Uhrzeit und Abweichung vom üblichen Betrieb
Speichermangel, Prozessabbruch oder ungültiger Speicherzugriff (Segfault)Verdachtsmoment, keine eindeutige PHP2Shell-SignaturZugehörige Anfragen, Pool, Prozessnummer (PID) und bekannte Softwarefehler
Unerwartetes Befehlsprogramm oder Downloadwerkzeug, gestartet durch PHPErhöhte Priorität; manche Anwendungen starten solche Programme legitimElternprozess, tatsächlicher Zweck und zeitlicher Zusammenhang
Nicht freigegebene Codeänderung oder belegter fremder BefehlKonkreter Hinweis auf eine KompromittierungIsolation, Beweissicherung und Prüfung des Umfangs

Erste Log-Abfragen unter Linux

Die folgenden Befehle lesen vorhandene Daten. Dienstnamen, Dateipfade und Zeitraum müssen zur Installation passen. Die Zeitangabe gilt in der lokalen Systemzeitzone; für den Abgleich mit anderen Systemen sind Zeitversatz und synchronisierte Uhren zu berücksichtigen. Das Journal enthält PHP-Fehler nur, wenn der jeweilige Dienst solche Meldungen tatsächlich dorthin schreibt. systemd: journalctl

ShellJournal: Speicherfehler und Worker-Abbrüche
sudo journalctl --since '2026-10-17 00:00:00' \
  -u php8.4-fpm -u php8.5-fpm -u apache2 -u nginx \
  --no-pager -o short-iso |
grep -Ei 'Allowed memory size.*exhausted|Out of memory|segfault|SIGSEGV|child .*exited on signal'

Eine fehlende Ausgabe bedeutet lediglich „kein Treffer in diesen Quellen mit diesem Suchmuster“. Separate FPM-Fehlerdateien, Containerlogs und virtuelle Hosts mit eigenen Protokollen benötigen zusätzliche Abfragen. Auch bereits rotierte Dateien gehören zum Untersuchungszeitraum.

Für übliche Apache-/nginx-Access-Logs mit einer protokollierten HTTP-Anfrage liefert die folgende Abfrage die letzten hundert passenden POST-Zeilen der eingelesenen Dateien. Das ist eine erste Sichtung, kein vollständiger Scanner und wegen der Dateireihenfolge keine garantierte zeitliche Sortierung:

ShellAccess-Logs: POST-Anfragen sichten
sudo zgrep -hE '"POST [^"]+ HTTP/[0-9.]+"' \
  /var/log/nginx/access.log* /var/log/apache2/access.log* |
tail -n 100

Falls ein genannter Logpfad nicht existiert oder ein anderes Format verwendet wird, ist die Dateiauswahl anzupassen. Standard-Access-Logs enthalten normalerweise nicht den vollständigen Inhalt einer Anfrage (Request-Body). Die häufig vorhandene Bytezahl beschreibt zudem meist die Antwortgröße, nicht die Größe des Uploads. Ein Suchlauf nach PHP_SESSION_UPLOAD_PROGRESS in gewöhnlichen Access-Logs kann deshalb leer bleiben, obwohl ein entsprechendes Formularfeld gesendet wurde. Fehlende Bodydaten lassen sich nachträglich nicht rekonstruieren. Apache: Bedeutung und Konfiguration der Logs

Eine Momentaufnahme der Prozessbeziehungen kann ergänzend helfen:

ShellAktuelle Prozesse und Elternprozesse
ps -eo pid,ppid,lstart,user,comm --forest

Die Liste zeigt nur gerade laufende Prozesse. Bereits beendete Befehle lassen sich nur nachvollziehen, wenn vorher eine passende Überwachung aktiv war. Dazu gehören Betriebssystem-Audits oder Sicherheitsprogramme, die Prozessstarts aufzeichnen (EDR). Eine heute eingeschaltete Aufzeichnung liefert keine Daten für gestern.

Logging gezielt verbessern, ohne Formularinhalte zu sammeln

Ein zusätzliches nginx-Protokoll kann Kennung, Zeitpunkt, Methode, Pfad und Ergebnis jeder Anfrage sowie Datenmenge und Laufzeit aufzeichnen. Die Definition gehört innerhalb des Blocks http { ... } in die nginx-Konfiguration. Das neue Format hilft erst bei künftigen Anfragen. nginx: log_format und access_log

nginxnginx: zusätzliches Metadatenformat
log_format php2shell escape=json
  '{"time":"$time_iso8601","request_id":"$request_id",'
  '"client":"$remote_addr","method":"$request_method","uri":"$uri",'
  '"status":"$status","request_bytes":"$request_length",'
  '"response_bytes":"$body_bytes_sent","duration":"$request_time",'
  '"upstream_status":"$upstream_status"}';

Die nächste Zeile aktiviert das Format innerhalb des passenden Blocks server { ... }. Vorhandene access_log-Einträge und übergeordnete Einstellungen müssen dabei geprüft werden: Eine eigene Einstellung auf dieser Ebene kann die bisher übernommene Protokollierung ersetzen.

nginxnginx: Format für den gewünschten Host aktivieren
access_log /var/log/nginx/php2shell-access.log php2shell;

Vor dem Neuladen der Konfiguration muss nginx -t erfolgreich sein. request_bytes umfasst die ganze Anfrage einschließlich Kopfzeilen, nicht nur die hochgeladene Datei. Die Zahl misst auch nicht den PHP-Speicherbedarf. $uri ist der von nginx bearbeitete Pfad und kann sich durch interne Weiterleitungen ändern. Der Parameterteil der URL, Cookies, Zugangskopfzeilen und Formularinhalte werden nicht direkt aufgezeichnet. Trotzdem können IP-Adressen und Pfade personenbezogene Angaben enthalten. Zugriffsrechte, Aufbewahrung und regelmäßige Rotation der Protokolldateien gehören deshalb zur Einrichtung. Hinter einem vorgeschalteten Server ist die Clientadresse nur bei korrekt eingerichteten Vertrauensregeln verlässlich. OWASP: sichere Protokollierung

Schutz während eines noch offenen Updates

Vorrang hat die korrigierte PHP-Installation. Falls ein kurzfristiges Update unmöglich ist, müssen öffentliche Anfragen vor PHP gestoppt werden, etwa durch eine statische Wartungsseite oder beschränkten Zugang. Das gilt auch für den direkten Zugriff auf den Ursprungsserver. Ein geschützter Weg über ein CDN, das Inhalte verteilt oder weiterleitet, reicht bei offenem Direktzugang nicht aus.

  • Anfragen begrenzen: Größen-, Upload- und Ratenlimits am vorgeschalteten Server (Reverse Proxy) an den tatsächlichen Bedarf anpassen. Auch legitime Importe und große Dateien benötigen eine geprüfte Regel. Eine kleine Anfrage kann intern mehr Speicher beanspruchen; ein Größenlimit ist deshalb kein vollständiger Schutz.
  • WAF als Zusatzschicht: Passende Herstellerregeln aktivieren und ihre tatsächliche Durchsetzung prüfen. Regeln im Beobachtungsmodus blockieren nichts; ein HTTP 403 belegt nur die Ablehnung dieser Anfrage.
  • Rechte begrenzen: Eigene Poolkonten, minimale Dateirechte, eingeschränkte Datenbankkonten und begrenzte Netzwerkzugriffe verkleinern mögliche Folgeschäden. Eine übernommene Anwendung kann weiterhin alle legitim verfügbaren Geheimnisse missbrauchen.
  • Offizielle Übergangsmaßnahmen: Frühes Abschalten des Session-Upload-Fortschritts blockiert bestimmte Pfade, aber nicht beide Fehler vollständig. Eine pauschale Umstellung auf unbegrenzten PHP-Speicher ohne passende äußere Begrenzung kann zusätzliche Ausfälle verursachen.

Bei konkreten Einbruchsspuren: Patch und Vorfall getrennt behandeln

Eine verdächtige Datei einfach zu löschen und anschließend PHP zu aktualisieren reicht nicht für einen belastbaren Abschluss. Zuerst ist die betroffene Instanz so zu isolieren, dass weitere Zugriffe verhindert werden. Parallel gehören relevante Logs, Zeitangaben und verfügbare Prozessdaten gesichert. Eine unüberlegte Bereinigung kann wertvolle Belege vernichten.

Anschließend folgen die Prüfung erreichbarer Daten und Nachbarsysteme, die Erneuerung möglicherweise offengelegter Zugangsdaten aus einer vertrauenswürdigen Umgebung und gegebenenfalls der Neuaufbau aus geprüften Quellen. Ein Backup muss zeitlich und inhaltlich vor einer möglichen Kompromittierung liegen. Die Rückkehr in den öffentlichen Betrieb setzt eine korrigierte aktive Laufzeit, geprüfte Anwendung und fortgesetzte Beobachtung voraus. „Patch installiert“ und „Vorfall aufgeklärt“ bleiben zwei unterschiedliche Nachweise.

Fragen und Antworten

Reicht ein WordPress-Update?

Nein. Ein WordPress-Update ersetzt keine korrigierte PHP-Laufzeit. Anwendung und Serverpakete benötigen getrennte Prüfungen.

Beweist eine funktionierende Website einen sicheren Zustand?

Nein. Reguläre Seitenaufrufe können trotz verwundbarer Laufzeit fehlerfrei funktionieren. Auch fehlende sichtbare Veränderungen schließen einen früheren Zugriff nicht aus.

Ein sinnvoller Nachweis verbindet Paketrevision, Herstellerbestätigung für beide CVEs und Kontrolle der aktiven Webprozesse. Bei Einbruchsspuren kommt eine gesonderte Untersuchung hinzu.

Quellen

  1. PHP: Sicherheitsmeldung vom 21. Oktober 2026
  2. PHP Foundation: Sicherheitsupdate und Hintergründe
  3. PHP: CVE-2026-109618
  4. PHP: CVE-2026-109619
  5. ENISA: gemeinsame Sicherheitsmeldung
  6. NHS England: PHP2Shell
  7. cPanel: korrigierte Paketversionen
  8. Google Cloud: PHP-Updates und erneutes Bereitstellen
  9. W3Techs: PHP-Verbreitung am 25. Oktober 2026

Zusätzliche Primärquellen und Dokumentation

Weiterführende Analysen und Berichterstattung

Dokumentation zur Log-Auswertung

Lukas Wojcik

Lukas Wojcik

Systems architect and technology enthusiast specializing in scalable tracking solutions, GMP Stack (GA4 & GTM), and robust backend architectures. Advocate for clean code and privacy-first design.

Kontakt

Eine Frage oder eine Idee für ein Webprojekt? Schreib mir kurz, worum es geht. Das Formular nutzt reCAPTCHA zum Schutz vor Spam.

Kommentar schreiben

Randfälle, die der Artikel nicht behandelt, und Rückfragen zum Code sind hier willkommen.

Die E-Mail-Adresse wird nicht veröffentlicht. Pflichtfelder sind mit einem Stern versehen.