# PHP in Kubernetes patchen

> Kubernetes PHP-Image nach PHP2Shell patchen: verwundbare Pods finden, Images neu bauen, alle Workloads ausrollen und den Stand je Pod nachweisen.

Quelle: https://phpsos.de/server/kubernetes/  
Stand: 25.10.2026  
Anbieter: PHP SOS, PHP-Notfallhilfe und Server-Sicherheit. Soforthilfe per WhatsApp: https://wa.me/491736494914?text=Hallo%20PHP%20SOS%2C%20wir%20brauchen%20Hilfe%20mit%20unserem%20PHP-Server.%20Firma%3A%20%E2%80%A6%20Website%3A%20%E2%80%A6

**Kurz gesagt:** In Kubernetes steckt PHP im Container-Image, nicht im Cluster. Nach PHP2Shell müssen Sie jedes Kubernetes PHP-Image mit behobener PHP-Version neu bauen, alle betroffenen Workloads neu ausrollen und danach in jedem laufenden Pod den Stand prüfen. Ein aktualisiertes Basis-Image im Registry allein ändert an laufenden Pods nichts.

## Warum der Cluster selbst nicht patcht

Kubernetes verwaltet Container, kümmert sich aber nicht um die Software darin. Jeder Pod läuft mit dem Image, aus dem er gestartet wurde, bis er ersetzt wird. Wer PHP-Anwendungen im Cluster betreibt, trägt deshalb die Verantwortung für die Images, auch wenn der Cluster als verwalteter Dienst bei einem Cloud-Anbieter läuft. Der Anbieter pflegt typischerweise die Steuerungsebene und die Knoten, nicht die Images der Kunden.

PHP2Shell umfasst CVE-2026-109618 und CVE-2026-109619, jeweils mit CVSS v4.0 9.2. Betroffen sind unter anderem PHP-FPM, Apache mit mod_php und FrankenPHP, also die üblichen Betriebsarten in PHP-Images. Behoben sind PHP 8.5.12, 8.4.27, 8.3.36 und 8.2.35.

## Bestandsaufnahme: Welches Kubernetes PHP-Image läuft wo?

Beginnen Sie mit einer Liste aller Images im Cluster. Die folgenden Befehle lesen nur. Namen von Namespaces, Deployments und Containern sind Beispiele.

```bash
# Alle Images aller Pods, gruppiert
kubectl get pods -A -o jsonpath='{range .items[*]}{.metadata.namespace}{"\t"}{.metadata.name}{"\t"}{range .spec.containers[*]}{.image}{" "}{end}{"\n"}{end}'

# Tatsächlich laufender Image-Digest je Container
kubectl get pods -A -o jsonpath='{range .items[*]}{.metadata.name}{"\t"}{range .status.containerStatuses[*]}{.imageID}{" "}{end}{"\n"}{end}'

# PHP-Version in einem laufenden Pod
kubectl exec -n shop deploy/web -c php -- php -v
```

Denken Sie neben Deployments auch an StatefulSets, DaemonSets, CronJobs und Init-Container. In größeren Clustern helfen Image-Scanner, die Images nach bekannten CVEs durchsuchen. Bei Distributionspaketen innerhalb des Images gilt wie überall: Ein Backport kann die Versionsnummer unverändert lassen, dann zählt das Änderungsprotokoll des Pakets.

## Images neu bauen

Aktualisieren Sie zuerst das Basis-Image. Nutzen Sie offizielle PHP-Images, wählen Sie eine Variante mit behobener PHP-Version. Bauen Sie dann Ihr eigenes Image neu, ohne die alte Basisschicht aus dem Cache zu übernehmen.

```bash
# Beispiel: Image neu bauen, Basis-Image aktiv neu ziehen
docker build --pull --no-cache -t registry.example.com/shop/web:2026-10-25 .

# PHP-Version im neuen Image vor dem Rollout prüfen
docker run --rm registry.example.com/shop/web:2026-10-25 php -v
```

Verlassen Sie sich nicht auf Tags wie `latest` oder eine bloße Hauptversion. Referenzieren Sie im Manifest möglichst den Digest des neuen Images, damit eindeutig ist, welcher Stand ausgerollt wird. Läuft die Bereitstellung über GitOps oder Helm, ändern Sie das Image dort, damit der Stand nicht beim nächsten Abgleich zurückgesetzt wird.

## Rollout und Kontrolle

Ein neuer Rollout ersetzt alle Pods eines Workloads schrittweise. Danach prüfen Sie den Stand in den laufenden Pods. Erst dann ist der Patch wirksam, denn neue Dateien helfen nur, wenn alte PHP-Prozesse nicht mehr laufen.

```bash
# Rollout mit neuem Image (Namen als Beispiel)
kubectl -n shop set image deploy/web php=registry.example.com/shop/web@sha256:<digest>
kubectl -n shop rollout status deploy/web

# Kontrolle: alle Pods neu gestartet, neuer Digest aktiv?
kubectl -n shop get pods -o wide
kubectl -n shop exec deploy/web -c php -- php -v
```

Wurde das Image unter gleichem Tag neu gepusht, löst `kubectl rollout restart` einen Neustart aus; Pods ziehen das Image aber nur neu, wenn die `imagePullPolicy` das vorsieht. Sicherer ist der Wechsel auf einen neuen Digest.

> **Wichtig:**
> Sichern Sie Logs, bevor Sie Pods ersetzen. Mit dem alten Pod verschwinden auch seine lokalen Protokolle. Bewahren Sie Webserver- und Anwendungslogs ab dem 20.10.2026 auf, idealerweise in einer zentralen Log-Plattform.

## Übergangsmaßnahmen im Cluster

Ist für Ihre PHP-Version noch kein behobenes Image verfügbar, empfiehlt php.net Übergangsmaßnahmen ohne vollständigen Schutz. Im Cluster setzen Sie Speichergrenzen über die Ressourcenlimits der Container, die auf cgroups beruhen. Das entspricht der Empfehlung, Speicher über Container oder cgroups zu begrenzen und nicht über `RLIMIT_AS` oder `RLIMIT_DATA`.

```ini
; php.ini oder FPM-Pool im Image, z. B. per ConfigMap eingebunden
session.upload_progress.enabled = 0
post_max_size = 8M
upload_max_filesize = 6M
```

Mit Upload-Funktion nennt php.net `post_max_size = 32M`. Auf PHP 8.5 kommt `fatal_error_backtraces=0` hinzu. Nach Änderung der Konfiguration ist ein neuer Rollout nötig. Ergänzend begrenzen NetworkPolicies ausgehende Verbindungen der PHP-Pods, und ein Ingress mit Schutzregeln kann Angriffsversuche erschweren. Regeln anhand der Anfragedaten allein genügen laut Cloudflare aber nicht.

## Dauerhaft besser aufstellen

Planen Sie regelmäßige automatische Rebuilds aller PHP-Images, eine Image-Prüfung in der Build-Kette und Richtlinien, die nur signierte oder geprüfte Images zulassen. Laufen PHP-Container mit Benutzer ohne Root-Rechte und schreibgeschütztem Dateisystem, sinkt der Schaden eines erfolgreichen Angriffs. Hinweise für einzelne Container stehen unter [PHP in Docker-Containern patchen](https://phpsos.de/php2shell/docker-container-patchen/), für FrankenPHP unter [FrankenPHP absichern](https://phpsos.de/server/frankenphp/).

In vielen Clustern laufen PHP-Anwendungen nicht allein. Häufig gibt es Sidecar-Container für Logging oder Metriken, Hilfs-Images für Datenbankmigrationen und Jobs, die nur nachts starten. Auch Images von Drittanbietern, etwa für ein Wiki, eine Monitoring-Oberfläche oder ein Ticketsystem, können PHP enthalten, ohne dass das im Namen erkennbar ist. Prüfen Sie deshalb nicht nur Ihre eigenen Anwendungen, sondern jedes Image im Cluster. Für fremde Images gilt: Warten Sie auf eine aktualisierte Fassung des Herstellers, prüfen Sie dessen Angaben zur enthaltenen PHP-Version und begrenzen Sie die Erreichbarkeit, bis sie vorliegt. Läuft ein solches System nur intern, senkt das das Risiko, ersetzt aber nicht das Update.

## Wie hilft PHP SOS konkret?

- Wir erfassen alle Workloads mit PHP, ihre Images und Digests und prüfen die PHP-Version in laufenden Pods.
- Über den [PHP-Patch-Service](https://phpsos.de/leistungen/php-patch-service/) bauen wir Images neu, rollen sie aus und dokumentieren den Stand je Workload.
- Wir sichern Logs vor dem Austausch und prüfen auf Spuren eines Angriffs.
- Mit [Security-Monitoring](https://phpsos.de/leistungen/security-monitoring/) und automatisierten Rebuilds sorgen wir dafür, dass der nächste Patch schneller im Cluster ankommt.


## Häufige Fragen

**Reicht es, das Basis-Image im Registry zu aktualisieren?**  
Nein. Laufende Pods nutzen weiter das Image, mit dem sie gestartet wurden. Erst ein neuer Rollout mit dem neu gebauten Image ersetzt die Pods. Prüfen Sie danach die PHP-Version in jedem laufenden Pod.

**Warum Images per Digest referenzieren?**  
Ein Tag kann auf unterschiedliche Image-Stände zeigen, je nachdem, wann es gezogen wurde. Ein Digest benennt genau einen Stand. Damit wissen Sie sicher, welcher Code in welchem Pod läuft, und Rollouts werden nachvollziehbar.

**Was ist mit CronJobs und Init-Containern?**  
Auch sie können PHP enthalten und gehören zur Bestandsaufnahme. CronJobs starten bei jedem Lauf neue Pods aus ihrer Vorlage; aktualisieren Sie daher das Image in der Vorlage. Init-Container laufen beim Start jedes Pods.

**Schützt eine NetworkPolicy vor PHP2Shell?**  
Sie schließt die Lücke nicht, kann aber den Schaden begrenzen. Wer ausgehende Verbindungen von PHP-Pods einschränkt, erschwert das Nachladen von Schadcode und Seitwärtsbewegungen im Cluster.

## Quellen

- [php.net: Sicherheitsmeldungen](https://www.php.net/)
- [PHP 8 ChangeLog](https://www.php.net/ChangeLog-8.php)
- [OWASP Cheat Sheets](https://cheatsheetseries.owasp.org/)
- [BSI](https://www.bsi.bund.de/)
