PHP2Shell (CVE-2026-109618 / CVE-2026-109619): cómo Core-Admin contiene el fallo de PHP mientras llegan los parches


#1

Artículo preliminar (21 de octubre de 2026). Está redactado antes de que el equipo de seguridad de PHP publique los detalles oficiales, previstos para el 21 de octubre de 2026 a las 14:00 UTC. Lo actualizaremos con la causa confirmada, las versiones corregidas y los parches para las ramas antiguas en cuanto estén disponibles.

Introducción

El 20 de octubre de 2026 el equipo de seguridad de PHP anunció una versión de seguridad urgente que corrige dos vulnerabilidades críticas, ambas con una puntuación CVSS v4.0 de 9.2. Los informes publicados las identifican como CVE-2026-109618 y CVE-2026-109619, y las describen como ejecución remota de código sin autenticación en el núcleo de PHP. Se ha filtrado además una herramienta de explotación, conocida como PHP2Shell, que asegura funcionar con todas las versiones desde PHP 5.4.0.

El fallo se dispara mientras PHP procesa la petición, antes de ejecutar el código de la aplicación. Por eso no se puede corregir desde WordPress, PrestaShop ni ninguna otra aplicación: hay que actuar sobre el propio PHP. Y como las ramas 8.1 y anteriores ya no tienen soporte, no recibirán parche oficial.

Mientras se publican y despliegan los parches, Core-Admin aplica automáticamente una mitigación en todo el parque: desactiva y bloquea la función de PHP señalada por los análisis publicados, en todas las versiones de PHP instaladas y en todas las formas en que se sirve PHP a la web (php-fpm, mod_php y php-cgi).

Este artículo explica qué se sabe del fallo, qué hace Core-Admin, qué versiones cubre, qué impacto tiene en las webs y cómo comprobarlo a mano.

Qué se sabe (y qué no)

Confirmado por PHP (anuncio del 20 de octubre):

  • Dos vulnerabilidades críticas, CVSS v4.0 9.2.
  • Versión de seguridad el 21 de octubre de 2026 a las 14:00 UTC.
  • Las versiones afectadas y las corregidas se publicarán con la versión de seguridad.

Según informes de terceros, sin confirmar todavía por PHP:

  • Las dos son ejecución remota de código sin autenticación.
  • Afectan a todas las versiones desde la 5.x (la herramienta filtrada dice “desde 5.4.0”).
  • Solo se parcheará la rama 8; las ramas 5 y 7 no tendrán corrección oficial.
  • No se conocen ataques reales ni una prueba de concepto pública, pero se esperan ataques masivos en cuanto se publiquen los detalles.

Cuidado con las listas de “versiones corregidas” que circulan. Alguna fuente da como corregidas las versiones 8.5.11, 8.4.26, 8.3.35 y 8.2.34. Son las del 24 de septiembre, anteriores al parche: tener esas versiones no protege. Las versiones corregidas son las que publique PHP el 21 de octubre.

Mecanismo sospechado

Dos análisis independientes (Syhunt y J4ck3LSyN) apuntan a un error de memoria (use-after-free) en el seguimiento del progreso de subida de ficheros de la sesión (session.upload_progress), una función de PHP que guarda en $_SESSION cuánto lleva recibido un formulario multipart/form-data mientras se sube.

Hemos contrastado esa hipótesis con el código fuente de PHP 8.4.26:

  • La estructura de datos señalada existe tal como la describen.
  • Con session.upload_progress.enabled = Off, el código afectado termina antes de tocar ningún dato del progreso.
  • La opción viene activa por defecto y es de tipo PHP_INI_PERDIR: un .user.ini o un php_flag en .htaccess pueden volver a activarla, salvo que se bloquee como opción de administrador.

Además, la función apareció precisamente en PHP 5.4.0, la versión a partir de la cual dice funcionar la herramienta filtrada.

Uno de los análisis menciona una posible segunda vía en el procesado general de peticiones multipart que esta opción no cerraría. No está verificado; lo revisaremos con el aviso oficial.

Versiones cubiertas

Versión de PHP ¿Tiene session.upload_progress? ¿Parche oficial? Qué hace Core-Admin
5.2, 5.3 No No (EOL) Nada que mitigar por esta vía. El checker las lista como “no cubiertas” hasta conocer el aviso oficial
5.4 – 7.4 Sí No (EOL) Mitigación aplicada. Parches adaptados en estudio
8.0, 8.1 Sí No (EOL) Mitigación aplicada. Parches adaptados en estudio
8.2 – 8.5 Sí Sí, el 21 de octubre Mitigación aplicada hasta instalar la versión corregida

La mitigación se aplica tanto a los motores PHP de Core-Admin (/usr/core-admin/php/X.Y) como al PHP de la distribución (/etc/php/X.Y, /etc/php5).

Se ha validado en servidores reales con Debian wheezy, jessie, stretch, buster y bullseye y Ubuntu focal, en los dos modos de trabajo de Core-Admin (apache2-mpm-worker-php-fpm y apache2-mpm-itk) y con Apache 2.2 y 2.4.

Cómo lo mitiga Core-Admin

La mitigación forma parte del checker security_and_mitigations, el mismo que ya gestiona CopyFail, Dirty Frag, pedit COW, Januscape y el resto de fallos críticos mientras llegan los parches oficiales. Para PHP2Shell añade cuatro comprobaciones.

1. Desactivar y bloquear la función (php2shell)

a) Fichero de configuración en cada SAPI web. En el conf.d de cada versión de PHP 5.4 o superior se escribe zzz-core-admin-cve-2026-109618.ini:

session.upload_progress.enabled = Off

El prefijo zzz- hace que se cargue después de php.ini y del resto de ficheros de conf.d, así que prevalece sobre ellos. Se escribe solo en los SAPI que reciben peticiones web (fpm, apache2, cgi); la línea de comandos no se toca.

b) Bloqueo según cómo se sirva PHP. Un fichero .ini no basta: un cliente podría volver a activar la opción desde su .user.ini o .htaccess. Por eso se bloquea en cada vía:

Cómo llega PHP a la web Desde dónde podría reactivarse Bloqueo que aplica Core-Admin
php-fpm (pools por alojamiento) .user.ini php_admin_flag[session.upload_progress.enabled] = off en cada pool. Un valor de administrador no se puede cambiar ni con .user.ini ni con ini_set()
mod_php (versión “default” en modo itk) .htaccess (php_flag, php_value) php_admin_flag session.upload_progress.enabled off a nivel de servidor Apache, en /etc/apache2/conf-available/core-admin-cve-2026-109618.conf (Apache 2.4) o /etc/apache2/conf.d/ (Apache 2.2)
php-cgi (otras versiones en modo itk) .user.ini No existe bloqueo de administrador: se neutraliza el .user.ini (ver el punto 2)

c) Recarga segura.

  • php-fpm: antes y después de modificar los pools se ejecuta php-fpm -t. Si la modificación introduce un error, se restauran los pools originales. Solo se recargan los motores que están en marcha.
  • Apache: se ejecuta apache2ctl configtest antes y después. Si el bloqueo rompiera la configuración, se retira automáticamente, para que un reinicio posterior de Apache no falle.
  • Si una recarga falla, el checker lo deja marcado y la reintenta en la siguiente pasada.

d) Verificación desde los binarios web, no desde la línea de comandos. El valor efectivo se comprueba con php-fpm -i y php-cgi -i de cada versión, porque la configuración de la línea de comandos puede ser distinta de la que recibe la web. Para mod_php se comprueban el fichero de conf.d, el bloqueo de Apache y que la recarga haya ido bien.

Las copias de seguridad de los pools modificados quedan en /var/backups/core-admin-php-cve-2026-109618/.

Además, los pools nuevos o regenerados por webhosting_management ya incluyen la línea de bloqueo, así que editar o regenerar un sitio no la elimina.

2. Neutralizar .user.ini con php-cgi (php2shell_overrides)

Solo actúa en servidores en modo apache2-mpm-itk, donde las versiones no “default” se sirven con php-cgi:

  • Cada hora se listan en segundo plano, y a baja prioridad, todos los .user.ini de las webs.
  • Las líneas que activan la opción se comentan, con una marca encima indicando que lo ha hecho Core-Admin. El resto del fichero no se toca.
  • El original se guarda una sola vez en /var/backups/core-admin-php-cve-2026-109618/user-ini/.
  • php-cgi relee .user.ini en un máximo de 5 minutos (user_ini.cache_ttl), así que no hace falta recargar nada.

Como el checker trabaja con permisos de root sobre ficheros de clientes, solo modifica un .user.ini si es un fichero normal, dentro de la carpeta de webs, sin enlaces simbólicos en la ruta, con un único enlace duro y de 64 KB como máximo. Cualquier otro caso se marca como CRITICAL para revisarlo a mano, sin escribir nada.

3. Revisión de los alojamientos (php2shell_dependencies)

Una vez al día, en segundo plano y a baja prioridad, se buscan en las webs los ficheros que mencionan upload_progress, y se clasifican:

  • CRITICAL: un .user.ini o .htaccess que reactiva la opción y que todavía nada bloquea. Es el único caso que deja un hueco real.
  • OK con nota INFO:: el código que usa la función (su barra de progreso dejará de avanzar) y los intentos de reactivarla que ya están neutralizados. Se listan para que soporte lo sepa, sin subir el estado.
  • Ignorados: los ficheros que solo mencionan la opción sin usarla: clases CSS (gfield_fileupload_progress de Gravity Forms), listas de opciones válidas (Symfony NativeSessionStorage) o herramientas de análisis (PHP Compatibility, PHP_CodeSniffer).

Para contar como “uso” real, el código tiene que contener el campo del formulario (PHP_SESSION_UPLOAD_PROGRESS o session.upload_progress.name) o leer la clave de la sesión (session.upload_progress.prefix o el literal upload_progress_).

4. Vigilancia de caídas de PHP (php2shell_crashes)

Un fallo de memoria explotado “a ciegas” suele tumbar procesos de PHP antes de conseguir su objetivo. El checker lee los logs de php-fpm (y el de errores de Apache si hay mod_php) y cuenta, por pool, los procesos que han muerto por SIGSEGV, SIGBUS o SIGABRT en la última hora:

  • 5 o más: WARNING.
  • 50 o más: CRITICAL.

Esta vigilancia funciona aunque la mitigación esté aplicada: también serviría para detectar intentos contra una vía que la mitigación no cubra.

Impacto en las webs

session.upload_progress solo rellena $_SESSION["upload_progress_<nombre>"] mientras llega un formulario multipart. Las subidas siguen funcionando igual; lo único que se pierde es la barra de progreso de las aplicaciones que consultan ese dato. Hoy casi todas calculan el progreso en el navegador (XMLHttpRequest.upload.onprogress), sin pasar por PHP.

Lo hemos comprobado en el código fuente:

Aplicación Versión revisada ¿Usa session.upload_progress? Efecto
WordPress última (octubre 2026) No. El núcleo ni siquiera usa sesiones de PHP Ninguno
PrestaShop 9.3.0 (develop) No Ninguno
Nextcloud 35.0.2 No (sus subidas usan WebDAV) Ninguno

En el despliegue por el parque solo hemos encontrado dos usos reales, y en ambos la subida sigue funcionando:

  • phpMyAdmin antiguo (4.0.x): la barra de progreso de la importación de ficheros .sql.
  • Plugin WPvivid Backup: la barra de progreso al restaurar una copia de seguridad.

¿Siguen protegidas las webs que usan la función? Sí. El fallo ocurre al procesar la petición, antes de que se ejecute el código de la web, y ningún código de la aplicación puede reactivar la opción: un ini_set() llega tarde y además lo impide el bloqueo de administrador. Por eso estos casos se informan como INFO: y no como aviso.

Salida del checker

Primera pasada en un servidor afectado (se aplica la mitigación):

[WARNING] PHP2Shell (CVE-2026-109618 + CVE-2026-109619): vulnerable, mitigation applied and verified
          (session.upload_progress.enabled Off verified on: core-admin PHP 7.4 fpm, core-admin PHP 7.4 cgi, ...,
          distro PHP 7.4 fpm)

El WARNING de la primera pasada es intencionado: indica que Core-Admin ha cambiado la configuración de PHP de los alojamientos.

Pasadas siguientes, ya en estado estable (no se vuelve a escribir nada):

[OK] PHP2Shell (CVE-2026-109618 + CVE-2026-109619): system not vulnerable
     (session upload progress disabled and locked on core-admin PHP 7.4, core-admin PHP 8.3, distro PHP 7.4)
[OK] PHP2Shell .user.ini overrides (CVE-2026-109618 + CVE-2026-109619): system not vulnerable
     (php-fpm working mode: .user.ini cannot override the pool lock)
[OK] PHP2Shell hosting dependencies (CVE-2026-109618 + CVE-2026-109619): system not vulnerable
     (no hosting uses or re-enables session upload progress (scan of /var/webs from ...;
      16 file(s) only mention it, ignored (CSS classes, option lists, compatibility sniffers)))
[OK] PHP2Shell worker crashes (CVE-2026-109618 + CVE-2026-109619): system not vulnerable
     (0 PHP worker crash(es) in the last hour (threshold 5))

En un servidor itk con mod_php aparece además mod_php (.htaccess locked) en la lista de motores bloqueados.

Opciones de exclusión

Cada comprobación tiene su opción en la configuración del checker:

Opción Efecto
skip_php2shell_mitigation No aplica la mitigación; la detección sigue y se informa como OK con un aviso. Solo para servidores que ya tienen la versión corregida de PHP o cuyas webs no pueden funcionar sin el progreso de subida
skip_php2shell_overrides_mitigation No comenta los .user.ini de los clientes (servidores itk)
skip_php2shell_dependencies_alert Silencia el CRITICAL de un override todavía activo, una vez revisado
skip_php2shell_crashes_alert Silencia la vigilancia de caídas en servidores con una causa conocida y ajena (por ejemplo, una extensión defectuosa)

Verificación manual

# 1. El fichero de configuración está en todas las versiones
ls -l /etc/core-admin/php/*/conf.d/zzz-core-admin-cve-2026-109618.ini /etc/php/*/*/conf.d/zzz-core-admin-cve-2026-109618.ini

# 2. Valor efectivo según cada binario web: todas las líneas deben terminar en Off
for b in /usr/core-admin/php/*/sbin/php-fpm /usr/core-admin/php/*/bin/php-cgi /usr/sbin/php-fpm* /usr/bin/php-cgi*; do [ -x "$b" ] && echo "$b: $($b -i 2>/dev/null | grep -oE 'session\.upload_progress\.enabled( => |</td><td class="v">)[^ <]*' | head -1)"; done

# 3. Pools bloqueados: cada directorio debe dar N/N
for d in /etc/core-admin/php/*/php-fpm.d /etc/php/*/fpm/pool.d; do [ -d "$d" ] && echo "$d: $(grep -l '^php_admin_flag\[session.upload_progress.enabled\] = off' $d/*.conf 2>/dev/null | wc -l)/$(ls $d/*.conf 2>/dev/null | wc -l) locked"; done

# 4. Con mod_php: el bloqueo de Apache está cargado
ls -l /etc/apache2/conf-enabled/core-admin-cve-2026-109618.conf /etc/apache2/conf.d/core-admin-cve-2026-109618.conf 2>/dev/null; apache2ctl -t

Un directorio de pools con uno menos (por ejemplo 4/5) suele ser el www.conf de la distribución con la sección [www] comentada: un fichero sin pools activos no necesita bloqueo.

Prueba real por la web

Para confirmar que una web concreta no puede reactivar la opción, crea un directorio temporal en su docroot con un script de prueba y un .user.ini (con php-fpm o php-cgi) o un .htaccess (con mod_php) que intente activarla. Usa un nombre aleatorio y bórralo al terminar. Ejemplo para un alojamiento con php-fpm:

d=<docroot>/zz-test-$RANDOM; mkdir $d && echo '<?php echo (ini_get("session.upload_progress.enabled") ? "ON" : "OFF") . " " . PHP_VERSION . " " . php_sapi_name () . "\n";' > $d/t.php && echo 'session.upload_progress.enabled = On' > $d/.user.ini && chown -R <usuario>:<grupo> $d && wget --no-check-certificate -q -S -O - http://<dominio>/$(basename $d)/t.php 2>&1 | grep -E 'HTTP/|^(ON|OFF)'; rm -rf $d

La respuesta debe ser OFF, seguida de la versión y el SAPI (fpm-fcgi, apache2handler o cgi-fcgi), con HTTP/1.1 200. Con mod_php, cambia el .user.ini por un .htaccess con php_flag session.upload_progress.enabled on. En servidores antiguos, usa wget en lugar de curl: el curl de Debian jessie puede fallar en TLS sin mostrar ningún error con -s.

Aplicar la mitigación a mano (sin Core-Admin)

En un servidor sin el checker, el mínimo equivalente es:

# 1. Desactivarla en cada SAPI web (ajusta las rutas a tus versiones)
for d in /etc/php/*/fpm/conf.d /etc/php/*/apache2/conf.d /etc/php/*/cgi/conf.d; do [ -d "$d" ] && printf 'session.upload_progress.enabled = Off\n' > $d/zzz-cve-2026-109618.ini; done

# 2. Bloquearla en cada pool de php-fpm (añadir al final de cada sección de pool)
#    php_admin_flag[session.upload_progress.enabled] = off

# 3. Con mod_php, bloquearla en Apache (dentro de <IfModule php_module>, php7_module o php5_module)
#    php_admin_flag session.upload_progress.enabled off

# 4. Comprobar y recargar
php-fpm7.4 -t && systemctl reload php7.4-fpm
apache2ctl configtest && systemctl reload apache2

Revertir la mitigación

Cuando el servidor tenga una versión de PHP corregida y quieras recuperar la barra de progreso:

  1. Activa skip_php2shell_mitigation en el checker (si no, volverá a aplicarla).
  2. Borra los ficheros zzz-core-admin-cve-2026-109618.ini de cada conf.d y core-admin-cve-2026-109618.conf de Apache (con su enlace en conf-enabled).
  3. Quita la línea php_admin_flag[session.upload_progress.enabled] = off de los pools, o restaura las copias de /var/backups/core-admin-php-cve-2026-109618/.
  4. Recarga php-fpm y Apache.

Mientras no haya versión corregida para tu rama de PHP, no recomendamos revertirla.

Preguntas frecuentes

P: ¿Las subidas de ficheros dejan de funcionar?

No. Las subidas funcionan exactamente igual. Solo deja de rellenarse el dato de progreso en la sesión, que casi ninguna aplicación actual utiliza.

P: ¿Tengo que hacer algo en mi web?

No. La mitigación se aplica en el servidor y cubre todas las webs, uses la aplicación que uses. No hace falta actualizar plugins ni tocar el código por este fallo, aunque siempre conviene tener la aplicación actualizada.

P: ¿Puede una web volver a activar la opción?

No. Con php-fpm y mod_php la opción está bloqueada como valor de administrador, que no se puede cambiar desde .user.ini, .htaccess ni ini_set(). Con php-cgi, Core-Admin neutraliza automáticamente cualquier .user.ini que intente activarla.

P: ¿Estoy protegido del todo?

Frente a la vía que señalan los análisis publicados, sí. Pero se trata de una mitigación preventiva basada en información todavía no confirmada por PHP. La solución definitiva es instalar la versión corregida de PHP en cuanto se publique, o los parches adaptados para las ramas antiguas. Actualizaremos este artículo con el aviso oficial.

P: Uso PHP 5.6 / 7.x / 8.0 / 8.1. ¿Qué hago?

Tu versión no recibirá parche oficial. Con la mitigación de Core-Admin estás protegido frente a la vía conocida, pero recomendamos planificar la migración a una versión con soporte (8.2 o superior). Estamos estudiando adaptar el parche oficial a las ramas antiguas que mantiene Core-Admin, en cuanto se publique.

P: ¿Se pierde la mitigación si regenero o edito un sitio?

No. Los pools que genera webhosting_management ya incluyen la línea de bloqueo. Y aunque un pool la perdiera por cualquier motivo, el checker la vuelve a añadir en su siguiente pasada.

P: ¿Necesito reiniciar algo?

No. El checker recarga php-fpm y Apache de forma controlada (con comprobación previa de la configuración) y php-cgi recoge el cambio por sí solo.

Pendiente de actualizar con el aviso oficial

  • Causa confirmada de CVE-2026-109618 y CVE-2026-109619, y si la segunda necesita otra mitigación.
  • Versiones corregidas de cada rama de PHP (8.2 – 8.5).
  • Parches adaptados para las ramas antiguas que mantiene Core-Admin.

Referencias