# Parchear PHP en Kubernetes

> Parchear la imagen PHP en Kubernetes tras PHP2Shell: encuentre los pods vulnerables, recompile imágenes, despliegue todas las cargas y demuestre el estado por pod.

Fuente: https://phpsos.de/es/server/kubernetes/  
Actualizado: 25/10/2026  
Proveedor: PHP SOS, Ayuda de emergencia para PHP y seguridad de servidores. Ayuda inmediata por WhatsApp: https://wa.me/491736494914?text=Hola%20PHP%20SOS%2C%20necesitamos%20ayuda%20con%20nuestro%20servidor%20PHP.%20Empresa%3A%20%E2%80%A6%20Sitio%20web%3A%20%E2%80%A6

**En resumen:** en Kubernetes, PHP está en la imagen del contenedor, no en el clúster. Tras PHP2Shell debe recompilar cada imagen PHP de Kubernetes con la versión corregida de PHP, volver a desplegar todas las cargas de trabajo afectadas y comprobar después el estado en cada pod en ejecución. Una imagen base actualizada en el registro no cambia nada en los pods que ya están en marcha.

## Por qué el propio clúster no parchea

Kubernetes gestiona contenedores, pero no se ocupa del software que hay dentro. Cada pod funciona con la imagen con la que se inició hasta que se sustituye. Quien opera aplicaciones PHP en el clúster es, por tanto, responsable de las imágenes, aunque el clúster funcione como servicio gestionado en un proveedor de nube. El proveedor mantiene normalmente el plano de control y los nodos, no las imágenes de los clientes.

PHP2Shell comprende CVE-2026-109618 y CVE-2026-109619, cada una con un CVSS v4.0 de 9,2. Afectan, entre otros, a PHP-FPM, a Apache con mod_php y a FrankenPHP, es decir, los modos de funcionamiento habituales en las imágenes de PHP. Están corregidas PHP 8.5.12, 8.4.27, 8.3.36 y 8.2.35.

## Inventario: ¿qué imagen PHP de Kubernetes funciona dónde?

Empiece con una lista de todas las imágenes del clúster. Los comandos siguientes solo leen. Los nombres de espacios de nombres, deployments y contenedores son ejemplos.

```bash
# Todas las imágenes de todos los pods, agrupadas
kubectl get pods -A -o jsonpath='{range .items[*]}{.metadata.namespace}{"\t"}{.metadata.name}{"\t"}{range .spec.containers[*]}{.image}{" "}{end}{"\n"}{end}'

# Digest de imagen realmente en ejecución por contenedor
kubectl get pods -A -o jsonpath='{range .items[*]}{.metadata.name}{"\t"}{range .status.containerStatuses[*]}{.imageID}{" "}{end}{"\n"}{end}'

# Versión de PHP en un pod en ejecución
kubectl exec -n shop deploy/web -c php -- php -v
```

Además de los deployments, piense en StatefulSets, DaemonSets, CronJobs y contenedores de inicialización. En clústeres grandes ayudan los escáneres de imágenes, que buscan CVE conocidas en ellas. Con los paquetes de distribución dentro de la imagen vale lo de siempre: un backport puede dejar el número de versión sin cambios y entonces cuenta el registro de cambios del paquete.

## Recompilar las imágenes

Actualice primero la imagen base. Si usa imágenes oficiales de PHP, elija una variante con la versión corregida de PHP. Después recompile su propia imagen, sin reutilizar de la caché la capa base antigua.

```bash
# Ejemplo: recompilar la imagen, descargando de nuevo de forma activa la imagen base
docker build --pull --no-cache -t registry.example.com/shop/web:2026-10-25 .

# Comprobar la versión de PHP en la imagen nueva antes del rollout
docker run --rm registry.example.com/shop/web:2026-10-25 php -v
```

No se fíe de etiquetas como `latest` ni de una mera versión principal. Referencie en el manifiesto, a ser posible, el digest de la imagen nueva, para que quede claro qué versión se despliega. Si el despliegue se hace con GitOps o Helm, cambie la imagen allí, para que el estado no se revierta en la siguiente sincronización.

## Rollout y control

Un nuevo rollout sustituye de forma gradual todos los pods de una carga de trabajo. Después se comprueba el estado en los pods en ejecución. Solo entonces es efectivo el parche, porque los archivos nuevos sirven únicamente si ya no funcionan procesos PHP antiguos.

```bash
# Rollout con imagen nueva (nombres a modo de ejemplo)
kubectl -n shop set image deploy/web php=registry.example.com/shop/web@sha256:<digest>
kubectl -n shop rollout status deploy/web

# Control: ¿todos los pods reiniciados, digest nuevo activo?
kubectl -n shop get pods -o wide
kubectl -n shop exec deploy/web -c php -- php -v
```

Si la imagen se ha vuelto a subir con la misma etiqueta, `kubectl rollout restart` provoca un reinicio; sin embargo, los pods solo descargan de nuevo la imagen si la `imagePullPolicy` lo prevé. Es más seguro pasar a un digest nuevo.

> **Importante:**
> Conserve los registros antes de sustituir los pods. Con el pod antiguo desaparecen también sus registros locales. Conserve los registros del servidor web y de la aplicación desde el 20/10/2026, idealmente en una plataforma central de registros.

## Medidas provisionales en el clúster

Si todavía no hay una imagen corregida para su versión de PHP, php.net recomienda medidas provisionales sin protección completa. En el clúster, los límites de memoria se fijan mediante los límites de recursos de los contenedores, que se basan en cgroups. Esto corresponde a la recomendación de limitar la memoria mediante contenedores o cgroups y no mediante `RLIMIT_AS` ni `RLIMIT_DATA`.

```ini
; php.ini o pool FPM en la imagen, p. ej. integrado mediante ConfigMap
session.upload_progress.enabled = 0
post_max_size = 8M
upload_max_filesize = 6M
```

Con función de carga de archivos, php.net indica `post_max_size = 32M`. En PHP 8.5 se añade `fatal_error_backtraces=0`. Tras cambiar la configuración hace falta un nuevo rollout. Como complemento, las NetworkPolicies limitan las conexiones salientes de los pods PHP, y un Ingress con reglas de protección puede dificultar los intentos de ataque. Según Cloudflare, sin embargo, las reglas basadas solo en los datos de la solicitud no bastan.

## Posicionarse mejor a largo plazo

Planifique recompilaciones automáticas periódicas de todas las imágenes PHP, una comprobación de imágenes en la cadena de compilación y políticas que solo admitan imágenes firmadas o verificadas. Si los contenedores PHP funcionan con un usuario sin privilegios de root y con el sistema de archivos protegido contra escritura, el daño de un ataque exitoso disminuye. Las indicaciones para contenedores individuales están en [Parchear PHP en contenedores Docker](https://phpsos.de/es/php2shell/docker-container-patchen/); para FrankenPHP, en [Proteger FrankenPHP](https://phpsos.de/es/server/frankenphp/).

En muchos clústeres, las aplicaciones PHP no funcionan solas. Con frecuencia hay contenedores sidecar para registros o métricas, imágenes auxiliares para migraciones de bases de datos y trabajos que solo se inician por la noche. También las imágenes de terceros, por ejemplo para un wiki, una interfaz de monitorización o un sistema de tickets, pueden contener PHP sin que se note en el nombre. Por eso no revise solo sus propias aplicaciones, sino todas las imágenes del clúster. Para las imágenes ajenas vale lo siguiente: espere una versión actualizada del fabricante, compruebe sus indicaciones sobre la versión de PHP incluida y limite la accesibilidad hasta que esté disponible. Si un sistema así solo funciona internamente, eso reduce el riesgo, pero no sustituye a la actualización.

## ¿Cómo ayuda PHP SOS en concreto?

- Registramos todas las cargas de trabajo con PHP, sus imágenes y digests y comprobamos la versión de PHP en los pods en ejecución.
- Mediante el [servicio de parcheo de PHP](https://phpsos.de/es/leistungen/php-patch-service/) recompilamos imágenes, las desplegamos y documentamos el estado por carga de trabajo.
- Conservamos los registros antes de la sustitución y buscamos rastros de un ataque.
- Con [monitorización de seguridad](https://phpsos.de/es/leistungen/security-monitoring/) y recompilaciones automatizadas conseguimos que el próximo parche llegue más rápido al clúster.


## Preguntas frecuentes

**¿Basta con actualizar la imagen base en el registro?**  
No. Los pods en ejecución siguen usando la imagen con la que se iniciaron. Solo un nuevo rollout con la imagen recompilada sustituye los pods. Después compruebe la versión de PHP en cada pod en ejecución.

**¿Por qué referenciar las imágenes por digest?**  
Una etiqueta puede apuntar a distintos estados de la imagen según cuándo se descargó. Un digest designa exactamente un estado. Así sabe con certeza qué código funciona en qué pod y los rollouts se vuelven trazables.

**¿Qué pasa con los CronJobs y los contenedores de inicialización?**  
También ellos pueden contener PHP y forman parte del inventario. Los CronJobs inician en cada ejecución pods nuevos a partir de su plantilla; por eso actualice la imagen en la plantilla. Los contenedores de inicialización se ejecutan al arrancar cada pod.

**¿Protege una NetworkPolicy frente a PHP2Shell?**  
No cierra la vulnerabilidad, pero puede limitar el daño. Quien restringe las conexiones salientes de los pods PHP dificulta la descarga de código malicioso y los movimientos laterales en el clúster.

## Fuentes

- [php.net: avisos de seguridad](https://www.php.net/)
- [Registro de cambios de PHP 8](https://www.php.net/ChangeLog-8.php)
- [OWASP Cheat Sheets](https://cheatsheetseries.owasp.org/)
- [BSI (Oficina Federal Alemana de Seguridad de la Información)](https://www.bsi.bund.de/)
