Resumen: PHP2Shell (CVE-2026-109618, CVE-2026-109619)
- Qué pasó: el 2026-10-21 PHP publicó 8.5.12, 8.4.27, 8.3.36 y 8.2.35 para corregir dos fallos con CVSS 9.2 en el propio motor. Ambos pueden dar a un atacante sin cuenta ejecución de código en cualquier servidor web PHP, por debajo de WordPress, Magento o Laravel.
- Los ataques empezaron antes del parche: los identificadores CVE se filtraron unas 23 horas antes de la publicación. Cloudflare vio tráfico de ataque antes del parche y watchTowr informó de intentos de explotación 19 minutos después.
- Parcheado no es limpio: actualizar PHP cierra la puerta, pero no echa a nadie. En las tiendas online, el acceso al servidor a menudo acaba en un skimmer en el checkout, y eso solo se ve en el navegador.
¿Poco tiempo? Consulta la monitorización de scripts del lado del cliente de cside. Te ayuda a monitorizar los cambios y el comportamiento de los scripts en el navegador que se describen a continuación.
El 2026-10-21 el proyecto PHP publicó correcciones de emergencia para dos fallos críticos en el motor de PHP, registrados como CVE-2026-109618 y CVE-2026-109619 y apodados PHP2Shell. Como los fallos viven en el runtime y no en ningún CMS ni plugin, todas las webs con WordPress, WooCommerce, Magento, Shopware o Drupal sobre una versión de PHP sin parchear estaban en riesgo al mismo tiempo.
Casi toda la cobertura hasta ahora trata del servidor, y con razón: actualiza PHP y reinicia todos los workers. Este artículo cubre la parte que suele quedarse fuera. Cuando un atacante consigue ejecutar código en una tienda online, el servidor rara vez es el premio. El premio son unas pocas líneas de JavaScript añadidas al checkout y servidas a cada comprador hasta que alguien mira lo que el navegador ejecuta de verdad.
Qué pasó: un fallo antiguo y una divulgación que se filtró
La causa de fondo no era nueva. Según la PHP Foundation, un desarrollador del núcleo detectó las primeras señales del problema de falta de memoria detrás de CVE-2026-109618 durante la auditoría externa de PHP de 2024. Nadie encontró entonces una vía real hasta la ejecución de código, cada posible corrección tenía costes de compatibilidad o de denegación de servicio, y el trabajo se estancó. La Fundación califica ese retraso de fallo estructural de su propio proceso.
Eso cambió en agosto de 2026, cuando las auditorías de Calif, OpenAI y Wiz convirtieron el viejo fallo en exploits funcionales. La publicación coordinada estaba prevista para el 2026-10-22. No aguantó.
| Cuándo (UTC) | Qué pasó |
|---|---|
| 2024 | Se detectan señales del fallo de falta de memoria durante la auditoría externa de PHP; no se identifica vía de explotación y la corrección se estanca |
| 2026-08-11 | Calif y OpenAI notifican por separado ejecución remota de código con la misma causa |
| 2026-08-24 y 2026-09-18 | Wiz y OpenAI notifican vectores de ataque adicionales |
| 2026-10-20, ~15:00 | Los dos identificadores CVE se filtran en foros y redes sociales, con una fecha de publicación errónea y una puntuación CVSS 10.0 también errónea |
| 2026-10-20, 19:30 | PHP preanuncia la corrección y adelanta la publicación un día |
| 2026-10-20, ~20:00 | Una firma de investigación publica por error un vídeo de una prueba de concepto funcional; las copias se difunden |
| 2026-10-21, 03:02 | Cloudflare activa reglas WAF por defecto en todos los planes, incluido el gratuito |
| 2026-10-21, 07:41 | Chainguard publica imágenes parcheadas antes de tiempo, lo que permite a cualquiera comparar el parche |
| 2026-10-21, 14:00 | PHP publica 8.5.12, 8.4.27, 8.3.36 y 8.2.35 |
| 2026-10-21, 14:19 | watchTowr informa de intentos de explotación activos contra ambos CVE |

El intervalo que importa a los defensores son esas 23 horas aproximadas entre la filtración y la publicación. Quien usaba PHP pasó esa ventana expuesto a un fallo cuya existencia los atacantes ya conocían, sin ningún parche que instalar.
Las dos vulnerabilidades, en pocas palabras
Ambos fallos están en código que casi cualquier petición PHP atraviesa: la gestión de memoria y el manejo de errores. Los dos tienen una puntuación de 9.2 en CVSS v4.0 y ambos pueden dar a un atacante no autenticado ejecución de código con los privilegios del worker web.
| CVE-2026-109618 | CVE-2026-109619 | |
|---|---|---|
| Nombre corto | RCE por corrupción al quedarse sin memoria | RCE por estado obsoleto entre peticiones |
| Qué falla | Una petición alcanza el límite de memoria justo en el peor momento. PHP abandona datos internos a medio inicializar y luego los trata como válidos durante la limpieza. | Un error fatal deja estado interno apuntando a memoria liberada al final de una petición. La siguiente petición en el mismo worker la usa (un use-after-free). |
| Disparador típico | Peticiones multipart/form-data manipuladas (formularios y subidas de archivos) que agotan la memoria aunque parecen respetar los límites | Un error fatal seguido de una petición posterior que lee el estado obsoleto, por ejemplo a través del progreso de subida de sesión, activado por defecto |
| Peor caso demostrado | RCE en Apache mod_php con una sola petición, antes de que se ejecute código de la aplicación, con la configuración por defecto | RCE en mod_php y PHP-FPM; en FPM la vía depende de una operación dentro de la aplicación |
Dos detalles lo hacen peor que un fallo típico de un CMS. Primero, actúa por debajo de tu aplicación, así que una instalación de WordPress o Magento totalmente actualizada sobre una versión vulnerable de PHP sigue expuesta, y los plugins de seguridad nunca llegan a ver la petición. Segundo, según los investigadores, un atacante también puede leer la memoria del worker de PHP sin conseguir antes ejecución de código. Esa memoria puede contener tokens de sesión, contraseñas, claves de API y certificados de otros usuarios.
Las descripciones oficiales son el aviso de corrupción por falta de memoria y el aviso de estado obsoleto.
A quién afecta y si se está explotando
Cualquier instalación de PHP que sirva peticiones web está afectada, sea cual sea la interfaz de servidor: PHP-FPM, Apache mod_php, php-cgi, FrankenPHP y LiteSpeed. Los investigadores demostraron ejecución de código sin autenticación contra instalaciones estándar de Magento 2.4.9, WordPress, Drupal, Joomla, Nextcloud, phpMyAdmin, Laravel y otros. Sansec destaca las tiendas Magento, Shopware y WooCommerce.
| Rama de PHP | Vulnerable | Corregido 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 llega al fin de soporte el 2026-12-31) |
| 8.1, 8.0, 7.4 | todas | Sin versión oficial. PHP publicó backports del código fuente; consigue una compilación del proveedor o actualiza de rama |
| 7.3 y anteriores | todas | Actualiza de rama |
Hay tres cosas que confunden a la gente. Los paquetes de las distribuciones recibieron el parche por adelantado y pueden llevarlo con un número de versión que parece antiguo, así que busca el CVE en el changelog del paquete en lugar de fiarte de la versión. El repositorio de Remi, habitual en servidores basados en RHEL, no publicó actualizaciones el 2026-10-21. Y actualizar WordPress, Magento o Laravel no sirve de nada aquí: la corrección viene del paquete del servidor, de tu hosting o de tu imagen de contenedor.
En cuanto a la explotación, todo fue muy rápido. Cloudflare dice que vio tráfico de ataque contra sus clientes antes de que saliera el parche, y que observó cómo los atacantes modificaban los payloads para saltarse sus reglas. watchTowr informó de intentos de explotación activos contra ambos CVE a las 14:19 UTC. En el momento de publicar, ninguna fuente ha confirmado públicamente el compromiso exitoso de un servidor concreto. Varias organizaciones, entre ellas servicios del gobierno neerlandés y BambooHR, se desconectaron por precaución en lugar de esperar.
Si no pudiste parchear dentro de esa ventana, da por hecho que te sondearon.
Por qué un fallo del servidor se convierte en un problema del checkout
En una tienda online, una shell es un medio, no un fin. Ha pasado tras cada ola de explotación masiva contra plataformas de comercio en PHP, con CosmicSting en 2024 como el caso más conocido: los atacantes consiguen ejecutar código, dejan una puerta trasera y luego cambian lo que la tienda envía a los navegadores de los compradores. El dinero está en los números de tarjeta que se escriben en el checkout, y esos solo existen en el navegador.
La cadena suele ser esta:
- Exploit. Una petición manipulada llega a un worker de PHP sin parchear.
- Ejecución de código. El código del atacante se ejecuta como el usuario web, sin iniciar sesión.
- Persistencia. El atacante deja una webshell, una tarea cron o una cuenta de administrador nueva. Esto sobrevive a la actualización de PHP, porque parchear cierra la puerta pero no echa a quien ya está dentro.
- Inyección. El atacante cambia lo que recibe el navegador: una etiqueta
<script>en una plantilla del checkout, un bundle de JavaScript propio modificado o, muy a menudo en Magento y WordPress, un fragmento guardado en la base de datos (ajustes de cabecera del tema, bloques CMS, opciones de widgets) donde las comprobaciones de integridad de archivos nunca miran. - Recolección. El navegador de cada comprador ejecuta el skimmer. Lee los campos de la tarjeta, o pone en su lugar un formulario de pago falso, y envía los datos a un dominio que parece de analítica o de CDN.
El comercio suele enterarse por un aviso de punto común de compra de una marca de tarjetas, semanas o meses después de que se robara la primera tarjeta.
Cada defensa cubre un tramo distinto de esa cadena:
| Defensa | Cubre | No ve |
|---|---|---|
| Actualización de PHP | Paso 1, para cada petición posterior a la instalación | Nada de lo que se plantó antes de parchear |
| WAF | Paso 1, la petición de exploit entrante | Payloads modificados; todo lo que ocurre después de la petición |
| Forense del servidor e integridad de archivos | Pasos 2 a 4, en archivos y logs | Scripts guardados en la base de datos; lo que hace la página en el navegador |
| Monitorización de scripts en el navegador | Pasos 4 y 5, lo que las páginas del checkout ejecutan de verdad y adónde envían los datos | El compromiso del servidor en sí |

Los skimmers modernos están hechos para no ser vistos por las herramientas que revisan el lado del servidor. Solo se activan en la ruta del checkout, una vez por sesión, para ciertos países o cuando no hay herramientas de desarrollo abiertas, así que un crawler que visita desde un centro de datos recibe una página limpia. Vimos el truco de una vez por sesión hace unos días en el secuestro del checkout de HulkApps. Un WAF ve el exploit entrante, no el script que tu página sirve tres semanas después. El único lugar donde el skimmer se muestra de forma fiable es la sesión de navegador de un cliente real.
Parcheado no es lo mismo que limpio: qué revisar ahora
Si tus servidores PHP estaban expuestos a internet con una versión afectada en algún momento después de la filtración del 2026-10-20, recorre las dos listas siguientes. La primera trata del servidor. La segunda trata de lo que reciben los navegadores de tus clientes, y es la que la mayoría de las listas de respuesta a incidentes dejan fuera.

En el servidor
- Conserva primero las evidencias. Haz una copia de los logs de PHP y del servidor web, de la configuración y de cualquier archivo sospechoso antes de cambiar nada.
- Actualiza y reinicia. Instala la versión corregida de PHP y reinicia Apache, PHP-FPM y todos los workers de larga duración. Un paquete actualizado con los workers antiguos todavía en marcha sigue siendo vulnerable.
- Busca persistencia. Revisa archivos PHP nuevos o modificados en las raíces web y los directorios de subidas, tareas cron inesperadas y usuarios administradores que nadie creó.
- Busca en los logs las huellas del exploit. Los investigadores sugieren buscar peticiones multipart inusuales seguidas de errores de límite de memoria o ráfagas de HTTP 500, cookies
PHPSESSIDde respuesta anormalmente grandes y reinicios inexplicables de workers de PHP. - Vigila el comportamiento de los procesos. Las conexiones salientes desde workers de PHP, o un
sh,curlowgetlanzado porphp-fpm, son señales claras. - Rota lo que vivía en memoria. Como la memoria del worker podía leerse sin ejecución de código, rota las claves de API, las credenciales de base de datos y los secretos de la pasarela de pago que tuvieran los procesos de PHP, y plantéate invalidar las sesiones activas.
En el navegador
- Inventaria cada script de tus páginas sensibles. Primero checkout, pago, login y cuenta. Incluye los bundles propios, no solo las etiquetas de terceros.
- Compara con una línea base anterior al 2026-10-20. Cualquier script nuevo, cualquier hash de archivo cambiado y cualquier dominio nuevo con el que hable el checkout merece una explicación.
- Revisa los sitios donde los skimmers se esconden fuera de tu código. En Magento, los ajustes "Scripts and Style Sheets" de la cabecera HTML y "Miscellaneous HTML" del pie, los bloques CMS y los widgets. En WordPress, los plugins de inyección en cabecera y pie, los widgets y las opciones del tema guardadas en la base de datos.
- No te fíes de un único rastreo. Un skimmer que se activa una vez por sesión o que ignora las IP de centros de datos pasará un escaneo. Necesitas observaciones de sesiones reales, a lo largo del tiempo.
- Vigila las peticiones salientes del checkout. Los datos de la tarjeta tienen que salir de la página de alguna forma: un
fetch, un beacon de imagen, un WebSocket. Un destino nuevo en la página de pago es la señal más clara que vas a tener. - Revisa los informes de violaciones de CSP, si los recoges. Un informe que nombra un dominio que nunca has usado merece investigarse aunque la página parezca normal.
Nada de esto sustituye al parche. Responde a la pregunta que el parche no puede responder: ¿cambió algo mientras la puerta estaba abierta?
Qué significa para PCI DSS 6.4.3 y 11.6.1
PHP2Shell es un caso de manual para los dos requisitos de PCI DSS 4.0.1 que pasaron a ser obligatorios el 2025-03-31.
- El requisito 6.4.3 te pide gestionar cada script que se carga y se ejecuta en una página de pago en el navegador del consumidor: confirmar que cada uno está autorizado, asegurar su integridad y mantener un inventario con una justificación escrita para cada uno. Un skimmer inyectado tras comprometer un servidor es, por definición, un script no autorizado.
- El requisito 11.6.1 pide un mecanismo de detección de cambios y manipulaciones que te avise de cambios no autorizados en los scripts de las páginas de pago y en las cabeceras HTTP relevantes para la seguridad, tal como las recibe el navegador. Ese es exactamente el cambio que hace un atacante en el paso 4 de la cadena anterior.
Dos preguntas prácticas para tu próxima evaluación. ¿Con qué frecuencia evalúa de verdad la página tu mecanismo de 11.6.1? Si la respuesta es semanal, un skimmer inyectado el 2026-10-21 podría funcionar durante días antes de que nadie se entere. ¿Y cubren tus evidencias la ventana desde el 2026-10-20? Si puedes demostrar que el inventario de scripts de tus páginas de pago no cambió, tienes una respuesta limpia. Si no puedes, merece la pena cerrar ese hueco ya.
Los comercios con SAQ A que incrustan el iframe de un proveedor de pagos tampoco se libran. Desde la revisión del SAQ A de enero de 2025, la elegibilidad depende de confirmar que tu sitio no es vulnerable a ataques de scripts que puedan afectar a tus sistemas de comercio electrónico. Una página padre comprometida puede seguir sustituyendo o tapando ese iframe.
Dónde encaja cside
Para dejar claro el alcance: cside no parchea PHP ni detiene la petición del exploit. Ese es el trabajo de tu actualización de PHP y de tu WAF. cside cubre la capa que viene después: lo que tus páginas ejecutan de verdad en los navegadores de tus clientes.
Sesiones reales, no rastreos sintéticos. cside monitoriza los scripts en sesiones reales de compradores en lugar de depender de un escaneo periódico, así que un skimmer que se activa una vez por sesión o se esconde de los centros de datos sigue ejecutándose delante de nosotros.
Cambios y comportamiento, no solo nombres de archivo. Un script nuevo en el checkout, un bundle propio modificado o un script que empieza a leer los campos de la tarjeta y a enviarlos a un dominio que tu tienda nunca ha usado generan una alerta, con el contenido del script disponible para inspeccionarlo.
Detenido en la sesión. Con Script Method, cside descarga cada script de terceros en sus servidores para calcular su hash, archivarlo y analizarlo, y los bloqueos se aplican en tiempo de ejecución en el navegador, junto a CSP. Un script no autorizado, o una capacidad concreta que intenta usar, se detiene en la sesión en lugar de notificarse a posteriori.
Evidencias para PCI. PCI Shield mantiene el inventario de scripts de 6.4.3 y las alertas de cambios de 11.6.1, con informes semanales que tu evaluador puede leer.
Los detalles anteriores reflejan la información pública y las declaraciones de los proveedores a 2026-10-21. Actualizaremos este artículo a medida que cambien los informes de explotación.
Si cside ya monitorizaba tu checkout el 2026-10-20, revisa los datos registrados desde entonces o reserva una demo para analizarlos con nuestro equipo. Empieza gratis para comenzar a monitorizar a partir del despliegue. Los nuevos despliegues no pueden reconstruir sesiones anteriores del navegador.
Fuentes
- Aviso de seguridad de PHP: RCE por corrupción al quedarse sin memoria (GHSA-w8hw-w9fx-j79w)
- Aviso de seguridad de PHP: RCE por estado obsoleto (GHSA-6wmf-4rv5-p3rp)
- Anuncio de PHP, 2026-10-21
- The PHP Foundation: Today's PHP security release, and how we're strengthening PHP security
- Cloudflare: Cloudflare deploys protections against php2shell vulnerability
- watchTowr: PHP Remote Code Execution (PHP2Shell)
- Rapid7: CVE-2026-109618 and CVE-2026-109619
- The Hacker News: PHP issues emergency patches for two critical PHP2Shell RCE flaws
- Sansec: PHP2Shell critical PHP RCE
- CERT-EU Security Advisory 2026-018








