El 21 de octubre de 2026 el proyecto PHP publicó un aviso de seguridad por dos vulnerabilidades críticas de ejecución remota de código (RCE) sin autenticación, conocidas como php2shell. Ambas tienen un puntaje de 9.2 en CVSS v4.0 y CISA las agregó a su catálogo de vulnerabilidades explotadas activamente (KEV) el 26 de octubre de 2026.
Para PHP “no hay mitigaciones completas, actualizar es la única opción segura”.
Resumen
| CVE-2026-109618 | CVE-2026-109619 | |
|---|---|---|
| Tipo | RCE por corrupción ante falta de memoria (OOM) | RCE por estado global obsoleto (stale global state) |
| Advisory | GHSA-w8hw-w9fx-j79w | GHSA-6wmf-4rv5-p3rp |
| CVSS v4.0 | 9.2 | 9.2 |
| Autenticación | No requiere | No requiere |
| En KEV (CISA) | Sí, desde 26/10/2026 | Sí, desde 26/10/2026 |
¿En qué consisten?
CVE-2026-109618: corrupción por falta de memoria
Cuando PHP se queda sin memoria, el manejo del error puede interrumpir la ejecución mientras los datos internos de la petición están inicializados solo parcialmente. Luego, la limpieza de la petición puede tratar esos datos inválidos como válidos, lo que lleva a la corrupción de memoria y a la ejecución de código.
CVE-2026-109619: estado global obsoleto
Parte del estado interno que pertenece a una petición puede sobrevivir después de que se liberó la memoria que lo respalda. Una petición posterior atendida por el mismo worker puede usar ese estado obsoleto antes de que la inicialización normal lo reinicie. Es un caso del tipo use-after-free entre peticiones.
¿Quién las descubrió?
Las vulnerabilidades fueron descubiertas de forma independiente por Calif y por Wiz Research:
- Calif encontró la falla con GPT-5.6 Sol, dentro de Patch the Planet, una iniciativa de OpenAI para apoyar a mantenedores de código abierto. La investigación es de Ryan Austin.
- Wiz Research también las descubrió y reportó, usando Wiz Atlas, Gemini 4 Argon y GPT-5.6 Sol.
- OpenAI coordinó la respuesta: conectó a los mantenedores de PHP con proveedores como Wiz y Cloudflare, y con organismos de gobierno como CISA, para preparar protecciones antes de la divulgación.
- Los mantenedores de PHP lideraron la corrección y su publicación.
Detalle técnico según Calif
La idea de fondo es vieja: en 2004 Stefan Esser ya había encontrado una vulnerabilidad remota basada en el límite de memoria de PHP. Calif partió de esa historia y buscó “parientes” de ese bug que siguieran en el código.
El patrón es siempre el mismo:
publicar o destruir estado
→ hacer un trabajo que puede fallar
→ inicializar, confirmar o restaurar
si ocurre un error fatal en el medio:
→ se saltea el paso de confirmar o restaurar
→ otra parte del código confía en un estado falso
Paso 1: provocar un error de memoria a voluntad. Calif encontró dos formas:
- Saltear
post_max_size. PHP compara ese límite con elContent-Lengthdeclarado, pero no con los bytes que realmente procesa. Una petición chunked en HTTP/1.1, o sin largo en HTTP/2, pasa el control. - Inflar
$_FILESsin superarpost_max_size. Una parte multipart confilename=""no cuenta paramax_file_uploads, pero PHP igual crea seis entradas en$_FILESpor cada una. Con nombres anidados comofiles[a][b][c]..., cientos de estos registros ocupan más de los 128 MiB de memoria por defecto con un cuerpo de menos de 8 MiB.
Paso 2: interrumpir PHP en un punto que deje estado roto. Calif encontró tres:
| Punto de interrupción | Dónde es explotable | Versiones |
|---|---|---|
| Alta de un elemento en una tabla hash (PHP cuenta el elemento antes de terminar de crearlo) | mod_php, contra cualquier script PHP |
PHP 7.3 o superior |
| Upload progress de sesiones (las variables globales de sesión quedan apuntando a memoria liberada) | mod_php, contra cualquier script PHP |
PHP 5.4.0 o superior |
Estado del deserializador genérico (unserialize) |
mod_php y PHP-FPM, según la aplicación |
— |
Esto explica por qué mod_php es el caso más grave: si PHP falla al iniciar una petición, mod_php libera la memoria pero reutiliza el mismo proceso, y la siguiente petición consume el estado roto. PHP-FPM, en cambio, termina el worker ante ese error. Para atacar PHP-FPM hace falta que la aplicación deserialice datos, por ejemplo con session_start(), unserialize() o maybe_unserialize() de WordPress.
Calif confirmó RCE sin autenticar en WordPress, Drupal, Joomla, MediaWiki, Roundcube, Magento, phpMyAdmin, Nextcloud, Laravel, Symfony y WHMCS.
Detalle técnico según Wiz Research
Wiz describe el mismo origen: todas son problemas de seguridad de memoria en cómo PHP maneja los errores fatales durante una petición, en especial los de falta de memoria: el error deja un estado interno corrupto que otra petición o worker reutiliza después.
Wiz reportó cuatro bugs:
| Bug | Qué permite | Qué demostró Wiz |
|---|---|---|
| Use-after-free en el deserializador de upload progress de sesiones | Corromper memoria y ejecutar código | RCE sin autenticar en WordPress, Drupal y Joomla |
| Divulgación remota de memoria del proceso | Leer memoria del worker sin autenticar | Filtración de memoria independiente de la aplicación |
| Use-after-free en el backtrace de errores fatales | Corromper memoria y ejecutar código | RCE sin autenticar en Drupal |
| Confusión de tipos en OPcache | Corromper el estado compartido de PHP y ejecutar código | RCE sin autenticar en WordPress |
La divulgación de memoria es similar a Heartbleed: PHP copia contenido de memoria liberada dentro de la cookie PHPSESSID de la respuesta. Esa memoria puede contener contraseñas, tokens, claves de API y certificados de otras peticiones. Funciona aunque la aplicación nunca llame a session_start().
WordPress, Drupal y Joomla son solo ejemplos: Wiz aclara que incluso una aplicación “Hello World” sobre una versión afectada puede ser vulnerable. También aclara que existen otras variantes además de estos cuatro bugs, y que la corrección de PHP las resuelve de raíz.
Wiz agrupa estos bugs bajo los dos CVE de forma algo distinta a como los describe PHP (por ejemplo, ubica el bug de upload progress en CVE-2026-109618, mientras que PHP lo mitiga en CVE-2026-109619). En este post sigo las descripciones y mitigaciones del aviso oficial de PHP.
El rol de la IA
El código vulnerable existía desde hacía más de una década. Explotarlo requería encadenar varios bugs y adaptarse a cómo PHP reutiliza la memoria en cada versión y configuración.
- Wiz afirma que la IA hizo práctico desarrollar y adaptar exploits funcionales en horas: lo que antes habría llevado meses de trabajo a un equipo, un investigador lo completó en una semana.
- Calif aclara que no usó herramientas especiales ni modelos que no estuvieran disponibles para todos. La clave fue conocer bien el objetivo y su historial de vulnerabilidades: los modelos no buscan solos primitivas de explotación de hace veinte años, hay que guiarlos hacia ahí. Después le pidieron al modelo que generalizara el patrón del primer bug, y así encontraron los siguientes.
- OpenAI lo considera uno de los problemas de seguridad de mayor impacto de los últimos tiempos. Advierte que las mismas capacidades pueden ayudar a los atacantes a desarrollar exploits rápido, y que espera que los hallazgos de este tipo aumenten en los próximos meses.
Cronología
| Fecha | Evento |
|---|---|
| 2004 | Stefan Esser descubre la primera vulnerabilidad remota de PHP basada en el límite de memoria |
| 2020 | Se reporta el bug #78876 de PHP (variables largas en multipart causan falta de memoria) |
| 2024 | OSTIF y Quarkslab identifican un bug relacionado, sin demostrar que sea explotable |
| 01/08/2026 | Calif descubre varios caminos independientes hacia RCE |
| 11/08/2026 | Calif reporta el primer bug a PHP e inicia la divulgación coordinada |
| 14/08/2026 | Calif comparte una prueba de concepto de RCE con PHP |
| 15/08/2026 | PHP confirma que la prueba de concepto funciona |
| 19/08/2026 | Wiz descubre su primera vulnerabilidad |
| 21/08/2026 | Calif reporta el segundo bug a PHP |
| 24/08/2026 | Wiz reporta las vulnerabilidades a PHP |
| 21/09/2026 | Según Wiz, PHP confirma sus reportes y empieza a desarrollar la corrección |
| 21/10/2026 | PHP publica las versiones corregidas y se hace la divulgación pública |
Cómo se realiza la explotación, paso a paso
Esta sección explica el mecanismo del ataque para entender por qué la actualización es la única defensa real. Es una vista conceptual basada en lo que publicaron Calif y Wiz; no incluye el payload ni el código del exploit.
La idea de fondo
Todas estas fallas siguen el mismo patrón. PHP primero “anuncia” que un dato interno existe y después lo termina de construir. Si en el medio ocurre un error fatal (típicamente por falta de memoria), el paso de construir o de limpiar se saltea, pero el dato quedó anunciado. Más tarde, otra parte de PHP confía en ese dato a medio hacer.
Paso 1: provocar el error de memoria
El atacante necesita que PHP se quede sin memoria en el momento justo. Para eso tiene que superar el límite memory_limit sin que post_max_size frene la petición antes. Calif describe dos maneras de lograrlo:
- Enviar la petición de forma que PHP no pueda medir su tamaño real por anticipado (por ejemplo, chunked en HTTP/1.1 o sin largo declarado en HTTP/2).
- Usar muchas partes de formulario vacías con nombres muy anidados: cada una ocupa poca red, pero obliga a PHP a crear muchas estructuras internas en memoria.
El resultado es que el atacante decide en qué operación interna va a fallar PHP.
Paso 2: dejar un estado "colgado" y que el worker sobreviva
El error tiene que ocurrir antes de que PHP termine de iniciar la petición. En ese punto, variables internas de PHP (por ejemplo, las de la sesión o las del deserializador) ya quedaron apuntando a memoria de la petición. Como la petición falla a medio iniciar, PHP libera esa memoria pero no ejecuta la limpieza que borraría esas variables. Quedan apuntando a memoria liberada.
Acá aparece la diferencia clave entre servidores:
Paso 3: una segunda petición consume el estado roto
Con el worker todavía vivo y las variables colgadas, el atacante manda una segunda petición que llega a la función de upload progress de sesiones. Esa función se ejecuta muy temprano, antes de que PHP reinicie esas variables, así que reutiliza el estado obsoleto. Mientras tanto, los datos de esta segunda petición ocupan la memoria que había quedado libre, de modo que el atacante controla su contenido.
a memoria liberada. El worker sobrevive. At->>W: Petición B — upload progress de sesiones Note over At,W: PHP reutiliza el estado obsoleto. Los datos
de B ocupan la memoria que quedó libre. W-->>At: Lectura de memoria / ejecución de código
Según el bug concreto, esto le da al atacante dos capacidades:
- Leer memoria de otras peticiones o del propio servidor, que puede contener contraseñas, tokens y claves (similar a Heartbleed).
- Controlar dónde escribe PHP un puntero y su tipo, lo que se encadena hasta la ejecución remota de código sin autenticación.
Por qué no hay mitigación completa
Las mitigaciones temporales cierran algún camino puntual (por ejemplo, apagar upload_progress corta la vía de la segunda petición confirmada), pero el problema de raíz —que PHP confíe en estado dejado por una petición que falló— sigue ahí y tiene otras variantes. Por eso la única solución completa es actualizar.
| 21/10/2026 | Cloudflare despliega reglas de WAF (3:02 UTC) |
| 23/10/2026 | PHP publica el aviso informativo sobre CVE-2026-115560 |
| 26/10/2026 | CISA agrega ambos CVE al catálogo KEV |
Explotación activa
Según datos de Wiz citados por The Hacker News, al 25 de octubre de 2026 el porcentaje de organizaciones significativamente afectadas había bajado al 52,1%. Wiz observó dos tipos de actividad:
- Intentos de explotación que coinciden con las pruebas de concepto (PoC) públicas.
- Herramientas con la marca “PHP2Shell” que en realidad no usan estas vulnerabilidades, sino envenenamiento de sesiones y una inclusión local de archivos (LFI) en la aplicación.
Wiz también señala que agotar la memoria no alcanza por sí solo para completar el exploit: las diferencias entre compilaciones de PHP, límites de memoria y comportamiento de los workers pueden hacer fallar las etapas siguientes. Esto no es motivo para demorar la actualización: como las PoC son públicas, mejorarlas es cuestión de tiempo.
¿Quién está afectado?
Según PHP, todas las instalaciones de PHP que atienden peticiones web, incluyendo:
- PHP-FPM
- Apache con
mod_php php-cgi- FrankenPHP
- LiteSpeed
El riesgo es mayor con mod_php, donde hay un exploit demostrado en el que una petición sin autenticar dispara el ataque antes de que se ejecute cualquier código de la aplicación. Es decir, no importa qué tan segura sea la aplicación.
Versiones corregidas publicadas por PHP:
| Rama | Versión corregida |
|---|---|
| 8.5 | 8.5.12 |
| 8.4 | 8.4.27 |
| 8.3 | 8.3.36 |
| 8.2 | 8.2.35 |
| 8.1 y anteriores | Sin soporte (ver abajo) |
Cualquier versión anterior a estas dentro de cada rama es vulnerable.
PHP 8.1 y anteriores ya no reciben actualizaciones del proyecto PHP. Aun así, PHP publicó backports mínimos del código fuente para 7.4, 8.0 y 8.1, y algunos proveedores con soporte extendido (LTS) también los distribuyen.
PHP 8.2 llega a su fin de vida el 31 de diciembre de 2026, así que conviene planificar la migración a 8.3 o superior.
¿Qué hacer?
1. Actualizar
Es la única solución completa. Actualizar el código del sitio o sus plugins no alcanza: hay que actualizar PHP. Si el hosting administra PHP, hay que pedirle que aplique la actualización.
Las recomendaciones de CISA son:
- Inventariar todas las instalaciones de PHP.
- Actualizar de inmediato, empezando por los sistemas expuestos a Internet.
- Si no es posible actualizar ahora, o se usa PHP 8.1 o anterior, sacar de línea los sistemas hasta poder corregirlos.
- Monitorear workers de PHP que lancen shells o descarguen herramientas.
Como el ataque ocurre por debajo de la aplicación, sus logs pueden aportar poco contexto. Wiz recomienda prestar atención a:
- Peticiones multipart inusuales seguidas de errores de límite de memoria o de respuestas HTTP 500 repetidas.
- Cookies
PHPSESSIDinesperadamente grandes o malformadas en las respuestas. - Reinicios de workers de PHP sin explicación.
Un WAF puede dar algo de protección, pero no reemplaza la actualización.
OpenAI publicó un comprobador de versiones de PHP como habilidad de Codex, como parte de Patch the Planet, para ayudar a identificar instalaciones potencialmente vulnerables.
Para verificar la versión instalada:
php -v
Algunas distribuciones aplican el backport sin cambiar el número de versión, así que conviene revisar también el changelog del paquete de la distribución.
2. Mitigaciones temporales (no completas)
Solo para ganar tiempo mientras se actualiza. Después de cambiar la configuración hay que reiniciar todos los workers.
CVE-2026-109618
; Elimina el límite controlable, aunque una falla de asignación real
; todavía puede llegar al camino vulnerable
memory_limit = -1
; Bajo si no se necesitan subidas de archivos, 32M si se necesitan
post_max_size = 8M
; Siempre menor a post_max_size
upload_max_filesize = 4M
- Preferentemente con
php_admin_valueen el pool de FPM o en la configuración de Apache. - Cuidado: como advierte Calif,
memory_limit = -1quita el tope de memoria de PHP, lo que aumenta el riesgo de agotar la memoria del servidor. Por eso conviene combinarlo con los límites de contenedor o cgroup del punto siguiente. - Limitar en el servidor web o proxy el tamaño de las peticiones, la cantidad de campos, partes multipart, cabeceras y profundidad de anidamiento.
- Usar límites de memoria por contenedor o cgroup. PHP advierte no usar
RLIMIT_ASniRLIMIT_DATA.
CVE-2026-109619
; Bloquea los caminos confirmados por sesiones, no otras variantes
session.upload_progress.enabled = 0
; Solo PHP 8.5: bloquea el camino confirmado de backtraces fatales
fatal_error_backtraces = 0
- Configurarlo en
php.ini, en el pool de FPM o en el servidor, de forma que aplique antes de procesar la petición. No sirveini_set()ni.user.inide FPM. - Quitar configuraciones por petición inválidas o deprecadas que generen diagnósticos antes de la inicialización. Ocultar los diagnósticos no ayuda.
- Corregir errores fatales y timeouts que un atacante pueda provocar.
Actualización 23/10/2026: PHP publicó un aviso informativo sobre otro problema, CVE-2026-115560, que afecta incluso a las versiones ya corregidas (como 8.5.12). Solo aplica a configuraciones poco comunes, en las que
serialize_handlerse cambia en tiempo de ejecución. Se corregirá en la próxima versión regular de PHP. El aviso recuerda quesession.upload_progress.enabled = 0ya figuraba como mitigación en GHSA-6wmf-4rv5-p3rp.
Caso Cloudflare
Cloudflare desplegó reglas de WAF el 21 de octubre de 2026 a las 3:02 UTC, unas horas antes de la divulgación pública. Están activas por defecto en todos los planes con WAF, incluido el gratuito:
| Plan | Ruleset | Reglas |
|---|---|---|
| Free | Cloudflare Managed Free Ruleset | PHP Remote Code Execution Attack (CVE-2026-109618, CVE-2026-109619) #1 a #7 |
| Pro, Business, Enterprise | Cloudflare Managed Ruleset | PHP Remote Code Execution Attack (CVE-2026-109618, CVE-2026-109619) #1 a #7 |
- En los planes pagos conviene revisar que el Managed Ruleset esté desplegado en modo block.
- Además, la regla Cloudflare Managed Response Firewall Default analiza la respuesta del servidor de origen y puede bloquearla antes de que llegue al atacante.
- Los eventos se pueden revisar en Security > Security Analytics > Events, filtrando por las reglas.
Cloudflare informó que observó tráfico de ataque contra sus clientes, con atacantes modificando los payloads para evadir las reglas. Por eso el WAF ayuda a ganar tiempo, pero no reemplaza la actualización de PHP.
Caso AWS
AWS informó que sus propios servicios no están afectados, pero sí los clientes que corren PHP vulnerable en ellos:
| Servicio | Acción |
|---|---|
| Amazon Linux | Paquetes actualizados disponibles, aplicarlos |
| Elastic Beanstalk | Nuevas versiones de plataforma PHP 8.2 a 8.5; con actualizaciones gestionadas se aplican en la próxima ventana de mantenimiento |
| Lightsail | Blueprints actualizados; las instancias existentes no se actualizan solas, hay que crear nuevas y migrar |
| Lambda | No hay runtime PHP gestionado; actualizar imágenes o runtimes propios y redesplegar |
| CodeBuild | Imágenes actualizadas desde el 30/10/2026; actualizar si se fijó una versión de imagen |
| EMR (EC2) | Afectados clústeres con Ganglia (EMR 4.2.0 a 6.15.0); migrar a EMR 7.x o no instalar Ganglia |
| AWS WAF | Grupo de reglas gestionadas de PHP actualizado; actualizar si se fijó una versión |
| WorkMail | Corregido por AWS, sin acción del cliente |
Fuentes
Fuente oficial:
Fuentes complementarias:
- Calif Research: PHP2Shell, a tale of two PHP remote vulnerabilities
- OpenAI: Patch the Planet: respuesta global a vulnerabilidades críticas descubiertas por agentes (21/10/2026)
- Wiz Research: PHP2Shell: AI uncovers critical RCE vulnerabilities affecting 70% of the Internet (21/10/2026)
- Cloudflare: Cloudflare deploys protections against php2shell vulnerability
- CISA: Critical Vulnerabilities in PHP Require Immediate Patching
- University of Washington IT: PHP CVEs
- AWS: Boletín de seguridad 2026-143-AWS
- The Hacker News: Hackers Actively Exploit Highly Critical Drupal Commerce Core Authorization Bypass Flaw (30/10/2026)
Más sobre conceptos relacionados en Amenaza vs Riesgo vs Vulnerabilidad.