Si tu sitio web usa PHP, hoy es el día de actuar. El equipo de PHP publicó este 21 de octubre actualizaciones de emergencia para dos vulnerabilidades críticas del núcleo del lenguaje, conocidas como PHP2Shell (CVE-2026-109618 y CVE-2026-109619), con una severidad de 9.2 sobre 10. Permiten que un atacante ejecute código en tu servidor sin usuario ni contraseña, y los detalles técnicos se filtraron antes de tiempo, así que la carrera entre atacantes y administradores ya empezó.
Afecta a WordPress, tiendas en Magento o PrestaShop, sistemas en Laravel, paneles de hosting y prácticamente cualquier servidor que procese peticiones web con PHP: PHP-FPM, Apache con mod_php, php-cgi, FrankenPHP y LiteSpeed. La telemetría de Palo Alto Networks identificó más de 22 millones de servidores expuestos a internet con versiones potencialmente vulnerables. En esta guía te explicamos, en lenguaje claro y con pasos concretos, qué pasó, cómo saber si estás afectado y cómo protegerte hoy mismo, tengas un hosting compartido, un VPS, contenedores Docker o una plataforma como Coolify.
PHP2Shell en 60 segundos
- Qué es: dos fallos de corrupción de memoria en el núcleo de PHP. No es un fallo de tu aplicación ni de un plugin: es del lenguaje.
- Qué permite: ejecución remota de código sin autenticación y fuga de memoria del servidor (puede exponer contraseñas, tokens y claves que vivan en ese proceso).
- Cómo se ataca: con peticiones
multipart/form-data, las mismas que usa cualquier formulario con subida de archivos. El fallo se dispara antes de que corra el código de tu aplicación: pedir login no protege.
- Versiones corregidas (ya disponibles): PHP 8.5.12, 8.4.27, 8.3.36 y 8.2.35.
- Sin parche oficial: PHP 8.1 y anteriores (fin de vida). Hay parches de código fuente para 7.4, 8.0 y 8.1, y algunos proveedores y distribuciones aplican los suyos.
- La única corrección real es actualizar PHP. Todo lo demás son mitigaciones temporales para ganar tiempo.
Qué es PHP2Shell, explicado sin humo
PHP procesa cada petición web en procesos trabajadores (workers) que atienden muchas peticiones seguidas. Los dos fallos rompen la memoria de ese proceso de dos maneras complementarias, según el análisis del aviso oficial y de firmas como Sonatype y watchTowr:
- CVE-2026-109618 (corrupción por falta de memoria): si una petición se queda sin memoria a mitad de camino (al superar
memory_limit), PHP puede interrumpirla dejando datos internos a medio inicializar. La limpieza de esa petición trata esos datos inválidos como si fueran válidos.
- CVE-2026-109619 (estado obsoleto reutilizado): cierto estado interno de una petición puede sobrevivir después de que su memoria fue liberada. La siguiente petición que atiende el mismo worker puede usar ese estado corrupto antes de que se reinicie correctamente.
El resultado práctico es el peor escenario posible: un atacante envía peticiones de subida de archivos especialmente construidas y consigue que el servidor ejecute su código o le entregue trozos de memoria del worker. Esa memoria puede incluir la cookie PHPSESSID y secretos de la aplicación, aunque tu aplicación nunca use sesiones, porque todo ocurre antes de que tu código se ejecute. La configuración de mayor riesgo, según el propio equipo de PHP, es Apache con mod_php.
El nombre "PHP2Shell" viene de una herramienta de explotación cuya captura circuló tras la filtración: su autor presume compatibilidad con PHP desde la versión 5.4. La firma watchTowr confirmó que los fallos son reales y logró reproducir el primero; Sansec, especializada en proteger tiendas en línea, anticipa ataques masivos en cuestión de minutos una vez que los atacantes comparen el código viejo con el parcheado.
Cronología de una filtración que adelantó todo
- 20 de octubre, ~15:20 UTC: aparecen en Hacker News detalles de los dos fallos, antes de la fecha pactada de publicación (la publicación original fue borrada después).
- 20 de octubre, tarde: investigadores como Kevin Beaumont alertan públicamente; watchTowr confirma la existencia de ambas vulnerabilidades y que reprodujo CVE-2026-109618.
- 20 de octubre, 19:33 UTC: el equipo de seguridad de PHP anuncia por su lista oficial una actualización de emergencia para el 21 de octubre a las 14:00 UTC, adelantando el plan original, y pide a todos los usuarios prepararse para actualizar en cuanto salga.
- 21 de octubre: se publican las versiones corregidas (8.5.12, 8.4.27, 8.3.36, 8.2.35) junto con los avisos oficiales (GHSA-w8hw-w9fx-j79w y GHSA-6wmf-4rv5-p3rp). Cloudflare despliega reglas de su WAF contra los vectores conocidos, incluso para planes gratuitos. La BSI alemana emite alerta de riesgo alto, el NCSC de Países Bajos baja su propio sitio por precaución y el NCSC británico aconseja desconectar los sitios que no puedan parchearse.
Moraleja de la cronología: esto no es un susto teórico. Hay exploit circulando, gobiernos apagando sitios por precaución y una ventana de exposición que se mide en horas, no en semanas.
¿Estás afectado? Revisa tu versión de PHP
Estás afectado si tu servidor web corre PHP por debajo de la versión corregida de tu rama:
- Rama 8.5: vulnerable hasta 8.5.11 → actualiza a 8.5.12
- Rama 8.4: vulnerable hasta 8.4.26 → actualiza a 8.4.27
- Rama 8.3: vulnerable hasta 8.3.35 → actualiza a 8.3.36
- Rama 8.2: vulnerable hasta 8.2.34 → actualiza a 8.2.35
- Rama 8.1 y anteriores: sin versión oficial corregida (fin de vida)
Formas rápidas de comprobarlo:
# En el servidor o dentro del contenedor
php -v
# En Docker Compose
docker compose exec app php -v
# Desde fuera, si tu servidor expone la cabecera
curl -sI https://tu-sitio.com | grep -i x-powered-by
# X-Powered-By: PHP/8.3.35 ← vulnerable
Dos advertencias importantes. Primera: si instalas PHP con los paquetes de Debian o Ubuntu, tu distribución puede aplicar el parche sin cambiar el número de versión; en ese caso manda el aviso de seguridad de tu distribución, no solo el php -v. Segunda: actualizar WordPress, Laravel o tu CMS no corrige nada de esto. El fallo está en PHP, una capa por debajo de tu aplicación.
Y ojo con el inventario completo: no revises solo tu sitio principal. El WordPress de marketing que nadie toca, el entorno de pruebas, el phpMyAdmin expuesto y esa tienda vieja en un subdominio también cuentan. Los escáneres automáticos no distinguen entre "el sitio importante" y "el olvidado".
La solución real: actualizar PHP hoy
No hay atajo: la única corrección completa es correr una versión parcheada (o un paquete de tu proveedor con el parche aplicado y verificado). Según tu entorno:
- Servidor con paquetes (Debian/Ubuntu):
apt update && apt upgrade y reinicia los servicios: no basta recargar el servidor web, hay que reiniciar los workers de PHP-FPM (y Apache si usas mod_php), porque un worker viejo puede seguir vivo con el código vulnerable.
- Docker: reconstruye forzando la descarga de la imagen base nueva y redespliega (detalle en la sección de contenedores).
- Hosting compartido o cPanel: depende de tu proveedor; revisa la sección de hosting compartido y, si no ves movimiento, abre un ticket hoy.
- PHP 8.1 o anterior: planifica desde ya la migración a 8.2 o superior. Mientras tanto, aplica las mitigaciones de abajo y valora los parches de proveedores con soporte extendido.
Dato para quien usa los repositorios rpms.remirepo.net: el propio aviso de PHP señala que hoy no tendrán paquetes actualizados; usa los paquetes de tu distribución o compila desde la fuente oficial.
Mitigaciones temporales mientras actualizas
Si no puedes actualizar en este momento, estas medidas reducen el riesgo. Ninguna sustituye el parche: el propio equipo de PHP advierte que no existe una configuración que corrija el fallo por completo.
1. Bloquea las peticiones multipart en el borde
Todos los vectores conocidos usan peticiones multipart/form-data. Rechazarlas en el servidor web, antes de que lleguen a PHP, corta el ataque. El costo: se rompen las subidas de archivos (formularios con adjuntos, la biblioteca de medios de WordPress, importaciones CSV y algunos checkouts). Prueba tu sitio después de aplicarlo.
Nginx (en cada bloque server que pase peticiones a PHP):
if ($http_content_type ~* "multipart/form-data") {
return 403;
}
Apache (en cada VirtualHost):
<If "%{HTTP:Content-Type} =~ /multipart\/form-data/i">
Require all denied
</If>
Caddy / FrankenPHP (en el bloque del sitio):
@multipart header Content-Type *multipart/form-data*
respond @multipart 403
¿Necesitas subidas sí o sí en tu panel? Pedir contraseña no protege, porque el fallo ocurre antes de tu aplicación. La salida razonable es permitir multipart solo desde IPs de confianza (tu oficina o tu VPN) y bloquearlo para el resto del mundo.
2. Ajuste de php.ini recomendado por Sansec
Sansec recomienda desactivar el registro de progreso de subida de sesiones, uno de los vectores confirmados:
session.upload_progress.enabled = 0
Algunos análisis añaden memory_limit = -1 porque el detonante es un error de falta de memoria. Tómalo con pinzas: es una capa parcial, tiene el riesgo de que una sola petición consuma toda la memoria del servidor, y el aviso oficial insiste en que ninguna combinación de ajustes equivale al parche. Si lo aplicas en contenedores, ponle un límite de memoria al contenedor y restaura tu valor normal en cuanto actualices. En PHP 8.5, CyberPanel también sugiere fatal_error_backtraces = 0 para cerrar una ruta concreta; igualmente parcial.
3. Si usas Cloudflare, actívalo como escudo
Cloudflare desplegó reglas de WAF contra los vectores conocidos, también en el plan gratuito. Si tu dominio pasa por su proxy (nube naranja), ya tienes una capa extra. Pero protege solo el tráfico que pasa por Cloudflare: si tu servidor también responde por su IP directa, un atacante puede saltarse el escudo.
4. Plan B extremo: modo solo lectura
Para sitios mayormente informativos, aceptar solo GET y HEAD en el servidor web mantiene el sitio visible mientras parcheas. Los formularios dejan de funcionar, pero el ataque también. Ojo: el "modo mantenimiento" de Laravel o WordPress no sirve, porque PHP sigue procesando la petición antes de responder; el bloqueo tiene que estar en Nginx, Apache o Caddy, delante de PHP.
Guía rápida por entorno
Docker y Docker Compose
En contenedores el parche no "llega": hay que reconstruir la imagen y redesplegar. Antes de nada, verifica si Docker Hub ya trae la versión corregida:
docker pull php:8.4-fpm && docker run --rm php:8.4-fpm php -v
Si devuelve 8.4.27 o superior, reconstruye y redespliega:
docker compose build --pull
docker compose up -d --force-recreate
docker compose exec app php -v
Dos trampas que dejan a mucha gente expuesta creyendo que ya actualizó: usar tags fijos en el Dockerfile (FROM php:8.3.12-fpm o un digest @sha256:... nunca cambia: hay que editarlo) y reconstruir sin --pull, reutilizando la imagen base vieja que ya está en caché.
Coolify, Railway y plataformas con Nixpacks
Si despliegas con Nixpacks (lo usan Railway, Coolify, Dokploy y EasyPanel, entre otros), hay un problema extra: Nixpacks instala PHP desde una instantánea fija de nixpkgs definida dentro del propio Nixpacks. Hasta que Nixpacks publique una versión con la instantánea actualizada, cada despliegue seguirá trayendo el PHP vulnerable, aunque redespliegues hoy.
Qué puedes hacer mientras tanto:
- Aplica el bloqueo de multipart a nivel de la plataforma o de un proxy delante de tu app (si tu Coolify usa Traefik o Caddy como proxy, el bloqueo va ahí).
- Pásate a un Dockerfile propio: Coolify, Railway y Dokploy lo usan automáticamente si lo encuentran en la raíz del proyecto. Con un Dockerfile basado en
php:8.4-fpm (o la rama que uses) controlas tú cuándo se actualiza PHP: basta reconstruir con --pull.
- Si usas Railpack/FrankenPHP: el parche llega cuando FrankenPHP publique una versión compilada con el PHP corregido; revisa sus releases antes de redesplegar y usa el bloqueo de Caddy como mitigación.
Hosting compartido y cPanel
Aquí no controlas el servidor, pero sí puedes (y debes) moverte hoy:
- CloudLinux (muy común en hosting con cPanel/Plesk): está publicando versiones corregidas de todas sus alt-php, desde la 5.2 hasta la 8.5, incluyendo ramas viejas sin soporte oficial. Si tu hosting usa CloudLinux, el parche llega como actualización de paquetes del proveedor.
- cPanel con EasyApache 4: las versiones corregidas de ea-php (de 7.4 a 8.5) llegan con EasyApache 4 v25.91.
- Imunify360: su conjunto de reglas 8.83 añade un "parche virtual" de ModSecurity que bloquea el patrón del exploit público. Ayuda, pero cubre un solo vector: no es la corrección.
- TuxCare ELS: si tu proveedor paga soporte extendido para PHP en fin de vida, sus paquetes corregidos se publican tras validación.
Traducción práctica: entra a tu panel, revisa qué versión de PHP corre tu sitio (cPanel lo muestra en "Select PHP Version" o "MultiPHP Manager") y, si sigue vulnerable, abre un ticket hoy preguntando por el plan de parcheo de CVE-2026-109618. Un proveedor serio ya está en ello; uno que no responde a esto tampoco responderá el día del incidente.
WordPress, WooCommerce y otros CMS
Que tu WordPress esté actualizado no te protege: el fallo está en PHP, no en el CMS. Se demostró el ataque contra instalaciones recientes de WordPress, Drupal, Joomla y Magento. Lo que sí puedes hacer desde el panel: confirmar la versión de PHP del hosting (Salud del sitio en WordPress lo muestra), exigir el parche a tu proveedor y, si tu hosting lo permite, subir tu sitio a una rama 8.2+ ya corregida desde el selector de versión de PHP.
Después de actualizar: no bajes la guardia
- Verifica la versión real en producción con
php -v en cada servidor y contenedor, y reinicia los workers: una recarga del servidor web puede dejar procesos PHP viejos atendiendo peticiones.
- Retira las mitigaciones temporales: el bloqueo de multipart, los ajustes de
php.ini y, muy importante, restaura tu memory_limit normal si lo habías cambiado.
- Rota los secretos si estuviste expuesto: como el fallo puede filtrar memoria del worker, cambia por precaución contraseñas de base de datos, claves de API,
APP_KEY de Laravel y tokens que vivieran en ese proceso.
- Revisa los registros buscando peticiones multipart inusuales hacia rutas que normalmente no reciben subidas, errores de memoria repetidos y accesos desde IPs extrañas en las últimas 48 horas.
Checklist rápida PHP2Shell
- Inventarié todos mis sitios y servidores con PHP, incluidos los olvidados.
- Comprobé la versión de PHP en cada uno (
php -v o el panel de hosting).
- Actualicé a 8.5.12 / 8.4.27 / 8.3.36 / 8.2.35, o confirmé el parche de mi proveedor.
- Si no pude actualizar aún: bloqueé multipart en el borde o activé el proxy de Cloudflare.
- En contenedores: reconstruí con
--pull y redesplegué; nada de tags fijos viejos.
- En Nixpacks/Coolify: mitigación aplicada o migración a Dockerfile propio planificada.
- Si sigo en PHP 8.1 o anterior: plan de migración a 8.2+ en marcha.
- Tras parchear: quité las mitigaciones, restauré
memory_limit, roté secretos y revisé logs.
Preguntas frecuentes sobre PHP2Shell
¿Actualizar WordPress o mi tema me protege?
No. La vulnerabilidad está en el propio PHP. Puedes tener el CMS más actualizado del mundo y seguir expuesto si el PHP del servidor es vulnerable.
Mi sitio no permite subir archivos. ¿Estoy a salvo?
No necesariamente. El atacante no usa tu formulario: envía directamente la petición multipart maliciosa al servidor, y PHP la procesa antes de que tu aplicación decida nada. Por eso pedir login tampoco protege.
¿Qué pasa si mi hosting usa PHP 7.4 u 8.1?
Esas ramas no recibirán versión oficial corregida. Algunos proveedores (CloudLinux, TuxCare) publican sus propios parches, y el equipo de PHP facilitó parches de código fuente para 7.4, 8.0 y 8.1. Si tu proveedor no ofrece ninguna de esas vías, la respuesta es migrar a PHP 8.2 o superior cuanto antes.
¿Ya hay ataques reales?
Hay código de explotación circulando desde la filtración del 20 de octubre, watchTowr confirmó que el fallo es explotable, Cloudflare reportó ataques antes del parche y Sansec espera explotación masiva inmediata tras la publicación de las correcciones (los atacantes pueden deducir el fallo comparando versiones). Varios organismos públicos europeos bajaron sitios por precaución. No es momento de "esperar a ver".
¿La mitigación de bloquear multipart rompe mi sitio?
Rompe las subidas de archivos legítimas mientras esté activa: formularios con adjuntos, subida de imágenes en paneles, importaciones. El resto del sitio sigue funcionando. Es un sacrificio temporal y consciente hasta completar la actualización.
Uso Laravel con Coolify, ¿qué hago exactamente?
Si despliegas con Nixpacks, redesplegar no basta por la instantánea fija de PHP. Aplica el bloqueo de multipart en el proxy, o mejor: añade un Dockerfile propio a tu proyecto (Coolify lo detecta automáticamente) basado en la imagen php:8.3-fpm u 8.4-fpm ya corregida, reconstruye y verifica con php -v dentro del contenedor.
En resumen
PHP2Shell es de esas vulnerabilidades que separan a los equipos que reaccionan en horas de los que se enteran por las noticias de la semana siguiente. El parche ya existe: actualiza a PHP 8.5.12, 8.4.27, 8.3.36 u 8.2.35, y si tu entorno no te lo permite todavía, bloquea las peticiones multipart en el borde y desactiva el upload_progress de sesiones como red de seguridad temporal.
En ARCADIG HUB estamos ayudando a nuestros clientes a auditar servidores, contenedores y despliegues en Coolify frente a CVE-2026-109618 y CVE-2026-109619. Si tienes aplicaciones PHP en producción y no sabes por dónde empezar, conversemos: revisamos tu exposición y te dejamos parcheado, no solo informado.
Fuentes