CVE-2026-109618 y CVE-2026-109619 en PHP: cómo saber si te afecta y cómo actualizar hoy
Índice de contenidos
- Puntos clave
- Qué corrigen CVE-2026-109618 y CVE-2026-109619
- Quién corre más riesgo según cómo sirves PHP
- Qué versiones están afectadas y cuáles corrigen
- Cómo comprobar tu versión de PHP
- Cómo actualizar PHP en Docker, Debian, Ubuntu y Alpine
- Imagen oficial de Docker
- Debian y Ubuntu
- Repositorio de Ondřej Surý y Alpine
- Cómo mitigar si no puedes actualizar todavía
- Cómo verificar que la corrección está activa
- Preguntas frecuentes
- ¿Me afecta si solo uso PHP desde la línea de comandos?
- ¿Basta con desactivar session.upload_progress?
- ¿Qué hago con PHP 8.1 o 7.4?
- Conclusión
- Fuentes
CVE-2026-109618 y CVE-2026-109619 son dos fallos críticos de PHP (CVSS 9,2) que permiten ejecutar código sin autenticación. Afectan a PHP 8.2, 8.3, 8.4 y 8.5 por debajo de 8.2.35, 8.3.36, 8.4.27 y 8.5.12, publicadas el 21 de octubre de 2026. La única corrección completa es actualizar y reiniciar los procesos de PHP.
El 21 de octubre de 2026 el proyecto PHP publicó las versiones 8.5.12, 8.4.27, 8.3.36 y 8.2.35 para corregir dos vulnerabilidades críticas que permiten ejecutar código en el servidor sin autenticación. Son CVE-2026-109618 (GHSA-w8hw-w9fx-j79w) y CVE-2026-109619 (GHSA-6wmf-4rv5-p3rp), las dos con una puntuación CVSS 4.0 de 9,2. Aquí tienes qué hace cada una, qué versiones afectan, cómo comprobar la tuya en Docker, Debian y Ubuntu, cómo actualizar y qué ajustes reducen la exposición si no puedes actualizar hoy. Los datos de paquetes e imágenes son de las 16:30 (hora peninsular) del mismo día. También está la versión en inglés de esta guía.
Puntos clave
- Afectan a PHP 8.2 por debajo de 8.2.35, a 8.3 por debajo de 8.3.36, a 8.4 por debajo de 8.4.27 y a 8.5 por debajo de 8.5.12. PHP 8.1 y anteriores no tienen versión oficial corregida.
- El riesgo más alto es Apache con mod_php: el aviso describe un ataque con una petición sin autenticar que se dispara antes de que corra tu aplicación. PHP-FPM, php-cgi, FrankenPHP y LiteSpeed también están en el aviso.
- La única corrección completa es actualizar y reiniciar todos los procesos de PHP. Las mitigaciones por configuración cortan caminos concretos, no el fallo.
- Debian 13 ya tiene
php8.48.4.27 entrixie-securityy Ubuntu publicó el aviso USN-8948-1. Las etiquetas 8.4.27 y 8.3.36 de la imagen oficialphpde Docker Hub todavía no estaban publicadas. - En Ubuntu,
php -vsigue diciendo 8.3.6 aunque el paquete esté corregido: compara la versión del paquete, no la de PHP.
Qué corrigen CVE-2026-109618 y CVE-2026-109619
Los dos fallos dejan a PHP usando memoria que ya no es válida, y un atacante puede convertir eso en ejecución de código con los permisos del proceso web. El aviso de seguridad de php.net[1] los resume así, y los avisos de GitHub del repositorio php/php-src dan el detalle técnico.
CVE-2026-109618, "RCE via OOM corruption". Cuando una petición agota la memoria (OOM, out of memory), PHP sale del contexto actual con longjmp(). Si eso ocurre mientras parte de la memoria de la petición está a medio inicializar, el cierre de la petición la lee como si fuera válida. Según el aviso GHSA-w8hw-w9fx-j79w[2], una subida multipart puede llegar al OOM sin pasar de post_max_size: partes con cabeceras sin límite, cuerpos sin longitud declarada útil o campos de archivo vacíos que no cuentan para max_file_uploads.
CVE-2026-109619, "RCE via stale global state". PHP guarda estado global (errores, sesión, objetos, extensiones) que apunta a memoria de una petición. Si un error fatal interrumpe la operación antes de limpiar ese estado, la siguiente petición atendida por el mismo proceso puede usarlo antes de inicializarse. El aviso GHSA-6wmf-4rv5-p3rp[3] confirma dos caminos: el progreso de subida de sesión (session.upload_progress), activo por defecto, y en PHP 8.5 las trazas de errores fatales (fatal_error_backtraces).
La corrección es la misma para los dos. El parche elimina el longjmp() del OOM, lo cambia por una parada ordenada en el siguiente punto seguro de la máquina virtual y limpia ese estado global entre peticiones. El ChangeLog de cada versión lo recoge en una sola línea: "Avoid state corruption via bailout".
Quién corre más riesgo según cómo sirves PHP
El modo en que sirves PHP cambia cuánto te expone el fallo, aunque ninguno queda fuera. El aviso de php.net lo dice en una frase: "We consider the risk highest for mod_php, with a demonstrated exploit where an unauthenticated request can trigger the attack before any application code runs."
| Forma de servir PHP | Qué dicen los avisos |
|---|---|
| Apache con mod_php | RCE completa demostrada sin autenticar, antes de que corra la aplicación |
PHP-FPM (nginx, Caddy, Apache con mod_proxy_fcgi) |
RCE por la sesión validada; para el OOM, susceptible por análisis del código, sin exploit completo |
| FrankenPHP | Probablemente susceptible al OOM por análisis del código |
| LiteSpeed (LSAPI) | Se comporta como FPM; exploits ligados a la aplicación, probables pero sin validar |
| php-cgi | En la lista de php.net, sin detalle en los avisos |
En FPM hay un detalle que conviene revisar hoy. Si tu nginx o Apache pasa ajustes por petición con PHP_VALUE o PHP_ADMIN_VALUE y alguno genera un aviso (por ejemplo, una directiva obsoleta), esa petición se convierte en un consumidor del estado viejo. Búscalo con grep -rn PHP_VALUE /etc/nginx /etc/apache2.
Ya circulan supuestos exploits. Desde la madrugada del 21 de octubre, antes de la publicación oficial, GitHub acumula repositorios con pruebas de concepto llamadas "php2shell". La búsqueda del CVE devolvía 98 a las 16:25.
No he ejecutado ni revisado ninguno. Trata ese código como no confiable, porque los falsos exploits con malware son habituales tras un CVE así.
Qué versiones están afectadas y cuáles corrigen
Estás afectado si usas PHP 8.2, 8.3, 8.4 u 8.5 por debajo de la versión corregida de tu rama. El registro del CVE[4], publicado por el propio proyecto PHP como CNA, da estos rangos para los dos fallos:
| Rama | Afectada | Corregida en |
|---|---|---|
| 8.5 | Por debajo de 8.5.12 | 8.5.12 |
| 8.4 | Por debajo de 8.4.27 | 8.4.27 |
| 8.3 | Por debajo de 8.3.36 | 8.3.36 |
| 8.2 | Por debajo de 8.2.35 | 8.2.35 (la rama termina el 31 de diciembre de 2026) |
| 8.1, 8.0 y 7.4 | Sin versión oficial | Parches de código fuente publicados por el equipo de seguridad |
El registro solo enumera de 8.2 a 8.5, pero php.net dice que, por la gravedad, el equipo publicó parches mínimos para compilar 7.4, 8.0 y 8.1. Si usas una de esas, depende de tu distribución o de un proveedor de soporte extendido. La NVD recibió los dos CVE a las 14:17 UTC y aún no los había analizado, así que su página no añade nada al registro del CVE.
Cómo comprobar tu versión de PHP
Comprueba la versión del binario que atiende las peticiones, no solo la del php de la interfaz de línea de comandos. En Debian y Ubuntu son paquetes distintos (php8.4-cli, php8.4-fpm, libapache2-mod-php8.4), y el de FPM o Apache puede ir por detrás. Este script compara la versión con la primera corregida de su rama:
<?php
// Rama => primera versión corregida (CVE-2026-109618/109619)
$fixed = ['8.2' => '8.2.35', '8.3' => '8.3.36',
'8.4' => '8.4.27', '8.5' => '8.5.12'];
$branch = PHP_MAJOR_VERSION . '.' . PHP_MINOR_VERSION;
if (!isset($fixed[$branch])) {
echo PHP_VERSION, ": rama sin version oficial corregida\n";
} elseif (version_compare(PHP_VERSION, $fixed[$branch], '<')) {
echo PHP_VERSION, ": VULNERABLE, actualiza a ", $fixed[$branch], "\n";
} else {
echo PHP_VERSION, ": corregida\n";
}
Guárdalo como check.php y ejecútalo con el mismo binario que usa tu web. Contra tres imágenes oficiales que tenía descargadas, el resultado fue este:
$ for i in php:8.3-cli php:8.4-fpm-alpine php:8.5-cli; do
> docker run --rm -v "$PWD/check.php:/check.php:ro" "$i" php /check.php
> done
8.3.31: VULNERABLE, actualiza a 8.3.36
8.4.26: VULNERABLE, actualiza a 8.4.27
8.5.10: VULNERABLE, actualiza a 8.5.12
En un contenedor en marcha, docker compose exec mi_servicio_php php -v da la versión sin montar nada. Para FPM instalado desde paquetes, php-fpm8.4 -v (o php-fpm8.3 -v) enseña la del binario de FPM. Si prefieres una página phpinfo(), bórrala en cuanto la mires: expone la configuración entera.
El script falla con los paquetes de Ubuntu. Ubuntu retroporta el parche sin cambiar la versión de PHP, así que un Ubuntu 24.04 corregido sigue diciendo 8.3.6. Ahí manda la versión del paquete, que se ve en la sección de actualización.
Cómo actualizar PHP en Docker, Debian, Ubuntu y Alpine
Actualizar es cambiar el paquete o la imagen y reiniciar todos los procesos de PHP. Un reload que deja vivos procesos antiguos no basta, porque el fallo vive en el binario cargado.
Imagen oficial de Docker
El repositorio de la imagen oficial, docker-library/php[5], fusionó el cambio a las cuatro versiones a las 16:19 hora peninsular. A las 16:30, Docker Hub todavía no servía las etiquetas 8.4.27 ni 8.3.36, aunque la petición para publicarlas en el repositorio de imágenes oficiales ya estaba abierta. Cuando aparezcan, sube la etiqueta en tu compose.yaml y recrea el servicio:
sed -i 's/php:8.4.26-fpm/php:8.4.27-fpm/' compose.yaml
docker compose pull
docker compose up -d
docker compose exec mi_servicio_php php -v
Si tu imagen se construye FROM php:8.4-fpm, reconstrúyela con docker compose build --pull para que baje la base nueva. Una etiqueta móvil como 8.4-fpm no se actualiza sola si la imagen ya está descargada. Para automatizar el pull tienes Watchtower, y Trivy o Grype detectan qué imágenes de tu registro siguen con un PHP vulnerable.
Debian y Ubuntu
En Debian 13 (trixie), php8.4 8.4.27-1~deb13u1 ya está en trixie-security, aunque el aviso DSA aún no aparecía en la web de Debian. En Debian 12 (bookworm), php8.2 seguía en 8.2.34-1~deb12u1, sin corregir. Actualiza solo los paquetes de PHP y reinicia el servicio:
sudo apt update
apt list --upgradable 2>/dev/null | grep '^php'
sudo apt install --only-upgrade 'php8.4*'
sudo systemctl restart php8.4-fpm # o apache2 si usas mod_php
dpkg -l 'php8.4-fpm' | tail -1
En Ubuntu, el aviso USN-8948-1[6] corrige tres ramas. Ubuntu 24.04 recibe php8.3 8.3.6-0ubuntu0.24.04.13, la 22.04 php8.1 8.1.2-1ubuntu2.28 y la 26.04 php8.5 8.5.4-0ubuntu1.5. Los mismos comandos sirven cambiando el número de rama. Ojo con la arquitectura: en un contenedor arm64 de Ubuntu 24.04, el espejo ports.ubuntu.com seguía ofreciendo la versión .12 a las 16:30.
Repositorio de Ondřej Surý y Alpine
Si instalas PHP desde packages.sury.org[7], el índice amd64 de bookworm ya tenía 8.4.27 y 8.3.36, fechados el 21 de octubre. En arm64 seguía 8.4.26, así que comprueba con apt-cache policy php8.4-fpm antes de dar el servidor por corregido. En Alpine, php84 estaba en 8.4.26-r0 y php83 en 8.3.35-r0 incluso en edge. Si dependes de rpms.remirepo.net, php.net avisa de que el repositorio no tendrá actualizaciones hoy y recomienda pasar a los paquetes de la distribución o compilar.
Cómo mitigar si no puedes actualizar todavía
Las mitigaciones reducen la exposición a caminos concretos, pero ninguna sustituye a la actualización, y así lo dicen los dos avisos. El anuncio de 8.4.27 lo deja claro: "There are no complete mitigations, updating is the only safe choice." Estas son las medidas que proponen:
| Medida | Qué corta | Límite |
|---|---|---|
memory_limit=-1 fijado por administración |
El OOM controlable de CVE-2026-109618 | Un fallo real de mmap() sigue llegando al camino vulnerable |
post_max_size bajo (8M sin subidas, 32M con ellas) |
Cuerpos grandes que empujan al OOM | No cubre las cabeceras multipart sin límite |
| Límites en el proxy: tamaño, partes, cabeceras y anidamiento | Peticiones diseñadas para agotar memoria | Debe cubrir peticiones sin Content-Length útil |
session.upload_progress.enabled=0 |
El camino de sesión de CVE-2026-109619 | No cubre otros estados globales |
fatal_error_backtraces=0 (solo PHP 8.5) |
El camino de las trazas de errores fatales | Solo ese camino |
| Quitar ajustes por petición que generen avisos | El consumidor previo a la inicialización | Ocultar los avisos con @ o error_reporting no sirve |
Pon estos ajustes donde PHP los lea al arrancar el proceso, nunca con ini_set() ni en .user.ini. En la imagen oficial basta un archivo en conf.d. Lo comprobé con php:8.4-fpm-alpine montando este archivo como /usr/local/etc/php/conf.d/zz-cve-2026-1096.ini:
session.upload_progress.enabled = 0
memory_limit = -1
post_max_size = 8M
Con el archivo montado, php-fpm -i devolvió session.upload_progress.enabled => Off, memory_limit => -1 y post_max_size => 8M, y php-fpm -t validó la configuración. En un pool de FPM instalado por paquete, el equivalente es php_admin_value[memory_limit] = -1 y php_admin_flag[session.upload_progress.enabled] = off, que la aplicación no puede sobrescribir. Después, reinicia todos los procesos.
Dos valores por defecto explican por qué estos ajustes importan. En las tres imágenes oficiales que probé (8.3.31, 8.4.26 y 8.5.10), session.upload_progress.enabled está activo, y en 8.5.10 fatal_error_backtraces también. memory_limit=-1 quita el techo de memoria, así que acompáñalo de un límite de memoria del contenedor o del cgroup. El aviso desaconseja RLIMIT_AS y RLIMIT_DATA, porque hacen fallar mmap() y llevan justo al camino vulnerable.
Cómo verificar que la corrección está activa
La verificación consiste en confirmar que cada proceso que atiende peticiones ejecuta el binario nuevo. Ejecuta el script de comprobación con el binario de FPM o de Apache, no solo con el de la línea de comandos. En Debian o Ubuntu, dpkg -l debe enseñar la versión corregida del paquete, y systemctl status php8.4-fpm una hora de arranque posterior a la actualización.
Revisa también que no queden procesos viejos. Con FPM, el proceso maestro y los hijos deben haber arrancado después del apt upgrade; con Docker, docker compose ps debe mostrar el contenedor recreado. Si el servidor tiene más de un pool o más de una versión de PHP instalada, repite la comprobación en cada una. Cuando se publique la DSA de Debian para bookworm o la nueva imagen de Alpine, repite el proceso en esos hosts.
Si ya habías aplicado las mitigaciones de CVE-2026-80521 en tus hosts Docker, el patrón es el mismo: primero inventario, luego parche y reinicio, y solo después las mitigaciones que quieras conservar.
Preguntas frecuentes
¿Me afecta si solo uso PHP desde la línea de comandos?
Los avisos describen ataques contra instalaciones que sirven peticiones web: un atacante necesita enviar peticiones HTTP a un proceso de PHP que se reutiliza o que procesa subidas. Un script de cron sin entrada externa no encaja en ese escenario. Aun así, actualiza el paquete de la línea de comandos a la vez que el resto.
¿Basta con desactivar session.upload_progress?
No. Ese ajuste corta el camino de sesión de CVE-2026-109619, pero no el OOM de CVE-2026-109618 ni otros estados globales que el parche completo también limpia. El propio aviso recomienda dejarlo desactivado aunque actualices, si no usas la barra de progreso de subidas.
¿Qué hago con PHP 8.1 o 7.4?
php.net no publica versiones de esas ramas, pero su equipo de seguridad dejó parches mínimos de código fuente para 7.4, 8.0 y 8.1. Ubuntu 22.04 ya trae php8.1 8.1.2-1ubuntu2.28 con el parche. Fuera de una distribución con soporte, la salida es pasar a 8.3 o 8.4.
Conclusión
CVE-2026-109618 y CVE-2026-109619 permiten ejecutar código en un servidor PHP sin autenticación, y Apache con mod_php es el caso más expuesto. La corrección es PHP 8.5.12, 8.4.27, 8.3.36 u 8.2.35, o el paquete parcheado de tu distribución, más un reinicio de todos los procesos. Debian 13 y Ubuntu ya la tienen; la imagen oficial de Docker, Alpine y Debian 12 deberían llegar en las próximas horas.
Empieza hoy por ejecutar el script de comprobación en cada servidor y desactivar session.upload_progress donde no lo uses.
Fuentes: [1] Aviso de seguridad de php.net del 21 de octubre de 2026[1], [2] GHSA-w8hw-w9fx-j79w, RCE via OOM corruption[2], [3] GHSA-6wmf-4rv5-p3rp, RCE via stale global state[3], [4] Registro de CVE-2026-109618 en cve.org[4], [5] Registro de CVE-2026-109619 en cve.org[4], [6] ChangeLog de PHP 8[8], [7] Aviso USN-8948-1 de Ubuntu[6], [8] Tracker de Ubuntu para CVE-2026-109618[9], [9] Repositorio docker-library/php[5], [10] Repositorio de PHP de Ondřej Surý[7].