mod_php o PHP-FPM: Riesgo, Rendimiento y Migración
PHP señaló a mod_php como el peor escenario en PHP2Shell. Descubre qué cambia en la arquitectura y cómo migrar a FPM sin detener el sitio.
por Cleverson Gouvêa

Elegir entre mod_php o PHP-FPM ha dejado de ser una decisión de rendimiento para convertirse en una decisión de riesgo. En el aviso del 21 de octubre de 2026 sobre PHP2Shell, el propio equipo de seguridad de PHP escribió que el riesgo es mayor en mod_php, porque el ataque demostrado se activa antes de cualquier línea del código de la aplicación. En esta comparativa muestro la diferencia de arquitectura, seguridad y rendimiento, y cómo migrar sin desconectar el sitio.
TL;DR
- PHP2Shell (CVE-2026-109618 y CVE-2026-109619) es ejecución remota de código sin autenticación, con CVSS 4.0 de 9,2. La corrección salió el 21/10/2026 en las versiones 8.5.12, 8.4.27, 8.3.36 y 8.2.35.
- Todos los modos de ejecutar PHP para web están afectados: PHP-FPM, Apache con mod_php, php-cgi, FrankenPHP y LiteSpeed. Pero PHP clasifica a mod_php como el escenario de mayor riesgo.
- Migrar a PHP-FPM no sustituye el parche. El orden correcto es actualizar PHP primero y migrar después, con calma.
- El propio manual de PHP ya dice que no se use mod_php en instalaciones nuevas: retiene a Apache en el MPM prefork, lo que limita significativamente la concurrencia.
- La migración en Apache requiere pocos comandos, pero tiene trampas reales:
php_valueen el.htaccessdeja de funcionar y el pool de FPM necesita ser dimensionado.
Qué cambia en la elección mod_php o PHP-FPM después de PHP2Shell
Hasta la semana pasada, la conversación sobre mod_php o PHP-FPM era sobre memoria, concurrencia y comodidad. mod_php era el camino "funciona a la primera" de Apache, y muchos servidores antiguos se quedaron en él por inercia.
PHP2Shell cambió el peso de esta elección. Los hechos, confirmados en las fuentes oficiales:
- Dos fallos, ambos sin autenticación. La CVE-2026-109618 es una corrupción de memoria en el tratamiento de out-of-memory (falta de memoria): PHP se interrumpe con datos internos de la petición montados a medias, y la limpieza al final de la petición trata esos datos como válidos. La CVE-2026-109619 es un estado global obsoleto (use-after-free): un dato interno sobrevive a la memoria a la que apuntaba, y la siguiente petición en el mismo proceso utiliza esa basura.
- Gravedad. Ambas tienen CVSS 4.0 de 9,2, según el equipo de seguridad de PHP. El FAQ de Tenable registra que identificadores con una puntuación de 10,0 circularon antes y eran erróneos.
- Cronología. Amazon vio un intento de explotación en su honeypot el 17/10, cuatro días antes de la divulgación, según Tenable. Los detalles se filtraron el 20/10, antes de la fecha coordinada, y PHP anticipó la corrección para el 21/10 a las 14h UTC, según Huntress.
- Exposición. Unit 42, de Palo Alto Networks, contó a través de Cortex Xpanse más de 22,6 millones de instancias expuestas potencialmente vulnerables.
Y la frase que cambia la ecuación de mod_php o PHP-FPM para quien decide la infraestructura procede del aviso oficial de PHP: el riesgo se considera mayor para mod_php, "con un exploit demostrado en el que una petición no autenticada puede activar el ataque antes de que cualquier código de la aplicación se ejecute".
Traduciendo para los responsables: en mod_php, no importa si tu WordPress, Moodle o Laravel está actualizado y bien escrito. El ataque ocurre antes de que la aplicación tenga la oportunidad de hacer cualquier cosa.
Arquitectura: cómo cada modelo ejecuta PHP
mod_php: PHP dentro de Apache
En mod_php (el módulo apache2handler), el intérprete PHP se carga dentro de cada proceso de Apache. Cada proceso hijo del servidor web es, al mismo tiempo, servidor HTTP e intérprete PHP.
Esto tiene dos consecuencias directas:
- Apache queda anclado al MPM prefork. El manual de PHP dice que, sin PHP compilado con thread safety (ZTS), mod_php exige prefork, "lo que limita significativamente la concurrencia". La mayoría de los paquetes de distribución no vienen con ZTS.
- Todo proceso carga PHP, incluso para servir una imagen. Una petición de
logo.pngocupa un proceso entero con el intérprete cargado.
PHP-FPM: PHP como servicio separado
En PHP-FPM (FastCGI Process Manager), PHP se ejecuta en un servicio propio, con pools de procesos. El servidor web (Apache con mod_proxy_fcgi o Nginx) solo reenvía las peticiones .php al pool, por socket Unix o TCP.
Cada pool tiene su usuario, su límite de procesos y sus configuraciones. La documentación de configuración de FPM incluye las directivas que marcan la diferencia en la práctica: user/group, pm.max_children, pm.max_requests, request_terminate_timeout y php_admin_value, esta última con valores que el script no puede sobrescribir con ini_set().
¿Y quién usa Nginx?
Nginx no tiene módulo de PHP embebido. Si tu sitio se ejecuta en Nginx, ya estás en PHP-FPM (o en otro proceso FastCGI) y la pregunta mod_php o PHP-FPM no se aplica. Esto no te exime de PHP2Shell: FPM también está en la lista de afectados.
Seguridad: por qué mod_php es el peor escenario
El punto central en la comparación mod_php o PHP-FPM no es que FPM sea inmune. No lo es. El punto es que mod_php junta tres factores negativos en el mismo proceso.
El ataque se ejecuta antes de la aplicación
El informe técnico de Datadog Security Labs detalla lo que PHP confirmó. En la ruta de subida de CVE-2026-109619, hubo ejecución de comandos tanto en mod_php como en PHP-FPM, pero en FPM el ataque también exige que la aplicación realice una operación adecuada después de que la inicialización haya terminado. En mod_php, no existe esa condición.
Para CVE-2026-109618, Huntress registra que PHP validó RCE completo vía HTTP contra mod_php con los límites estándar de entrada y memoria y configuraciones prefork normales. El laboratorio de Datadog también usó Apache prefork con mod_php.
Un usuario para todos los sitios
En mod_php, todo sitio del servidor se ejecuta como el usuario de Apache (www-data en Debian/Ubuntu, apache en Red Hat). Si un atacante ejecuta un comando a través de un sitio, tiene el permiso de Apache, que normalmente lee los archivos de todos los sitios de ese servidor, incluyendo wp-config.php y config.php con contraseña de base de datos.
En PHP-FPM, el estándar saludable es un pool por sitio, cada uno con su usuario Linux. La invasión de un sitio queda contenida en los permisos de ese usuario. Es el mismo principio de menor privilegio que defiendo en la lista de verificación de hardening de servidor Linux.
Lo que PHP-FPM no resuelve
Aquí reside la trampa comercial: hay gente vendiendo "migra a FPM y estarás seguro". No es cierto.
- FPM sigue siendo vulnerable sin el parche. El aviso oficial lista a PHP-FPM entre los afectados.
- Datadog explica que un pool más grande reduce la probabilidad de éxito por intento, pero no elimina el fallo, y que los atacantes intentan ocupar todos los procesos menos uno para caer siempre en el mismo.
- El exploit exitoso no necesariamente derriba el proceso. El ataque puede generar solo dos a cuatro errores de memoria y luego quedar en silencio.
El orden es siempre: parche primero, arquitectura después.
Rendimiento y consumo de memoria
Prefork contra event
Con mod_php, Apache se ejecuta en prefork: un proceso por conexión, cada uno con PHP cargado. Conexiones lentas, keep-alive y archivos estáticos ocupan procesos pesados.
Con PHP-FPM, Apache puede usar el MPM event, que es el estándar desde Apache 2.4, como recuerda el manual de PHP. Event atiende muchas conexiones con pocos hilos ligeros, y solo lo que es PHP va al pool. El manual llega a llamar al MPM con hilos "recomendado para un mejor rendimiento bajo carga".
Dónde FPM gana en la operación
- Reiniciar PHP sin reiniciar Apache. Aplicar un parche, cambiar
php.inio matar un proceso bloqueado afecta solo a PHP. Esto cuenta mucho en una semana como esta, en la que PHP pide reiniciar todos los workers después del parche. - Límites por sitio. Un sitio con un plugin problemático no consume todos los procesos del servidor, porque su pool tiene un límite propio en
pm.max_children. - Diagnóstico.
request_slowlog_timeoutregistra el backtrace de peticiones lentas, ypm.status_pathmuestra en tiempo real cuántos procesos están ocupados. - Varias versiones de PHP lado a lado. Un pool en 8.3 y otro en 8.4 en el mismo servidor, algo que mod_php no hace.
Dónde mod_php aún "gana"
Siendo justos: en la balanza mod_php o PHP-FPM, mod_php tiene menos piezas. No hay socket, no hay segundo servicio que monitorizar y el .htaccess con php_value funciona directamente. En un servidor de laboratorio con un único sitio y tráfico mínimo, la diferencia de rendimiento es pequeña. Solo que, después de PHP2Shell, la simplicidad no compensa permanecer en el escenario de mayor riesgo.
Tabla comparativa: mod_php o PHP-FPM
El resumen de la comparación mod_php o PHP-FPM en los criterios que pesan en la operación de un servidor de producción:
| Criterio | mod_php (Apache) | PHP-FPM |
|---|---|---|
| Dónde se ejecuta PHP | Dentro de cada proceso de Apache | Servicio separado, con pools |
| MPM de Apache | Prefork (sin ZTS) | Event (estándar de Apache 2.4) |
| Riesgo en PHP2Shell, según PHP | El mayor: exploit antes del código de la aplicación | Afectado; en la ruta de subida de la 109619, depende de la operación de la aplicación |
| Usuario de ejecución | Uno solo (usuario de Apache) para todos los sitios | Uno por pool, aislando sitios |
| Reiniciar PHP | Reinicia Apache entero | Reinicia solo FPM (o un pool) |
| Varias versiones de PHP | No | Sí, un pool por versión |
| Límite de procesos por sitio | No | pm.max_children por pool |
| Configuración por directorio | php_value en el .htaccess |
.user.ini o php_admin_value en el pool |
| Recomendación del manual de PHP | No usar en instalaciones nuevas | Recomendado para implementaciones modernas |
| Soporte en Nginx | No existe | Estándar |
Cómo descubrir qué usa tu servidor hoy
Antes de decidir entre mod_php o PHP-FPM en tu caso, confirma el modo actual. Tres formas, de la más rápida a la más completa:
- Por Apache. Ejecuta
apachectl -M | grep -i php. Si aparecephp_module(ophp7_module,php8_module), mod_php está cargado. - Por el MPM. Ejecuta
apachectl -V | grep -i mpm.preforkes un fuerte indicio de mod_php;eventindica que PHP está fuera de Apache. - Con un
phpinfo()temporal. El campo Server API muestraApache 2.0 Handler(mod_php) oFPM/FastCGI. Borra el archivo inmediatamente después: unphpinfo()expuesto entrega la versión y las rutas a quien esté escaneando internet.
Aprovecha para anotar la versión exacta de PHP. Si está por debajo de 8.5.12, 8.4.27, 8.3.36 o 8.2.35 (o del paquete corregido de tu distribución), el problema urgente es ese, no la arquitectura.
Cómo migrar de mod_php a PHP-FPM sin tumbar el sitio
Si la respuesta para mod_php o PHP-FPM en tu servidor es migrar, la hoja de ruta a continuación es válida para Debian y Ubuntu con Apache 2.4, que es el escenario más común que encontramos. Sustituye 8.3 por tu versión.
Paso 0: parche antes de nada
Actualiza PHP a la versión corregida de tu distribución y reinicia Apache. Esto ya cierra la ventana de PHP2Shell en mod_php. La migración viene después, en una ventana planificada. Si aún no lo has hecho, este es el único paso que importa hoy. La duda mod_php o PHP-FPM puede esperar unos días; el parche no. En la publicación sobre cómo proteger el servidor web contra ataques explico las capas de WAF y rate limit que ayudan mientras tanto, sin sustituir la corrección.
Paso 1: instalar FPM y crear el pool
Instala php8.3-fpm con las mismas extensiones que usa mod_php (compara php -m antes y después). Crea un pool por sitio en /etc/php/8.3/fpm/pool.d/, con usuario propio, socket propio y límites:
userygroupdel sitio, nowww-datalisten = /run/php/site1.sockpm = dynamicypm.max_childrencalculado por la memoria (siguiente paso)pm.max_requests = 500, para reciclar procesos periódicamenterequest_terminate_timeoutcoherente con elmax_execution_timephp_admin_value[session.upload_progress.enabled] = 0, si la aplicación no usa barra de progreso de subida
Este último elemento procede del aviso oficial: bloquea las rutas de sesión confirmadas de CVE-2026-109619, pero no otras variantes. PHP pide aplicar en php.ini, en el pool de FPM o en la configuración del servidor, y para no confiar en ini_set() ni en .user.ini.
Paso 2: dimensionar el pool
La fórmula básica es pm.max_children = memoria disponible para PHP ÷ memoria media por proceso. Mide el consumo real con ps durante la hora punta, no uses memory_limit como estimación. Un pool demasiado pequeño genera cola y error 503; uno demasiado grande lleva al servidor a usar swap.
Si el servidor ejecuta Moodle, la cuenta cambia bastante entre horario normal y semana de exámenes. Los números de referencia están en la guía de requisitos de servidor para Moodle 5.x.
Paso 3: cambiar el modo de Apache
En Debian/Ubuntu, la secuencia típica es:
a2enmod proxy_fcgi setenvifa2enconf php8.3-fpm(o unSetHandler "proxy:unix:/run/php/site1.sock|fcgi://localhost"en el vhost, para pool por sitio)a2dismod php8.3a2dismod mpm_preforkya2enmod mpm_eventapachectl configtesty, si todo está correcto,systemctl restart apache2
El cambio interrumpe las conexiones por unos pocos segundos. Hazlo en horario de bajo tráfico y ten anotado el camino de vuelta: los mismos comandos, invertidos.
Paso 4: las trampas que rompen el sitio
php_valueyphp_flagen el.htaccess. Estas directivas solo existen en mod_php. En FPM, Apache devuelve un error 500. Mueve los valores al pool (php_admin_value) o a.user.ini.- Permisos de archivo. Con el nuevo usuario del pool, las carpetas de subida y caché que pertenecían a
www-datadejan de ser escribibles. Ajusta el propietario antes del cambio. - Variables de entorno y autenticación HTTP. Algunas aplicaciones leen las cabeceras de autorización de una manera que cambia en FastCGI. Prueba el inicio de sesión e integraciones de API.
- Timeouts. El
ProxyTimeoutde Apache necesita ser mayor que el tiempo de las tareas largas, como informes e importaciones.
Paso 5: validar y monitorizar
Confirma en el phpinfo() temporal que el Server API se ha convertido en FPM, ejecuta los flujos críticos (inicio de sesión, checkout, subida, cron) y acompaña el slowlog y la página de estado del pool en las primeras 48 horas. Solo considera el cambio de mod_php o PHP-FPM concluido después de ese período sin alertas.
Cuándo no migrar ahora
En la decisión mod_php o PHP-FPM, la respuesta a largo plazo es FPM, pero hay momentos en que hacerlo ahora es un error.
- Cuando PHP aún no ha sido actualizado. Migrar un PHP vulnerable a FPM cambia el escenario de mayor riesgo por uno aún vulnerable. Parche primero.
- Cuando el servidor ejecuta PHP 7.3 o más antiguo. Para las versiones 5.4 a 7.3 no hay corrección del proyecto, y para 7.4 a 8.1 solo existen backports mínimos de código fuente, según Tenable. Aquí el plan es actualizar PHP y la aplicación. La CISA recomienda desconectar sistemas PHP que no pueden ser actualizados o que ejecutan 8.1 o anterior.
- Cuando el servidor es gestionado por un panel. cPanel, Plesk y HestiaCP tienen su propia forma de cambiar el modo PHP por dominio. Modificar Apache manualmente puede ser deshecho en la próxima actualización del panel. Usa la opción del panel.
- En medio de un período crítico. Semana de matrícula, campaña de ventas o examen en el AVA no es momento de cambiar la arquitectura. Actualiza PHP, aplica las mitigaciones oficiales y agenda la migración.
Y un punto sobre las mitigaciones: memory_limit=-1, session.upload_progress.enabled=0 y, en PHP 8.5, fatal_error_backtraces=0 reducen rutas de ataque específicas. PHP dice textualmente que no hacen que la instalación sea segura y que actualizar es la única opción segura. El 23/10 salió un tercer aviso, CVE-2026-115560, relacionado con el upload progress de sesión. El vector es improbable: exige que la aplicación cambie el session.serialize_handler en tiempo de ejecución. La corrección viene en la próxima versión regular, y la recomendación es mantener session.upload_progress.enabled=0 hasta entonces.
Cómo Agathas Web resuelve esto
Administro servidores Linux con PHP desde 2008: Moodle de instituciones educativas, WordPress, Laravel y sistemas que se comunican con la API oficial de WhatsApp. La pregunta mod_php o PHP-FPM, para mí, tiene una respuesta estándar desde hace años: FPM, un pool por aplicación, cada uno con su usuario. PHP2Shell solo dejó claro por qué esto importa.
En el alojamiento gestionado de Agathas Web, lo que está incluido para un escenario como este:
- Actualización del runtime de PHP en ventana combinada, con pruebas en staging antes, como parte de la rutina de parches de sistema operativo, PHP y base de datos.
- Arquitectura revisada: diagnóstico del modo actual (mod_php, FPM, panel), plan de migración a PHP-FPM con pools aislados, dimensionamiento de
pm.max_childrenbasado en el consumo real y plan de reversión. - Capas de protección ya previstas en el servicio: WAF de Cloudflare, fail2ban y hardening del sistema operativo, para reducir la exposición mientras se aplica un parche.
- Monitorización 24/7 con alertas en el WhatsApp del equipo técnico, para detectar señales como ráfagas de error de memoria y procesos de PHP abriendo shell.
- Respuesta a incidentes con plan documentado, y copias de seguridad verificadas con restauración probada.
Cómo funciona: nos das acceso al servidor (o empezamos por una migración a una infraestructura nueva), hacemos el inventario de versiones y modos de PHP, presentamos el plan con ventana y rollback, y ejecutamos con tu aprobación por escrito. La migración del proveedor actual entra en la configuración. Para contratar, habla con el equipo a través de la página de alojamiento gestionado y dinos cuántos sitios y qué aplicaciones se ejecutan en el servidor.
Conclusión: mod_php o PHP-FPM, la respuesta se ha vuelto sencilla
Para un servidor que atiende a internet, la respuesta para mod_php o PHP-FPM es PHP-FPM, con un pool aislado por sitio. El manual de PHP ya desaconsejaba mod_php en instalaciones nuevas por rendimiento y operación, y PHP2Shell añadió el argumento de seguridad: es el escenario que el propio equipo de PHP señala como el de mayor riesgo.
Solo no inviertas el orden. Primero, PHP actualizado a 8.5.12, 8.4.27, 8.3.36, 8.2.35 o el paquete corregido de la distribución, con todos los workers reiniciados. Después, la migración planificada, con pruebas y camino de vuelta. Y recuerda que PHP 8.2 llega al fin de vida el 31/12/2026: si tu servidor está en él, vale la pena casar la migración a FPM con la actualización de versión.
Si no tienes un sysadmin para hacer esto ahora, el alojamiento gestionado de Agathas Web asume el parche, la migración y la monitorización.
Fuentes: aviso de seguridad y archivo de noticias de PHP, manual de PHP sobre Apache, configuración de PHP-FPM, Tenable, Unit 42, Datadog Security Labs, Huntress, watchTowr y Help Net Security.
Posts relacionados

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.

Imagen Docker PHP Vulnerable: Reconstrucción Correcta tras PHP2Shell
<code>docker pull</code> no soluciona PHP2Shell. Aprende a reconstruir imágenes <code>php:8.x</code> y FrankenPHP, y qué ajustar en tu CI/CD para aplicar el parche en producción.

Gestión de Parches de Servidor: La Rutina 24/7 Post-PHP2Shell
Del ataque del 17/10 al parche del 21/10: ¿dónde estaba la ventana de exposición de PHP2Shell y qué parte de ella depende solo de usted?