Mitigación PHP2Shell: Qué Configurar y Por Qué No Es Suficiente

Los tres ajustes oficiales compran tiempo, no seguridad. Descubra dónde aplicarlos, cómo reiniciar cada worker PHP y qué hacer hasta que llegue el parche.

por Cleverson Gouvêa

Mitigación PHP2Shell: Qué Configurar y Por Qué No Es Suficiente

La mitigación PHP2Shell que aplica hoy en php.ini compra tiempo, pero no cierra la puerta. Las dos fallas (CVE-2026-109618 y CVE-2026-109619) permiten la ejecución remota de código sin necesidad de login en prácticamente cualquier servidor PHP expuesto. En esta guía le muestro qué configurar mientras la actualización no llega, cómo reiniciar todos los workers de la manera correcta y por qué el propio equipo de PHP afirma que nada de esto sustituye el parche.

TL;DR

  • PHP2Shell son dos fallas críticas (CVSS 4.0 = 9.2), sin autenticación. La corrección se publicó el 21/10/2026 en las versiones 8.5.12, 8.4.27, 8.3.36 y 8.2.35.
  • La mitigación PHP2Shell oficial tiene tres ajustes: memory_limit=-1, session.upload_progress.enabled=0 y, en PHP 8.5, fatal_error_backtraces=0. Estos reducen la exposición, pero no hacen que el servidor sea seguro.
  • La configuración solo es efectiva después de que cada proceso PHP es reiniciado: FPM, Apache con mod_php, colas, workers de larga duración y contenedores.
  • PHP 7.4 a 8.1 solo tienen backports mínimos de código fuente. PHP 5.4 a 7.3 no tienen ninguna corrección: la solución es migrar.
  • El 23/10 se emitió una alerta adicional (CVE-2026-115560). Quien ya haya desactivado el progreso de carga (upload progress) está cubierto hasta la próxima versión regular.

Qué es PHP2Shell y por qué la urgencia

PHP2Shell es el apodo de dos vulnerabilidades en el núcleo de PHP que permiten a un atacante anónimo ejecutar código en su servidor con una petición HTTP bien construida. No necesita contraseña, plugin vulnerable ni error de la aplicación.

  • CVE-2026-109618 es una corrupción por falta de memoria (out-of-memory). PHP se queda sin memoria en medio del montaje de la petición, deja estructuras internas a medias y, en la limpieza, utiliza esos datos inválidos.
  • CVE-2026-109619 es un problema de estado global obsoleto, un use-after-free entre peticiones. Un estado interno sobrevive a la memoria de la petición anterior, y la siguiente petición atendida por el mismo worker actúa sobre ese resto.

La línea de tiempo explica la urgencia. Según las Preguntas Frecuentes de Tenable, Amazon registró un intento de explotación en sus honeypots el 17/10, cuatro días antes de la divulgación. Los detalles se filtraron en redes sociales el 20/10, antes de la fecha acordada, y PHP anticipó el parche para el 21/10/2026. watchTowr informa de intentos de explotación en su red de honeypots desde el día 21.

El alcance también asusta. Palo Alto Networks (propietaria de Unit 42) afirmó haber identificado más de 22,6 millones de instancias expuestas potencialmente vulnerables, según TechTarget. Otros recuentos son menores, porque cada empresa mide de una manera. El mensaje es el mismo para todas: si ejecuta WordPress, Laravel, Moodle o un sistema PHP propio, está dentro del alcance.

Qué versiones están afectadas

Rama de PHP Situación Qué hacer
8.5 Corregido en la 8.5.12 Actualizar ya
8.4 Corregido en la 8.4.27 Actualizar ya
8.3 Corregido en la 8.3.36 Actualizar ya
8.2 Corregido en la 8.2.35 Actualizar y planificar la retirada (fin de vida el 31/12/2026)
7.4, 8.0 y 8.1 Sin versión oficial; solo backports mínimos de código fuente Paquete de distro/LTS o migrar a 8.2+
5.4 a 7.3 Sin corrección Migrar o retirar de internet

Mitigación PHP2Shell en tres ajustes oficiales

El aviso de seguridad de PHP enumera tres configuraciones de mitigación PHP2Shell para quienes aún no pueden actualizar. Cada una ataca una vía específica de explotación, y ninguna lo cubre todo.

1. memory_limit=-1 (contra la CVE-2026-109618)

La falla de out-of-memory depende de que PHP alcance el límite de memoria en un punto predecible. Con memory_limit=-1, ese límite por petición deja de existir. PHP solicita que el ajuste se realice de manera que la aplicación no pueda sobrescribirlo, por ejemplo con php_admin_value en el pool de FPM o en la configuración de Apache, y que verifique que ningún pool, directorio o aplicación restablezca un límite finito.

El equipo de PHP hace una advertencia que afecta a mucha gente: no lo sustituya por RLIMIT_AS o RLIMIT_DATA, porque esos límites del sistema operativo pueden provocar precisamente la falla de asignación vulnerable.

2. session.upload_progress.enabled=0 (contra la CVE-2026-109619)

La función de upload progress de las sesiones viene activada por defecto y es una de las vías confirmadas de explotación. Desactivarla cierra esta vía. El propio PHP advierte que esto "bloquea las vías de sesión confirmadas, pero no otras variantes".

3. fatal_error_backtraces=0 (solo en PHP 8.5)

En PHP 8.5, el backtrace de error fatal es otra vía confirmada de la CVE-2026-109619. Desactivarlo bloquea solo esta vía.

Dónde colocar (y dónde no)

La regla de oro de la mitigación PHP2Shell es simple: el ajuste debe ser efectivo antes de que PHP procese la petición. Use php.ini, el pool de FPM o la configuración del servidor web. No confíe en ini_set() ni en .user.ini, porque se aplican demasiado tarde.

; /etc/php/8.3/fpm/pool.d/www.conf (ajuste la ruta a su versión)
php_admin_value[memory_limit] = -1
php_admin_value[session.upload_progress.enabled] = 0
; solo PHP 8.5:
php_admin_value[fatal_error_backtraces] = 0

La guía de CIQ para Rocky Linux añade dos refuerzos opcionales: post_max_size = 8M cuando la aplicación no recibe cargas (32M cuando las recibe, con upload_max_filesize por debajo de eso) y pm.max_requests = 1 en FPM, que impide la herencia de estado entre peticiones a costa de mucha pérdida de rendimiento.

Por qué la mitigación PHP2Shell no es suficiente

Aquí reside el error más costoso: aplicar los tres ajustes, ver el sitio en línea y tachar la tarea de la lista. PHP es directo en su aviso: estas medidas reducen la exposición, pero no hacen que la instalación sea segura. La única corrección completa es actualizar.

Son cuatro motivos prácticos:

  1. Cobertura parcial. La mitigación PHP2Shell cierra las vías confirmadas. Las variantes que nadie ha publicado aún siguen abiertas.
  2. memory_limit=-1 no elimina la falla de memoria. Según CIQ, fallas de mmap() u otras asignaciones aún pueden llegar al segmento vulnerable. Solo elimina el detonante más fácil.
  3. Efecto colateral real. Sin límite de memoria, un script con un bucle infinito o un informe pesado puede consumir toda la RAM del servidor y activar el OOM killer de Linux. La recomendación es establecer un límite por contenedor o cgroup, preferiblemente un grupo por worker. PHP lo trata como una barrera de disponibilidad, no como una mitigación completa.
  4. WAF ayuda, pero no decide. Cloudflare publicó reglas de emergencia, pero solo protegen el tráfico que pasa por ella, y la propia empresa reconoce que las reglas basadas en peticiones no separan con fiabilidad el ataque del tráfico legítimo.

Tabla de decisión rápida

Ajuste Bloquea No bloquea Coste
memory_limit=-1 Detonante predecible de OOM Fallas de mmap() y otras asignaciones Riesgo de que un script tumbe el servidor
session.upload_progress.enabled=0 Vías de sesión confirmadas Otras variantes de la 109619 Desaparece la barra de progreso nativa de carga
fatal_error_backtraces=0 (8.5) Vía del backtrace fatal Las demás vías Menos detalle en los logs de error
pm.max_requests=1 Herencia de estado entre peticiones La falla de OOM Fuerte caída de rendimiento
WAF (Cloudflare etc.) Parte de los payloads conocidos Tráfico que no pasa por el WAF Falsos positivos

La CISA, agencia de ciberseguridad de EE. UU., fue más allá: recomendó retirar de servicio los sistemas PHP que no puedan ser corregidos o que ejecuten PHP 8.1 o anterior. La CERT-EU sugiere aislar las aplicaciones expuestas hasta que la corrección sea aplicada y verificada.

Cómo reiniciar workers sin dejar procesos antiguos atrás

La nueva configuración y el nuevo binario solo son efectivos cuando cada proceso PHP es reiniciado. PHP lo repite en cada punto del aviso: "reinicie todos los workers". En la práctica, es aquí donde muchas correcciones quedan a medias: sin un reinicio, la mitigación PHP2Shell solo existe en el archivo.

PHP-FPM y Apache

# Debian/Ubuntu (ajuste la versión)
sudo systemctl restart php8.3-fpm
# Apache con mod_php: reinicio completo, no solo graceful
sudo systemctl restart apache2   # o httpd en RHEL/Rocky

Prefiero restart a reload en una corrección de seguridad. Es un corte de pocos segundos, que usted programa, a cambio de la certeza de que ningún proceso antiguo ha sobrevivido.

Los procesos que todo el mundo olvida

CIQ recuerda que todos los procesos PHP necesitan reiniciarse, incluidos los jobs de CLI de larga duración. En la lista de verificación entran:

  • Colas Laravel: php artisan queue:restart (o reinicio de Horizon) y Octane con php artisan octane:reload.
  • Programas de Supervisor: sudo supervisorctl restart all en los grupos que ejecutan PHP.
  • Moodle: el cron y los ejecutores de tareas ad hoc que se ejecutan en bucle.
  • Contenedores: docker restart reutiliza la misma imagen. Necesita descargar la imagen corregida y recrear el contenedor (docker compose pull && docker compose up -d).
  • Aplicaciones que incrustan su propio PHP: dependen de la actualización del proveedor.

Cómo verificar que ha funcionado

  1. No confíe en el php -v del terminal: muestra la CLI, que puede ser otro binario. Verifique lo que el servidor web está utilizando:
  2. Cree un archivo temporal, accesible solo por su IP, con <?php echo PHP_VERSION, ' ', ini_get('memory_limit'), ' ', ini_get('session.upload_progress.enabled');. Acceda, compruebe y elimine el archivo.
  3. Vea la hora de inicio de los procesos con ps -o pid,lstart,cmd -C php-fpm8.3. Todo debe ser más reciente que la instalación del paquete.
  4. En Debian/Ubuntu, needrestart enumera los servicios que aún cargan bibliotecas antiguas.

Plan de 72 horas: qué hacer y en qué orden

Si tiene un servidor PHP expuesto y aún no ha actualizado, este es el orden que seguiría para combinar la mitigación PHP2Shell y la actualización:

  1. Inventario (hora 0). Liste todos los hosts con PHP, versión, SAPI (FPM, mod_php, CGI) y quién está expuesto a internet. El mod_php es el más expuesto, con RCE confirmado en configuración estándar.
  2. Conserve los logs. Antes de reiniciar o reconstruir, guarde los logs del servidor web. Amazon recomienda investigar a partir del 17/10.
  3. Aplique la mitigación PHP2Shell (horas 1-2) con los tres ajustes, en el lugar correcto, y reinicie todos los workers.
  4. Actualice (horas 2-24). Ramas 8.2 a 8.5: paquete de la distribución o del repositorio que utilice. 7.4 a 8.1: paquete LTS de la distro, si existe. 5.4 a 7.3: aísle y programe la migración.
  5. Reinicie de nuevo y verifique con las tres pruebas anteriores.
  6. Caza de rastros (horas 24-72). Nuevos archivos PHP en carpetas de carga, usuarios administrativos creados en los últimos días, cron extraño. Como recuerdan los analistas consultados por TechTarget, actualizar no elimina un acceso que el atacante ya haya conseguido. En un servidor expuesto y sin parche, cambie las credenciales que el worker PHP tenía en memoria (base de datos, APIs, SMTP).
  7. Solo entonces revierta lo que sea incómodo, como el memory_limit=-1, devolviendo un límite finito razonable.

Cuándo NO aplicar la mitigación PHP2Shell a ciegas

  • Servidor pequeño y compartido con muchos sitios: memory_limit=-1 sin cgroup es una invitación a que un sitio tumbe a todos. En ese caso, actualizar directamente suele ser más seguro que mitigar.
  • Aplicación que muestra barra de progreso de carga utilizando la función nativa de sesión: avise al equipo antes, porque la barra dejará de funcionar.
  • Entorno que no puede reiniciar fuera de la ventana de mantenimiento: el ajuste no sirve de nada hasta el reinicio. Negocie la ventana ahora.

La alerta del 23/10: CVE-2026-115560

Dos días después del parche, PHP publicó un aviso informativo sobre la CVE-2026-115560, un vector de RCE que afecta incluso a versiones ya corregidas, como la 8.5.12. La buena noticia: solo existe si la aplicación define session.serialize_handler como php_binary o php_serialize en la configuración y cambia a php en tiempo de ejecución con ini_set() antes de session_start(), con el progreso de carga (upload progress) aún activado.

PHP clasificó el escenario como improbable y lo corregirá en la próxima versión regular. La orientación es mantener session.upload_progress.enabled=0 hasta entonces. Si aplicó este elemento de la mitigación PHP2Shell el día 21, no necesita hacer nada más, como resumió The Hacker News. Por ello, no revierta este ajuste junto con el memory_limit después del parche.

Qué significa esto para Moodle, WordPress y Laravel

PHP2Shell afecta al intérprete, no a la aplicación. Por lo tanto, no sirve de nada esperar una actualización de Moodle o WordPress: quien lo resuelve es el paquete PHP del servidor.

En Moodle, el punto de atención es la memoria. El propio Moodle eleva el límite en tiempo de ejecución en tareas pesadas, como la copia de seguridad de cursos y los informes. Con memory_limit=-1 esto deja de ser un problema, pero una copia de seguridad grande puede consumir toda la RAM. Si aún está en PHP 8.1 debido a una versión antigua de Moodle, este es el momento de revisar los requisitos de servidor para Moodle 5.x y planificar el salto.

En WordPress y Laravel, el mayor cuidado es con los workers de larga duración (colas, Octane, cron del sistema) y con los alojamientos compartidos en los que no controla PHP. Si su proveedor no le ha informado la versión y la fecha del reinicio, pregunte por escrito.

La mitigación PHP2Shell tampoco sustituye lo básico. Si el servidor nunca ha pasado por una lista de verificación de hardening de servidor Linux, o si aún no tiene WAF, fail2ban y rate limit, la próxima falla encontrará la misma puerta abierta.

Cómo Agathas Web resuelve esto

La pregunta que este incidente dejó a muchas empresas no es técnica: es quién estaba de guardia el día 21. Cuando la corrección se publica a las 14h UTC de un miércoles, alguien necesita inventariar, aplicar, reiniciar, verificar y buscar rastros el mismo día. Si esa persona no existe en su equipo, ese es el servicio que vendemos.

En el alojamiento gestionado de Agathas Web, el soporte incluye:

  • Actualización de sistema operativo, runtime (PHP, Node, Python), base de datos y plugins críticos, en ventana acordada y con pruebas en staging antes de producción.
  • Monitorización continua (uptime, rendimiento, errores y logs) con Grafana, Prometheus y Sentry, y alerta en el WhatsApp del equipo técnico.
  • WAF de Cloudflare con reglas personalizadas, fail2ban, rate limit y hardening del sistema operativo.
  • Copia de seguridad diaria e incremental, cifrada y fuera del servidor, con restauración probada cada mes.
  • Respuesta en hasta 15 minutos para incidentes críticos, con SLA en el contrato y plan de incidentes documentado.
  • Atención directa con quien opera su entorno, sin central de nivel 1 leyendo un guion.

Cómo funciona: comenzamos con un diagnóstico del entorno actual (versiones, SAPI, workers, exposición). Si tiene sentido migrar, realizamos la migración en hasta 7 días hábiles con un plan de rollback. Después de eso, alertas como esta entran en nuestro flujo de soporte: la mitigación PHP2Shell (o la equivalente de la próxima falla) en el intervalo hasta el parche, la actualización en ventana acordada y el reinicio verificado de los workers, sin que usted necesite abrir una incidencia. Para contratar, hable con el equipo por WhatsApp en la página del alojamiento gestionado y describa lo que ejecuta hoy. Si su caso es un AVA, también tenemos el alojamiento Moodle dedicado.

Conclusión: mitigue hoy, actualice mañana, verifique siempre

La mitigación PHP2Shell es un torniquete. Detiene la hemorragia durante unas horas mientras actualiza a 8.5.12, 8.4.27, 8.3.36 o 8.2.35, reinicia todos los workers y confirma a través del servidor web que la nueva versión está en funcionamiento. Quien se detuvo en el php.ini está menos expuesto, pero sigue expuesto.

Si aún ejecuta PHP 8.1 o anterior, PHP2Shell es el empujón que faltaba: no habrá una versión oficial para esas ramas. Y si su servidor depende de que alguien recuerde revisar las noticias de seguridad, quizás el problema real sea ese. Conozca el alojamiento gestionado de Agathas Web y deje el próximo parche de emergencia en manos de quienes operan servidores todos los días.