PHP2Shell (CVE-2026-109618, CVE-2026-109619): qué actualizar, qué revisar y cómo ayuda un WAF
Dos fallos críticos de PHP permiten ejecutar código en remoto sin autenticación. Actualiza a 8.5.12, 8.4.27, 8.3.36 u 8.2.35, desactiva el progreso de subida de sesión y revisa los registros en busca de las señales que explicamos aquí.
Por el equipo de seguridad de OpenWAF
En resumen. PHP2Shell es el nombre que los investigadores dieron a dos fallos críticos del motor de PHP, CVE-2026-109618 y CVE-2026-109619 (puntuación CVSS 4.0 de 9,2), publicados el 21 de octubre de 2026. Los dos pueden acabar en ejecución remota de código sin autenticación (RCE en PHP) con el usuario de PHP del servidor web. Están corregidos en PHP 8.5.12, 8.4.27, 8.3.36 y 8.2.35.
- Actualiza PHP ya y reinicia todos los procesos de PHP. Ningún cambio de configuración lo corrige del todo.
- Mientras tanto, pon
session.upload_progress.enabled=0enphp.inio en la configuración del pool, y bajapost_max_size. - Un tercer fallo, CVE-2026-115560, no está corregido en esas versiones. El mismo ajuste lo cubre hasta la próxima versión de mantenimiento de PHP.
- OpenWAF bloquea en el borde las peticiones que llevan el campo del progreso de subida de sesión (regla 10075). Es una medida provisional y no sustituye a la actualización.
Qué es PHP2Shell
PHP2Shell es una familia de fallos de seguridad de memoria en la forma en que PHP prepara y cierra cada petición web. La descubrieron investigadores de Wiz, Calif y Codex Security de OpenAI, que señalan que el código afectado se remonta a PHP 5.4. El proyecto PHP publicó dos avisos el 21 de octubre de 2026 y, a la vez, versiones nuevas de todas las ramas con soporte.
| CVE | Aviso | Qué falla | Impacto |
|---|---|---|---|
| CVE-2026-109618 | GHSA-w8hw-w9fx-j79w «RCE via OOM corruption» | Un error por falta de memoria puede interrumpir PHP cuando los datos de la petición solo están inicializados en parte. La limpieza de la petición trata después esos datos inválidos como válidos. | RCE sin autenticación. Validada por HTTP contra mod_php con los límites de memoria y de entrada por defecto. |
| CVE-2026-109619 | GHSA-6wmf-4rv5-p3rp «RCE via stale global state» | Un estado que pertenece a la petición puede sobrevivir a la memoria que lo respalda. La siguiente petición que atiende el mismo proceso puede usarlo antes de que se reinicie (un uso tras liberación). | RCE sin autenticación y fuga de memoria de otras peticiones. |
Los dos avisos tienen el mismo vector CVSS 4.0, AV:N/AC:H/AT:P/PR:N/UI:N/VC:H/VI:H/VA:H: accesible por la red, sin inicio de sesión, sin interacción del usuario y con impacto total en el servidor. La complejidad del ataque figura como alta, pero los investigadores demostraron exploits funcionales, así que no conviene fiarse de esa nota.
Cómo llega un atacante a los fallos
En CVE-2026-109618, el atacante provoca un error por falta de memoria en el peor momento. El aviso describe varias formas de hacerlo a través del analizador multipart:
- un cuerpo sin un
Content-Lengthutilizable se salta la comprobación depost_max_size; - cada parte multipart puede llevar cualquier número de cabeceras;
- los campos de fichero vacíos no cuentan para
max_file_uploads, pero generan metadatos igualmente, y los nombres de campo anidados multiplican el trabajo.
En CVE-2026-109619, una petición deja un estado obsoleto y otra posterior en el mismo proceso lo consume. Las vías confirmadas son:
- el progreso de subida de sesión, activado por defecto y que funciona sin que la aplicación llame nunca a
session_start(); - los avisos que generan los ajustes INI por petición (
php_valueen.htaccess, oPHP_VALUEen FPM); - el ajuste
fatal_error_backtracesde PHP 8.5.
A quién afecta
Según el proyecto PHP, corre riesgo cualquier instalación de PHP que atienda peticiones web. La interfaz (SAPI) con la que se ejecuta PHP cambia lo fácil que es el ataque:
| SAPI | Riesgo | Por qué |
|---|---|---|
| Apache mod_php | El más alto | mod_php ejecuta siempre el cierre de la petición, aunque el arranque haya fallado. El exploit demostrado se dispara antes de que se ejecute el código de la aplicación, así que da igual qué aplicación haya encima. |
| PHP-FPM (Nginx, proxy_fcgi de Apache, Caddy) | Alto | FPM termina el proceso hijo cuando falla el arranque, y no se ha mostrado un exploit completo de CVE-2026-109618 en FPM. La RCE por CVE-2026-109619 sí se validó en FPM con una operación adecuada de la aplicación. |
| php-cgi | Afectado | El proyecto PHP lo incluye entre las SAPI web afectadas. |
| FrankenPHP | Alto | Procesos de larga duración. El aviso lo considera probablemente vulnerable a ataques que no dependen de la aplicación. |
| LiteSpeed (LSAPI) | Afectado | Se consideran probables los exploits que dependen de la aplicación, pero no se han validado. |
Las webs con WordPress, Drupal o Joomla funcionan sobre estas mismas SAPI. Los investigadores informan de RCE previa a la autenticación en las tres, y la fuga de memoria de CVE-2026-109619 funciona sea cual sea la aplicación.
Versiones corregidas
| Rama | Corregido en | Notas |
|---|---|---|
| PHP 8.5 | 8.5.12 | Si aún no puedes actualizar, pon también fatal_error_backtraces=0. |
| PHP 8.4 | 8.4.27 | |
| PHP 8.3 | 8.3.36 | |
| PHP 8.2 | 8.2.35 | El soporte de seguridad termina el 31 de diciembre de 2026. |
| PHP 8.1, 8.0, 7.4 | Sin versión | Sin soporte. El equipo de seguridad de PHP publicó parches mínimos en código fuente como ramas: 8.1, 8.0 y 7.4. |
La versión candidata de PHP 8.6.0 publicada ese mismo día (RC4) también incluye las correcciones.
Paquetes de las distribuciones. Las distribuciones de Linux y los proveedores de soporte extendido recibieron los parches por adelantado. Un paquete puede llevar la corrección con un número de versión que parece antiguo, así que busca los CVE en su registro de cambios en lugar de comparar versiones. Por ejemplo:
apt changelog php8.2-fpm | grep -E 'CVE-2026-10961[89]' # Debian, Ubuntu
rpm -q --changelog php-fpm | grep -E 'CVE-2026-10961[89]' # RHEL, Alma, Rocky
php -v # solo compilaciones oficiales
Después de actualizar, reinicia todos los procesos de PHP: Apache si usas mod_php, cada pool de FPM y los procesos de FrankenPHP y LiteSpeed. Un proceso que sigue en marcha mantiene el código vulnerable en memoria.
Estado de la explotación
La publicación fue precipitada. La tarde antes de la fecha prevista se publicó por error un vídeo con una prueba de concepto, y The Hacker News informó de los primeros ataques y de «intentos de explotación activos» el 21 de octubre, el mismo día de los parches. Informaciones posteriores hablan de intentos registrados en honeypots desde el 17 de octubre y de variantes de la botnet Mirai que ya prueban los fallos. Por ahora ninguna fuente ha confirmado públicamente una intrusión con éxito. Con tanto escaneo, da por hecho que cualquier servidor PHP sin parchear recibirá intentos.
Mitigaciones parciales y sus límites
El proyecto PHP lo deja claro: solo actualizar es una solución completa. Las medidas siguientes reducen la exposición a vías de ataque concretas mientras programas la actualización. No hacen segura una instalación.
Para CVE-2026-109618 (corrupción por falta de memoria)
- memory_limit=-1, fijado donde las aplicaciones no puedan cambiarlo (
php_admin_valueen el pool de FPM o en la configuración de Apache). Así desaparece el fallo por límite de memoria de PHP que controla el atacante. Un fallo de asignación del sistema operativo todavía puede llegar al código vulnerable. - Un post_max_size bajo:
8Men webs sin subidas de ficheros y32Msi las necesitas, conupload_max_filesizepor debajo. - Límites de petición en el servidor web o en el proxy para el tamaño del cuerpo decodificado, el número de campos, de partes multipart y de cabeceras, y la profundidad de anidamiento. Tienen que cubrir también las peticiones sin un
Content-Lengthutilizable. - Un límite de memoria del contenedor o del cgroup como frontera de disponibilidad, a ser posible uno que mate solo el proceso afectado. No uses
RLIMIT_ASniRLIMIT_DATA: pueden provocar justo el fallo de asignación que necesita el ataque.
Para CVE-2026-109619 (estado global obsoleto)
- session.upload_progress.enabled=0 en
php.ini, en el pool de FPM o en la configuración del servidor, y después reinicia todos los procesos.ini_set()y el.user.inide FPM se aplican demasiado tarde y no sirven. Cierra las vías de sesión confirmadas, no todas las variantes. - En PHP 8.5, fatal_error_backtraces=0, que solo cierra la vía confirmada de las trazas de errores fatales.
- Quita los ajustes por petición no válidos u obsoletos que generan avisos antes de que empiece la petición. Ocultarlos con
error_reporting,display_errorso@no sirve. - Corrige los errores fatales y los tiempos de ejecución agotados que pueda provocar un atacante, también en callbacks, subidas, importaciones y código de limpieza.
; php.ini o pool de FPM (php_admin_value[...] = ...); después, reinicia todos los procesos
session.upload_progress.enabled = 0
post_max_size = 8M ; 32M si la web acepta subidas
upload_max_filesize = 4M ; siempre por debajo de post_max_size
fatal_error_backtraces = 0 ; solo PHP 8.5
Ojo a un cambio de comportamiento tras actualizar. Quedarse sin memoria ya no detiene PHP en el acto: el error salta en el siguiente punto seguro, y un segundo límite, duro y por encima de memory_limit, termina el proceso sin más. En ese caso no se ejecutan las funciones de cierre, así que revisa el código que dependa de register_shutdown_function() para registrar o limpiar tras un error de memoria.
Señales de ataque
Los investigadores citados por The Hacker News señalan estas pistas. Búscalas en los registros del servidor web, de PHP y de FPM desde el 17 de octubre:
- peticiones
multipart/form-dataextrañas, a menudo a URL que nunca reciben subidas, seguidas de errores «Allowed memory size exhausted» o de respuestas HTTP 500 repetidas; - cookies
PHPSESSIDanormalmente grandes en las respuestas; - procesos de PHP que se reinician o se caen sin motivo claro (
child exited on signalen FPM, fallos de segmentación en el registro de errores de Apache); - ráfagas de avisos antes de que se ejecute ningún script, avisos de limpieza o «Maximum execution time exceeded» en URL raras, que los avisos GHSA citan como señales que conviene revisar.
Mientras investigas, activa log_errors con error_reporting=E_ALL. Unos registros limpios no prueban nada: un exploit con éxito puede no dejar ningún error de PHP. Si encuentras estas señales en un servidor sin parchear, trátalo como posiblemente comprometido. Busca ficheros nuevos en directorios con permiso de escritura, tareas cron nuevas y conexiones salientes inesperadas del usuario de PHP, y cambia los secretos que pueda leer la aplicación.
La continuación: CVE-2026-115560
El 23 de octubre de 2026, dos días después de los parches, el proyecto PHP publicó un aviso informativo sobre otro vector de RCE, distinto y «poco probable», en el progreso de subida de sesión: CVE-2026-115560. Las versiones del 21 de octubre no lo corrigen.
Necesita una combinación poco habitual de configuración y código:
- la configuración pone
session.serialize_handlerenphp_binaryophp_serialize; - la aplicación lo cambia a
phpen tiempo de ejecución conini_set()antes de llamar asession_start(); - el progreso de subida de sesión sigue activado.
Las aplicaciones que nunca cambian el serializador en tiempo de ejecución no están expuestas. El proyecto PHP publicará la corrección y el aviso completo con la próxima versión de mantenimiento; no ha anunciado fecha ni versión. Su consejo es poner session.upload_progress.enabled=0 hasta entonces. Si ya lo hiciste por CVE-2026-109619, mantenlo.
Para comprobar si tu código cambia el serializador:
grep -rnE "ini_set\(\s*['\"]session\.serialize_handler" --include='*.php' .
Cómo protege OpenWAF tus webs
La regla 10075 está activa en el borde de OpenWAF. Bloquea cualquier petición en la que un argumento se llame PHP_SESSION_UPLOAD_PROGRESS (sin distinguir mayúsculas), esté en un cuerpo multipart, en un cuerpo URL-encoded o en la cadena de consulta. Es el campo que lee PHP para empezar el progreso de subida de sesión. Al descartarlo en el borde, esas peticiones no llegan al proceso de PHP, lo que cubre las vías de sesión confirmadas de CVE-2026-109619 y el vector de CVE-2026-115560.
Una regla de WAF es una medida provisional, y esta tiene límites claros:
- No cubre CVE-2026-109618 en general. Las vías de falta de memoria pasan por el propio analizador multipart, y una petición pensada para ellas no necesita ese campo. Los límites de tamaño y de tiempo de petición de cada web dificultan agotar la memoria, pero no lo corrigen.
- No cubre las vías de CVE-2026-109619 que dependen de la configuración del servidor, como los avisos INI por petición o
fatal_error_backtraces. - Solo reconoce el nombre de campo por defecto. Si una aplicación cambió
session.upload_progress.name, esta regla no bloquea las peticiones con el nombre nuevo. - Solo protege los nombres de host que pasan por OpenWAF. El tráfico que llega directamente a tu origen se la salta, así que limita el origen a OpenWAF siempre que puedas.
Las barras de progreso de subida legítimas usan el mismo campo, así que dejan de funcionar detrás de la regla. Si necesitas una, añade una excepción por web para la regla 10075 en esa ruta, y solo cuando el servidor ya tenga una versión de PHP corregida. Las webs con el WAF en modo solo registro anotan las peticiones que coinciden en lugar de bloquearlas.
La solución sigue siendo actualizar PHP. La regla te da tiempo para hacerlo.
Lista de comprobación
- Haz inventario de cada servidor, imagen de contenedor y cuenta de alojamiento con PHP, y anota la SAPI (mod_php, FPM, CGI, FrankenPHP, LiteSpeed).
- Actualiza a 8.5.12, 8.4.27, 8.3.36 u 8.2.35, o instala el paquete de tu distribución cuyo registro de cambios cite CVE-2026-109618 y CVE-2026-109619.
- En 7.4, 8.0 u 8.1, aplica el parche en código fuente o el paquete de tu proveedor de soporte extendido, y planifica el paso a una rama con soporte.
- Reinicia Apache, cada pool de FPM y todos los procesos de PHP de larga duración. Reconstruye y vuelve a desplegar las imágenes de contenedor.
- Pon
session.upload_progress.enabled=0enphp.inio en el pool hasta que salga la corrección de CVE-2026-115560, o para siempre si no usas el progreso de subida. - Hasta que todos los servidores estén parcheados, baja
post_max_size, aplica límites de petición en el proxy y ponfatal_error_backtraces=0en PHP 8.5. - Revisa los registros desde el 17 de octubre en busca de las señales anteriores, y trata como posiblemente comprometidos los servidores sin parchear que las muestren.
- Pon las webs PHP públicas detrás de un WAF que bloquee
PHP_SESSION_UPLOAD_PROGRESSmientras actualizas, y limita los orígenes al WAF.
Preguntas frecuentes
¿Se está explotando PHP2Shell?
Los intentos de explotación empezaron a las pocas horas de la publicación del 21 de octubre de 2026, según The Hacker News, que cita a Cloudflare, watchTowr y otros. Mientras escribimos esto ninguna fuente ha confirmado públicamente una intrusión con éxito, pero con escaneos masivos cualquier servidor PHP sin parchear es un objetivo.
Uso Nginx con PHP-FPM, no mod_php. ¿Me afecta?
Sí. El proyecto PHP incluye todas las instalaciones que sirven peticiones web: PHP-FPM, php-cgi, FrankenPHP y LiteSpeed. mod_php es el caso de mayor riesgo porque hay un exploit demostrado que se dispara antes de que se ejecute el código de la aplicación; en FPM se validó la ejecución remota de código por CVE-2026-109619 con una operación adecuada de la aplicación. Actualiza en cualquier caso.
Mi distribución sigue mostrando una versión antigua de PHP. ¿Soy vulnerable?
No necesariamente. Las distribuciones y los proveedores de soporte extendido recibieron los parches por adelantado y suelen aplicarlos sin cambiar el número de versión original. Busca CVE-2026-109618 y CVE-2026-109619 en el registro de cambios del paquete en vez de comparar números de versión.
¿Basta con session.upload_progress.enabled=0?
No. Corta las vías confirmadas de CVE-2026-109619 a través del progreso de subida de sesión y el vector de CVE-2026-115560, pero no la corrupción por falta de memoria de CVE-2026-109618 ni otras variantes. Solo actualizar PHP corrige PHP2Shell. Si no usas barras de progreso de subida, deja el ajuste desactivado también después de actualizar.
¿Me protege un WAF frente a PHP2Shell?
En parte. Un WAF puede descartar las peticiones que llevan el campo PHP_SESSION_UPLOAD_PROGRESS, como hace la regla 10075 de OpenWAF, y los límites de tamaño de petición dificultan agotar la memoria. No ve todas las vías de CVE-2026-109618 ni las de CVE-2026-109619 que dependen de la configuración. Tómalo como una medida provisional mientras actualizas.
¿Qué es CVE-2026-115560 y tiene parche?
Es un vector distinto y poco probable de ejecución remota de código en el progreso de subida de sesión, anunciado por el proyecto PHP el 23 de octubre de 2026. Necesita una configuración poco habitual: session.serialize_handler con php_binary o php_serialize en la configuración y cambiado a php con ini_set() antes de session_start(). Las versiones del 21 de octubre no lo corrigen; el parche y el aviso completo llegarán con la próxima versión de mantenimiento. Hasta entonces, pon session.upload_progress.enabled=0.
¿Qué hago con PHP 7.4, 8.0 u 8.1?
Esas ramas ya no reciben versiones. El equipo de seguridad de PHP publicó parches mínimos en código fuente para 7.4, 8.0 y 8.1, pensados para quien compila PHP; si no, pregunta a tu proveedor de soporte extendido o a tu distribución, o pasa a una rama con soporte.
Fuentes
- GHSA-w8hw-w9fx-j79w: RCE via OOM corruption (CVE-2026-109618) PHP, 21 oct 2026
- GHSA-6wmf-4rv5-p3rp: RCE via stale global state (CVE-2026-109619) PHP, 21 oct 2026
- Security advisory: Critical remote code execution vulnerabilities, update now php.net, 21 oct 2026
- Informational advisory: Session upload progress (CVE-2026-115560) php.net, 23 oct 2026
- PHP Issues Emergency Patches for Two Critical PHP2Shell RCE Flaws as Exploit Attempts Emerge The Hacker News, 21 oct 2026
- PHP Warns of Another Unpatched RCE Risk Two Days After Emergency PHP2Shell Patches The Hacker News
- CVE-2026-109618 record CVE Program, 21 oct 2026
- PHP2Shell (researchers’ site: Wiz, Calif, OpenAI Codex Security) PHP2Shell researchers
Temas
- PHP2Shell
- CVE-2026-109618
- CVE-2026-109619
- CVE-2026-115560
- PHP RCE
- session upload progress
- mod_php
- PHP-FPM
Autor
OpenWAF