PHP2Shell: comprueba y parchea el RCE de PHP en tu servidor
El 21 de octubre de 2026 el proyecto PHP publicó 8.5.12, 8.4.27, 8.3.36 y 8.2.35 para corregir dos fallos en el propio PHP, apodados PHP2Shell. Ambos permiten que una petición de alguien que no ha iniciado sesión ejecute código como el worker de PHP. El error está en el runtime, no en WordPress, Drupal o Joomla, así que actualizar el CMS o sus plugins no lo cierra. Esta guía explica a quién afecta, cómo comprobar un servidor con un solo comando, qué hacer hoy si todavía no puedes actualizar y cómo actualizar con seguridad.
Qué son los dos fallos
- CVE-2026-109618, corrupción por falta de memoria - cuando falla una reserva de memoria, PHP puede detener una petición mientras sus datos internos están a medio preparar, y la limpieza posterior confía en esos datos rotos. Una petición multipart manipulada puede provocarlo incluso dentro de los límites de tamaño que tengas configurados.
- CVE-2026-109619, estado global obsoleto - el estado que pertenece a una petición puede sobrevivir a la memoria que lo respalda. La siguiente petición que atiende el mismo worker puede usar esa memoria liberada antes de que se reinicie (un use-after-free). La vía confirmada pasa por la función de session upload progress y los errores fatales.
Ambos tienen una puntuación de 9.2 (crítica) en CVSS 4.0. El anuncio de PHP dice que durante la investigación se construyó un exploit funcional y que el riesgo es máximo en Apache con mod_php, donde el ataque se ejecuta antes de cualquier código de la aplicación. En pocos días aparecieron varios exploits públicos de prueba de concepto; Rapid7 informa de que cada uno funciona solo con una combinación concreta de sistema operativo, versión de PHP y servidor web, y ha visto intentos de explotación. Trátalo como un parche de emergencia.
A quién afecta
A toda instalación de PHP que sirva peticiones web: PHP-FPM, Apache con mod_php, php-cgi, FrankenPHP y LiteSpeed. Eso cubre casi todos los servidores con WordPress, WooCommerce, Drupal, Joomla, Magento, Laravel y Nextcloud.
| Rama de PHP | Afectadas | Primera versión corregida |
|---|---|---|
| 8.5 | 8.5.0 - 8.5.11 | 8.5.12 |
| 8.4 | 8.4.0 - 8.4.26 | 8.4.27 |
| 8.3 | 8.3.0 - 8.3.35 | 8.3.36 |
| 8.2 | 8.2.0 - 8.2.34 | 8.2.35 |
| 7.4, 8.0, 8.1 | todas | sin versión en php.net; backports en el código fuente, paquetes de la distribución o de un proveedor LTS |
| 7.3 y anteriores | todas | sin corrección |
Las distribuciones suelen mantener el número de versión antiguo y aplicar la corrección como backport (por ejemplo, un paquete de Debian o Ubuntu que sigue diciendo 8.2.x), así que con PHP empaquetado consulta el paquete en el security tracker de tu distribución, no solo el número.
Comprueba un servidor con un solo comando
Guarda esto como php2shell-check.php y ejecútalo con el mismo PHP que sirve tu sitio. Muestra la versión, si esa versión es anterior a la corrección y los dos ajustes que cambian las medidas provisionales de más abajo.
<?php
// PHP2Shell check: is this PHP build older than the October 21, 2026 fixes?
$fixed = ['8.5' => '8.5.12', '8.4' => '8.4.27', '8.3' => '8.3.36', '8.2' => '8.2.35'];
$branch = PHP_MAJOR_VERSION . '.' . PHP_MINOR_VERSION;
echo "PHP " . PHP_VERSION . " (" . PHP_SAPI . ")\n";
if (!isset($fixed[$branch])) {
echo "Branch $branch gets no php.net release: check your distro or LTS vendor, or upgrade to 8.4.\n";
} elseif (version_compare(PHP_VERSION, $fixed[$branch], '<')) {
echo "VULNERABLE: upgrade to {$fixed[$branch]} or later (or a distro build with the backport).\n";
} else {
echo "Patched upstream version ({$fixed[$branch]}+).\n";
}
echo "session.upload_progress.enabled = " . (ini_get('session.upload_progress.enabled') ? 'On' : 'Off') . "\n";
echo "post_max_size = " . ini_get('post_max_size') . ", memory_limit = " . ini_get('memory_limit') . "\n";
php php2shell-check.php
Salida comprobada el 2026-10-24 en las imágenes Docker oficiales de php:
PHP 8.3.30 (cli)
VULNERABLE: upgrade to 8.3.36 or later (or a distro build with the backport).
session.upload_progress.enabled = On
post_max_size = 8M, memory_limit = 128M
PHP 8.4.27 (cli)
Patched upstream version (8.4.27+).
PHP 7.2.34 (cli)
Branch 7.2 gets no php.net release: check your distro or LTS vendor, or upgrade to 8.4.
El php de la línea de comandos puede ser una compilación distinta de la que hay detrás de tu sitio. Para comprobar la parte web, ejecuta php-fpm -v (o php-fpm8.3 -v en Debian y Ubuntu), o pon el script en la raíz web para una sola petición y bórralo justo después.
Si hoy no puedes actualizar: medidas provisionales
El equipo de PHP deja claro que no hay una mitigación completa y que actualizar es la única opción segura. Estos ajustes reducen el ataque mientras programas la actualización. Defínelos donde la aplicación no pueda sobrescribirlos - en php.ini o en el pool de FPM con php_admin_value -, porque ini_set() y .user.ini se aplican demasiado tarde. Después reinicia todos los workers.
; FPM pool, e.g. /etc/php/8.3/fpm/pool.d/zz-php2shell.conf (the [www] section of your pool)
[www]
php_admin_value[session.upload_progress.enabled] = 0
php_admin_value[post_max_size] = 32M
php_admin_value[upload_max_filesize] = 30M
php-fpm8.3 -t && systemctl restart php8.3-fpm
Comprobamos este archivo de pool con php-fpm -t en PHP 8.4 (configuration test successful). Qué hace cada línea:
session.upload_progress.enabled = 0bloquea la vía confirmada de CVE-2026-109619, no todas las variantes. Desactívalo salvo que una barra de progreso de subida dependa de él.post_max_sizede 8M si no hay subidas, o 32M si el sitio acepta archivos, conupload_max_filesizepor debajo, como recomienda el equipo de PHP. Limita también el tamaño de la petición en nginx (client_max_body_size 32m;) o en Apache (LimitRequestBody).- Solo en PHP 8.5, añade
fatal_error_backtraces = 0. - PHP también sugiere
memory_limit = -1fijado por el administrador, para que el propio límite de memoria no pueda usarse para provocar CVE-2026-109618. Hazlo solo con un límite de memoria de contenedor o cgroup alrededor de PHP, o una sola petición maliciosa puede ocupar toda la RAM del servidor. No usesRLIMIT_ASniRLIMIT_DATApara esto: pueden provocar el fallo.
Ocultar errores (display_errors, error_reporting, @) no ayuda, y un log de errores vacío no demuestra que un servidor no haya sido atacado.
Cómo actualizar
- PHP empaquetado (Debian, Ubuntu, RHEL, AlmaLinux). Instala la actualización de seguridad (
apt update && apt upgrade, odnf upgrade 'php*') y luego reinicia PHP-FPM o Apache, porque los workers en marcha conservan el código antiguo. Confirma que el changelog del paquete menciona CVE-2026-109618. - Imágenes Docker. Reconstruye sobre una etiqueta corregida (
php:8.4-fpmya apunta a 8.4.27) condocker compose build --pully vuelve a crear los contenedores. Un contenedor en ejecución mantiene el PHP antiguo hasta que se sustituye. - PHP 7.4 - 8.1. Usa el paquete con backport de tu proveedor o pasa a 8.4. PHP 7.3 y anteriores nunca recibirán corrección: pon el sitio detrás de una lista de permitidos o una VPN hasta migrarlo.
- Después de actualizar, vuelve a ejecutar el script de comprobación y revisa el log del servidor web en busca de peticiones POST multipart inusuales y caídas de workers de PHP desde el 21 de octubre.
Si necesitas ayuda, la administración gestionada de servidores incluye parches como este, y nuestra guía de servidor cloud para WordPress muestra una configuración de PHP-FPM que mantiene estos ajustes en el pool. Antes de actualizar un sitio en producción, haz un snapshot: copia de seguridad y restauración de una VM explica cómo.
Qué hicimos nosotros
Esa misma semana revisamos cada servicio de DCXV que usa PHP y aplicamos las medidas de esta guía. Los servidores de los clientes los administran sus propietarios: si ejecutas PHP en un servidor cloud o dedicado de DCXV, haz hoy la comprobación de arriba. Un servidor cloud nuevo recibe los paquetes actuales en su primer apt upgrade.
Fuentes (consultadas el 2026-10-24): el anuncio de las versiones de seguridad de PHP 8.x del 21 de octubre de 2026, los avisos de PHP GHSA-w8hw-w9fx-j79w y GHSA-6wmf-4rv5-p3rp y el análisis de Rapid7.
