← volver Torre de servidor agrietada con un candado roto y una concha marina en la parte superior, vinculada por un cable a una ventana de navegador separada.

PHP2Shell: la vulnerabilidad PHP que argumenta a favor de prescindir del backend

El 21 de octubre, el centro nacional de ciberseguridad holandés sacó su propio sitio web offline. No porque WordPress hubiera sido hackeado, sino porque el intérprete PHP debajo de él podría serlo.

Ese día el proyecto PHP envió correcciones para dos bugs de ejecución remota de código no autenticada en el intérprete mismo, CVE-2026-109618 y CVE-2026-109619. Cualquier sitio donde PHP respondiera solicitudes públicas tuvo que parchearse o desaparecer. Los sitios que servían HTML estático desde un CDN no tenían proceso PHP en la ruta de solicitud, por lo que no había nada que parchearse en el edge. WordPress Headless aún necesitaba que su backend se actualizara, pero el sitio público se mantuvo activo. Debajo: la línea de tiempo, el argumento arquitectónico, una tabla de decisiones por stack, un plan de 30/60/90 días, y una lista de verificación si te quedas con PHP por ahora.

Si ejecutas PHP, haz esto hoy.

  • Confirma que la versión en ejecución es 8.5.12, 8.4.27, 8.3.36 u 8.2.35, o un backport de proveedor cuyo aviso hayas leído, y reinicia cada worker.
  • Verifica qué envió realmente tu panel de control de hosting, no lo que dice el dashboard.
  • Trata las mitigaciones ini de PHP y cualquier regla WAF como un puente hacia el parche, no como sustituto del mismo.
  • En 7.4 a 8.1, pregunta a tu proveedor si construyó los backports de código del equipo de seguridad, y programa la actualización de todas formas.

Qué pasó el 21 de octubre de 2026

La línea de tiempo importa porque explica el pánico. Según Tenable, los identificadores CVE circularon en Hacker News y redes sociales el 20 de octubre. Ese mismo día, el equipo de seguridad de PHP publicó un aviso anticipado de un lanzamiento para el 21 de octubre a las 14:00 UTC, diciendo que podría lanzarse antes si los detalles se hacían públicos. Tenable también reporta, citando a watchTowr, que la divulgación originalmente había sido programada para el 22 de octubre bajo embargo.

El equipo de seguridad de PHP luego publicó su aviso el 21 de octubre, titulado "Security advisory: Critical remote code execution vulnerabilities, update now" (php.net news archive). La declaración conjunta de ENISA sitúa las actualizaciones a las 13:40 UTC. Las versiones corregidas son PHP 8.5.12, 8.4.27, 8.3.36 y 8.2.35.

Los dos bugs, de los GitHub advisories:

  • CVE-2026-109618: ejecución remota de código mediante corrupción por falta de memoria.
  • CVE-2026-109619: ejecución remota de código mediante estado global obsoleto, un use-after-free entre solicitudes manejadas por el mismo worker.

El equipo de seguridad de PHP califica ambos CVSS v4.0 como 9.2. Tenable señala que algunos informes iniciales, incluyendo watchTowr y un post en Hacker News, dijeron 10.0. Cada SAPI que sirve web está en alcance: PHP-FPM, Apache mod_php, php-cgi, FrankenPHP y LiteSpeed. El aviso de OOM destaca mod_php como el más expuesto, porque la falla ocurre completamente antes de que se ejecute cualquier código de aplicación. Calif dice que la ruta de código más antigua afectada se remonta a PHP 5.4.0. El descubrimiento se acredita a Wiz, Calif y OpenAI, con investigación asistida por IA.

Luego los cortes. Reuters y RTE reportaron servicios gubernamentales sacados offline en los Países Bajos, Finlandia, Francia y Australia, incluyendo el sitio del propio centro nacional de seguridad cibernética holandés. CERT-EU recomendó aislar aplicaciones conectadas a internet hasta que fueran parcheadas, y CISA instó a parchear de inmediato. Krebs reporta que Cloudflare desplegó reglas WAF a las 3:02 am UTC. Amazon Threat Intelligence dice que vio un intento el 17 de octubre y posteriormente describió la explotación como generalizada.

Sobre la explotación, las fuentes no están de acuerdo, y debes saberlo. La PHP Foundation dijo que no había identificado exploits funcionales en el momento del lanzamiento. Krebs reporta a expertos diciendo que existen exploits funcionales. Tenable dijo que código que afirmaba explotar los bugs estaba circulando pero no había verificado ninguno.

Por qué el consejo fue parchear ahora u offline

Ejecución remota de código no autenticada en la ruta de solicitud significa que el servidor web es el objetivo. No hay login para ponerlo enfrente, no hay plugin para desactivar. Llega una solicitud, PHP la analiza, y el bug ya está en juego. El aviso de OOM confirma impacto como ejecución de código no autenticada como la cuenta del worker web, validada sobre HTTP contra mod_php con límites predeterminados de entrada y memoria.

Las mitigaciones que PHP enumeró son reales, y son medidas temporales.Los avisos dicen:

  • Establece memory_limit=-1 administrativamente (vía php_admin_value), mantén post_max_size conservador, y bloquea solicitudes multipart en el frontend si no las usas.
  • Establece session.upload_progress.enabled=0.
  • En PHP 8.5, establece fatal_error_backtraces=0.
  • Reinicia todos los workers después de cualquiera de estos.

Los mismos avisos son contundentes: actualizar es el único arreglo completo. Para el bug de estado obsoleto no hay ninguna mitigación genérica y completa en la configuración. El desarrollador de PHP core Gina Peter Banyard, citado por Tenable, dijo que la única mitigación es parchar o actualizar PHP, y Joe Ferguson, gerente de lanzamientos de PHP 8.6, dijo que los ajustes de ini no te salvarán. Así que trata la lista como un puente para pasar una tarde, no como una postura.

Dos problemas prácticos hicieron el día más difícil que un cambio de versión. El hosting compartido y los paneles de control distribuyen paquetes PHP en su propio calendario, así que la versión que crees que ejecutas puede no ser la que está ejecutándose. Plesk publicó su propio aviso para el PHP que distribuye, que es el tipo de página que necesitas leer en lugar de asumir.

Y luego las ramas más antiguas. El aviso de php.net dice que PHP 8.1 y versiones anteriores ya no reciben actualizaciones del proyecto y remite a distribuciones y proveedores LTS para los backports. El equipo de seguridad sí publicó ramas de backport de código fuente mínimas para 7.4, 8.0 y 8.1 en GitHub, pero un parche de código fuente no es un lanzamiento: alguien aún tiene que compilarlo y entregarlo a tu hosting. PHP 5.4 a 7.3 no reciben nada. Si nunca actualizaste, ese fue tu 21 de octubre.

Algunos números en escala. W3Techs muestra PHP en el 69.3% de sitios web con un lenguaje del lado del servidor conocido al 22 de octubre, con 65.3% de esos en versión 8, 26.9% en versión 7 y 7.7% en versión 5. Censys cuenta 2.58 millones de hosts expuestos a internet y 54.9 millones de propiedades web ejecutando PHP. Son muchos workers para reiniciar.

Quiénes no tenían nada que hacer el 21 de octubre

Aquí está la exposición en términos de ruta de solicitud. Haz una pregunta de cualquier sitio: cuando un visitante carga una página, ¿qué código se ejecuta para responderle?

Elefante en una caja de servidor al lado de un candado roto, con una ventana de navegador desacoplada vinculada por un único cable delgado.

HTML estático en un CDN

Si la respuesta es "nada, el CDN devuelve un archivo", PHP2Shell no toca el sitio público. Ningún proceso PHP responde solicitudes, así que no hay nada que parchar en el borde y ninguna razón para desconectar nada. Ejecuto gautamkhorana.com en Astro con salida estática. HostList, que construí con Next.js y Supabase con aproximadamente 28,000 páginas programáticas, no tenía proceso PHP que parchar. Tampoco lo tenía Deluxe Astrology, que ejecuta más de 91,000 páginas en 30 idiomas. Nadie recibió una llamada el 21 de octubre.

Headless WordPress

Headless es otra historia, y prefiero ser preciso que halagador. El backend de PHP aún necesitaba 8.5.12, 8.4.27, 8.3.36 u 8.2.35 ese día, porque WordPress sigue ejecutándose en PHP. La diferencia es dónde se sienta. Detrás de un firewall o una lista de direcciones IP permitidas, con el sitio público servido por Astro o Next.js, el backend no estaba en la ruta de la solicitud de un visitante. El parche era una tarea de mantenimiento, no una interrupción pública.

Dilo claramente: esto no es "headless es unhackable". Un atacante que pueda alcanzar el backend aún puede alcanzar el bug, por eso la lista de permitidos importa. Los frameworks SSR tienen sus propios riesgos de runtime de servidor, cubiertos en el artículo de seguridad de Next.js, Astro y Nuxt, y la comparación más amplia vive en seguridad headless vs WordPress. No repetiré ninguno aquí.

Un patrón, no un caso aislado

Esta no fue la primera vez que la ruta de solicitud de PHP hizo titulares. La inyección de argumentos de PHP-CGI, CVE-2024-4577, llegó en 2024. Había un bug de PHP-CGI más antiguo en 2012. Ahora PHP2Shell. Diferentes fallos, la misma forma: código que se sienta frente a cada solicitud pública se golpea, y todos los demás aguas abajo se apresuran.

Ahora la lección que corta del otro lado. React2Shell en Next.js mostró que los runtimes de SSR llevan su propia exposición de ruta de solicitud. Si un servidor JavaScript responde cada solicitud de página, es el nuevo PHP para propósitos de parches. Pasar de WordPress a un sitio renderizado por servidor Next.js mueve la superficie de ataque. No la elimina. La salida estática es la afirmación fuerte: SSR es un intercambio.

Así que la pregunta nunca fue "qué lenguaje". Es "qué código responde una solicitud pública". Reduce esa lista y tus días de incidente se acortarán, sea lo que sea en lo que se escriba el siguiente CVE.

También hay un punto de futuro. Los investigadores de Wiz escribieron que los fallos habían estado presentes durante décadas, que explotarlos tomaba una cadena de pasos "en el límite de lo que los investigadores humanos podrían lograr prácticamente", y que "los modelos de IA de frontera redujeron sustancialmente esa barrera" (Krebs). La implicación, que es mía en lugar de la suya: si los fallos antiguos se vuelven más baratos de convertir en exploits, la cadencia de divulgación aumenta para cada runtime. Planifica para más días como este, no menos.

Qué te costó el 21 de octubre, por stack

Stack¿PHP en la ruta de solicitud pública?Lo que tuviste que hacer el 21 de octubreLo que el próximo CVE de PHP te cuestaRuta de migración sensata
WordPress clásico u otro CMS PHPSí, cada páginaActualizar PHP a una versión corregida, reiniciar cada worker, o aislar el sitio hasta que pudierasEl mismo apuro, en el sitio públicoIr headless, tipo de página por tipo de página
Headless WordPress (backend PHP detrás de un firewall, Next.js o Astro en el front end)No, solo el backendParchar el backend PHP; el sitio público siguió sirviendoUna ventana de parche en un host bloqueado, sin interrupciones públicasQuedarse; mantener el backend en lista blanca
Laravel o una aplicación PHP personalizadaSíActualizar el runtime, reiniciar workers, verificar qué envió tu hostEl mismo apuroPoner un front end estático o SSR adelante e ir sacando tipos de página gradualmente
Jamstack estático (Astro, Next.js static export, Nuxt generate, Eleventy)NoNada en el edge; verificar herramientas de construcción y cualquier origenNada en el edgeQuedarse
Next.js o Nuxt con SSRSin PHP, pero un servidor JavaScript responde las solicitudesNada para PHP; aplican sus propios avisos de runtimeUn CVE de runtime diferente con la misma formaTraslada las páginas que no necesitan renderizado por solicitud a salida estática

WordPress clásico u otro CMS PHP. Drupal, Magento, Joomla y WordPress todos funcionan en PHP, y Calif reporta ejecución remota de código sin autenticación confirmada contra versiones específicas de los cuatro, según el FAQ de Tenable. Esta fila cargó con todo el costo del día.

WordPress Headless. Aplicaste parches, pero en tu horario y detrás de un firewall. Los editores seguían editando. Los visitantes no veían nada.

Laravel o PHP personalizado. Misma exposición que el CMS clásico, con un detalle: nadie publica un aviso de producto para tu aplicación personalizada, así que tú posees el inventario. El repositorio php2shell de NCSC-NL dice que las aplicaciones PHP personalizadas no están registradas en su descripción general.

Static Jamstack. Nada que hacer en el edge. Si tu compilación se ejecuta en una caja de CI, aplica parches cuando sea conveniente, ya que no está sirviendo visitantes.

SSR con Next.js o Nuxt. Sin PHP, sin PHP2Shell. Pero un proceso de servidor sigue respondiendo solicitudes, y React2Shell es el recordatorio de que este proceso tiene sus propios días malos.

El plan de 30/60/90 días

El objetivo es sacar la superficie pública de PHP sin reconstruir la experiencia de edición.

  1. Para el día 30: lista tus tipos de página (posts, páginas de destino, páginas de producto, archivos) y marca cuáles realmente necesitan lógica por solicitud. Confirma la versión de PHP en cada host. Coloca un CDN frente al origen y restringe el admin a una lista de permitidos.
  2. Para el día 60: implementa un front end de Astro o Next.js para uno o dos tipos de página estática con mayor tráfico, construido desde la API de contenido de WordPress. Activa una compilación al publicar. Agrega redirecciones 301 para cada URL que muevas.
  3. Para el día 90: migra los tipos de página restantes que puedan ser estáticos. Cierra el origen de PHP al tráfico público para que solo el proceso de compilación y tus editores en la lista de permitidos lo alcancen. Cualquier cosa que realmente necesite un servidor (búsqueda, formularios, cuentas) va a un servicio pequeño y nombrado que puedas actualizar por su cuenta.

Sacar la superficie pública de PHP sin perder el CMS

No tienes que deshacerte de WordPress para sacar PHP de la ruta de solicitud. WordPress Headless mantiene editores, contenido y el flujo de trabajo de plugins para escribir y aprobaciones, mientras que Astro o Next.js sirve el sitio. Los editores mantienen la pantalla que conocen. Los visitantes obtienen archivos de un CDN.

Migra progresivamente. Elige un tipo de página, reconstruyela en el nuevo front end, redirecciona 301 las URLs antiguas y continúa. El admin permanece en PHP, detrás de una lista de permitidos. El patrón de hosting es simple: origen bloqueado, CDN al frente, compilación al publicar.

Sobre la elección del framework: Astro para sitios de contenido, Next.js cuando el sitio necesita una capa de aplicación, Nuxt para equipos de Vue. Los compromisos más profundos están en la comparación de generadores de sitios estáticos y la guía de WordPress Headless.

En cuanto al esfuerzo, usando solo los precios iniciales: la migración de WordPress a Astro es desde $7k, el desarrollo de WordPress Headless es desde $10k, y una migración de CMS heredado comienza desde $5k. Si el sitio necesita una capa de aplicación, la migración de WordPress a Next.js desde $10k es la ruta que funciona. Esos son puntos de partida, y la cifra real depende de tipos de página, integraciones y cuánto flujo de trabajo de edición deseas conservar. Si estás considerando dejar PHP completamente, la página leave-WordPress cubre ese camino.

El día más barato para comenzar esto no es el día después de un aviso. Pero el día después de un aviso es cuando se aprueban presupuestos, así que úsalo.

Si vas a mantener PHP por ahora

Algunos sitios se quedarán así durante uno o tres años. Está bien. Mientras tanto, haz esto:

  1. Confirma que la versión de PHP en ejecución es 8.5.12, 8.4.27, 8.3.36 u 8.2.35 (o un backport de proveedor cuyo aviso hayas leído), y que todos los workers se reiniciaron. Una actualización de paquete que deja workers antiguos ejecutándose no ha arreglado nada.
  2. Verifica qué realmente entregó tu panel de control de hosting, en lugar de lo que dice el dashboard.
  3. Aplica las mitigaciones listadas de PHP solo como puente. Los avisos dicen que no hacen segura una instalación, y el aviso de OOM advierte contra RLIMIT_AS y RLIMIT_DATA, que activan la ruta vulnerable.
  4. Planifica ahora la salida de 7.4 a 8.1. El proyecto PHP ya no actualiza 8.1 y versiones anteriores, y dependerás del backport de alguien más.
  5. Coloca el sitio detrás de un WAF mientras parches. El CTO de Cloudflare Dane Knecht llamó a sus reglas "solo un PARCHE TEMPORAL", y Tenable señala que solo cubren el tráfico enrutado a través de Cloudflare.
  6. Vigila los web shells y archivos PHP que no deberían existir. Wiz espera explotación masiva para instalarlos, así que revisa directorios de carga y archivos modificados recientemente.

Para sitios que permanecerán en WordPress, la protección de seguridad de WordPress desde $150/mes cubre el lado del parcheo continuo y monitoreo.

El hecho más contundente del 21 de octubre es que el bug vivía en el único lugar que toca todo visitante de PHP, así que los únicos sitios sin nada que hacer fueron aquellos donde PHP nunca respondió una solicitud pública. La salida estática es la versión fuerte de esa afirmación; WordPress headless igual necesitaba su backend parcheado, y SSR solo cambia un runtime por otro.

FAQ

¿Se ve afectado WordPress por PHP2Shell?

WordPress en sí no es el bug. Los defectos están en PHP, y WordPress funciona en PHP, así que cualquier sitio WordPress en un PHP sin parches estaba expuesto. El FAQ de Tenable, citando a Calif, reporta ejecución remota de código sin autenticación confirmada contra versiones específicas de WordPress, lo que resuelve la cuestión.

¿Un WordPress headless aún necesita el parche?

Sí. El backend ejecuta PHP, y un atacante que pueda alcanzarlo puede alcanzar el error. Lo que headless cambia es la exposición: el backend puede estar detrás de un firewall o allowlist mientras un front end separado sirve al público.

¿Un sitio Next.js o Astro es más seguro que PHP?

El resultado estático de cualquiera de los dos es más seguro contra esta clase de error, porque ningún runtime del lado del servidor responde solicitudes. SSR es un tradeoff: cambias PHP por un runtime de servidor JavaScript con sus propios avisos, como React2Shell mostró.

¿Un WAF me protege?

Parcialmente, y solo por un tiempo. Cloudflare llamó a sus reglas un parche temporal y solo cubren tráfico a través de Cloudflare. Un WAF te compra tiempo para parchar. No es un parche.

¿Debo llevar mi sitio sin conexión?

CERT-EU recomendó considerar el aislamiento de aplicaciones expuestas a internet hasta que una solución esté disponible, y la declaración conjunta de ENISA dice lo mismo donde la remediación inmediata no es viable. Si puedes parchar rápido, parcha. Si no puedes, el aislamiento es una decisión razonable.

¿Qué versiones de PHP están parcheadas?

PHP 8.5.12, 8.4.27, 8.3.36 y 8.2.35, según los avisos de PHP.

¿Están parcheados PHP 7.4, 8.0 y 8.1?

No con lanzamientos. El aviso de php.net dice que 8.1 y versiones anteriores ya no reciben actualizaciones del proyecto PHP, y el equipo de seguridad publicó ramas de backport de código fuente mínimas para 7.4, 8.0 y 8.1 en su lugar. Pregunta a tu hosting o distribución si las compiló; de cualquier forma, planifica la actualización.

← volver