-FROM php:8.3.35-fpm-bookworm, +FROM php:8.3.36-fpm-bookworm. Diesen einzeiligen Diff will ich diese Woche in jedem PHP-Repository sehen. Er ist nicht clever, und niemand wird ihm auf GitHub einen Stern geben. Aber er macht aus einem kritischen Sicherheitsfix einen Pull Request mit grüner Pipeline und einem Reviewer-Namen dran. Ohne ihn bekommst du stattdessen einen nervösen E-Mail-Verlauf mit deinem Hoster und eine Ticketnummer, die im März keiner mehr wiederfindet.
Dein Interpreter ist eine Abhängigkeit. Er ist sogar die wichtigste, die du hast, und die meisten von uns behandeln ihn wie das Wetter. Wir pinnen 140 Composer-Pakete auf exakte Commit-Hashes, streiten im Code-Review über ein Minor-Update einer Logging-Library und lassen das alles dann auf irgendeinem php-Binary laufen, das zufällig auf der Kiste lag, als zuletzt jemand apt ausgeführt hat. PHP2Shell ist ein guter Anlass, damit aufzuhören, und zwar ein besserer als jeder Konferenzvortrag über reproduzierbare Builds.
Kurz zum Hintergrund, falls du Ende Oktober tief in einem Sprint gesteckt hast. Am 21. Oktober 2026 hat das PHP-Projekt Fixes für CVE-2026-109618 und CVE-2026-109619 veröffentlicht. Beides sind Speichersicherheitsfehler tief in der Engine. Der eine ist über einen Out-of-Memory-Pfad erreichbar, der andere ist ein Use-after-free, und zusammen können sie einem Fremden Codeausführung auf deinem Server verschaffen, ganz ohne Login. Gepatcht sind 8.5.12, 8.4.27, 8.3.36 und 8.2.35. Für 8.1 und alles Ältere gibt es upstream nichts, und 8.2 erreicht am 31. Dezember 2026 sein Lebensende. Wer auf 8.2 sitzt, bekommt also jetzt einen Patch und vor den Feiertagen eine Migration zu planen. Das Canadian Centre for Cyber Security hat übrigens ein eigenes Advisory herausgegeben, falls deine Compliance-Leute noch einen zweiten Briefkopf brauchen.
Unangenehm ist an diesem Bug vor allem eines: Keiner deiner üblichen Alarme schlägt an. WordPress hat einen Hinweis veröffentlicht, dass dafür kein Core-Release nötig ist. Das stimmt, heißt aber auch, dass das gelbe Update-Banner in wp-admin stumm bleibt. Zieh Laravel auf das neueste Minor, und es ändert sich nichts. composer audit meldet auf einem sperrangelweit offenen Server null Befunde, weil Composer noch nie etwas über das Binary wusste, auf dem es läuft. Deine Middleware, deine Validierungsregeln und deine WordPress-Hooks haben nichts mehr zu melden, wenn die Engine darunter kompromittiert ist. Wenn die Runtime also nicht irgendwo festgehalten ist, wo du tatsächlich hinschaust, ist sie genau dann unsichtbar, wenn du sie am dringendsten sehen müsstest.
Der stärkste Einwand verdient eine faire Anhörung, und er hat zwei Teile. Erstens läuft ein riesiger Teil von PHP auf Managed oder Shared Hosting, und viele haben sich genau deshalb dafür entschieden, damit sie nie ein Binary verantworten müssen. Einer Fünf-Personen-Agentur mit 60 WordPress-Kundenseiten zu sagen, sie solle den Interpreter versionieren, geht am Grund vorbei, aus dem sie einen Hoster bezahlt. Zweitens backporten Distributionen Fixes und lassen den Upstream-Versionsstring unverändert. Ein Debian- oder RHEL-Paket kann also sicher sein und trotzdem eine Nummer melden, die verwundbar aussieht. Wer auf Upstream-Nummern pinnt, bekommt womöglich Fehlalarme oder, schlimmer noch, falsche Beruhigung.
Ich nehme beides ernst und finde trotzdem, dass dich keins davon aus der Verantwortung entlässt. Das Patchen kannst du abgeben. Das Wissen nicht. Selbst bei einem Hoster, auf dem du nie eine Shell bekommen wirst, kann deine Anwendung melden, mit welcher Runtime sie läuft: über einen Health-Endpoint, einen Uptime-Check, der PHP_VERSION ausliest und unterhalb einer Schwelle fehlschlägt, oder eine Zeile im Deploy-Log. Wenn Backports den Versionsstring verwässern, dann halte eben Paketname und Release fest, aber halte es irgendwo fest, wo du diffen kannst. Es geht nicht um eine bestimmte Nummer. Es geht darum, dass die Antwort auf die Frage, was da eigentlich läuft, ein nachschlagbarer Fakt ist und keine Vermutung. Gefährlich wird das Raten bei langlebigen Prozessen. Wenn ein FPM-Master, ein Octane-Worker oder ein Horizon-Supervisor seit dem 19. Oktober läuft, hat er noch den alten Code im Speicher, egal was der Paketmanager behauptet.
Unsere Nachbarn, die Go schreiben, bekommen ihre Runtime in jedes Binary kompiliert, ob sie wollen oder nicht, und dafür bauen sie bei jedem Toolchain-Wechsel sämtliche Services neu. Wir haben uns für einen gemeinsam genutzten Interpreter entschieden, und der ist günstiger, zugänglicher und ein großer Grund dafür, dass PHP das halbe Web von einem Hostingpaket für zehn Euro aus betreibt. Das ist ein echter Vorteil. Er bringt nur ein bisschen Buchführung mit sich, und mit PHP2Shell war diese Buchführung fällig.
Deshalb frage ich, und ich hätte die Antworten wirklich gern in den Kommentaren: Wo steht deine produktive PHP-Version gerade tatsächlich? In einem Dockerfile, in einer Ansible-Variable, in einem Dropdown im Hosting-Panel oder nirgends? Und wenn dich heute Nachmittag jemand fragen würde: Könntest du innerhalb von zehn Minuten belegen, welcher Patchstand deinen letzten Produktions-Request beantwortet hat?




Kommentare
Noch keine Kommentare — schreib den ersten.
Starte die Diskussion
Kein Konto, kein Passwort nötig — gib einfach deine E-Mail-Adresse ein, wir senden dir einen einmaligen Anmelde-Link. Beim ersten Mal bist du damit automatisch angemeldet.
Deine Bewertung wird nach der Anmeldung automatisch übernommen.
Schau in dein Postfach
Wir haben einen Anmelde-Link an … gesendet. Öffne ihn auf diesem Gerät — dieser Tab meldet dich automatisch an.
Nichts angekommen? Wirf einen Blick in den Spam-Ordner — und markiere die Mail dort als „Kein Spam“, dann landet sie künftig direkt im Postfach.