Cada vez que aparece un nuevo CVE en el ecosistema de PHP, los titulares sensacionalistas gritan de inmediato sobre "tomas de control totales del servidor sin autenticación". Cuando el PHP Group publicó CVE-2026-115560 (CVSS 6.4) (GHSA-4966-6377-397r), los rumores lo confundieron rápidamente con fallos de los wrappers HTTP.
Como ingenieros de backend, nuestro trabajo no es entrar en pánico por los titulares, sino leer el aviso de seguridad original y entender la ruta de ejecución exacta. Vamos a desmenuzar qué es realmente CVE-2026-115560, por qué ocurre, qué aplicaciones están realmente afectadas y cómo neutralizarlo con una sola línea en php.ini.
1. El mecanismo central: cómo serializa PHP las sesiones
PHP admite varios formatos internos (session.serialize_handler) para codificar la superglobal $_SESSION antes de escribirla en disco o en Redis:
php(predeterminado): Formatea las entradas comokey|serialized_value(usando el carácter pipe|como delimitador).php_serialize(introducido en PHP 5.5.4): Formatea todo el array de sesión con elserialize()estándar, sin delimitadores pipe especiales.
Mientras una aplicación use exactamente el mismo serializador al escribir y al leer una sesión, todo es seguro. El peligro surge cuando los datos se escriben con php_serialize (que permite caracteres | sin escapar dentro de las cadenas) y luego se leen con el handler php (que trata todo lo que hay después de | como un objeto PHP serializado).
2. Dónde entra en juego session.upload_progress
Cuando session.upload_progress.enabled = 1 está activo en php.ini, PHP inspecciona las subidas de archivos multipart ANTES de que el código de tu aplicación (index.php) empiece a ejecutarse. Si la subida contiene un campo PHP_SESSION_UPLOAD_PROGRESS, el motor de PHP inicializa automáticamente la sesión durante la fase de arranque de la solicitud, usando el serializador predeterminado definido en php.ini.
El fallo de CVE-2026-115560
¿Qué pasa si tu código PHP cambia después el handler en tiempo de ejecución con lo siguiente?
// Changing the serializer dynamically at runtime before session_start()
ini_set('session.serialize_handler', 'php_serialize');
session_start();Como el rastreador de progreso de subida ya inicializó las estructuras de sesión esperando un handler distinto, se produce un desajuste de serializador entre el payload del progreso de subida y el decodificador de sesión en tiempo de ejecución.
Un atacante puede enviar una subida multipart con un payload que empiece con un carácter pipe (|O:8:"Exploit":...). Cuando el handler desajustado deserializa el archivo de sesión, se desencadena una PHP Object Injection (deserialización de datos no confiables).
Información: ¿Por qué puntúa CVSS 6.4 y no 9.8?
A diferencia de los fallos de RCE universales, CVE-2026-115560 requiere dos condiciones previas concretas: session.upload_progress.enabled debe estar activado Y la aplicación debe sobrescribir dinámicamente session.serialize_handler en tiempo de ejecución mediante ini_set(). Las aplicaciones estándar de Laravel o Symfony que configuran las sesiones de forma estática no están expuestas al desajuste en tiempo de ejecución.
3. Mitigación inmediata y versiones de PHP parcheadas
Paso 1: actualiza PHP
El equipo de PHP corrigió este desajuste del ciclo de vida en las versiones de seguridad oficiales de octubre de 2026:
- PHP 8.3.x ➔ Actualiza a la versión parcheada
- PHP 8.4.x / 8.5.x ➔ Actualiza a la versión parcheada
Paso 2: desactiva session.upload_progress en php.ini
Las aplicaciones web modernas siguen el progreso de subida de archivos en el cliente con JavaScript (XMLHttpRequest.upload.onprogress o streams de Fetch), lo que hace que el seguimiento heredado del progreso de subida en sesiones del lado del servidor de PHP sea totalmente redundante, además de una superficie de ataque recurrente.
Abre el php.ini de producción y desactívalo de forma permanente:
; Disable legacy server-side upload progress session injection
session.upload_progress.enabled = 0Reinicia php-fpm (systemctl reload php8.3-fpm) y todo el vector de ataque quedará cerrado de forma permanente.
Hoja de ruta y herramienta interactivas
Desarrollador Backend Junior 2026
Lo que realmente necesitas saber para conseguir un puesto backend junior en 2026 y lo que puede esperar, filtrando las trampas de palabras de moda de las ofertas reales.
¿SQL o NoSQL?
Responde seis preguntas y te diré qué tipo de base de datos encaja con tu proyecto, y por qué.
Sigue leyendo
- CZESCortando el ruido: ¿qué lenguaje y framework de backend deberías elegir en 2026?
Cortando el ruido: ¿qué lenguaje y framework de backend deberías elegir en 2026?
25 de octubre de 2026 · 4 min de lectura - CZES¿Qué es una vulnerabilidad IDOR? Autenticación vs. autorización y cómo prevenir BOLA
¿Qué es una vulnerabilidad IDOR? Autenticación vs. autorización y cómo prevenir BOLA
24 de octubre de 2026 · 3 min de lectura