← Blog

PHP2Shell y Node.js: el 21 de octubre tocó parchear los dos, y así se hace sin romper nada

PHP ha publicado 8.5.12, 8.4.27, 8.3.36 y 8.2.35 para cerrar dos fallos críticos que permiten ejecutar código sin autenticarse, y el mismo día Node.js sacó 26.12.1, 24.22.1 y 22.23.4 con un fallo en el descompresor Brotli que también permite ejecutar código. Qué se sabe, a quién afecta y qué tienes que hacer hoy.

Un miércoles para olvidar

El 21 de octubre de 2026 coincidieron dos de las plataformas que más webs mueven: PHP publicó una release de seguridad de urgencia y, unas horas después, Node.js sacó la suya. En redes ya se hablaba de "día de pesadilla" para quien lleva servidores, y no era exagerado: el mismo día salieron también avisos de LiteLLM, Next.js y varios productos empresariales.

Aquí nos centramos en lo que toca a casi todo el mundo que tiene una web o una API: PHP y Node.js. Vamos al grano.

Actualizado el 22 de octubre. Circula que "se han saltado el parche". Lo hemos comprobado y lo explicamos más abajo, en el apartado Actualización del 22 de octubre: lo que se han saltado son las medidas temporales y algunas reglas de cortafuegos, no el parche oficial.

En una frase

  • PHP: dos fallos críticos (CVE-2026-109618 y CVE-2026-109619, CVSS v4.0 9.2 cada uno) permiten a un atacante ejecutar código en el servidor sin autenticarse. Hay que pasar a 8.5.12, 8.4.27, 8.3.36 u 8.2.35 y reiniciar los procesos de PHP.
  • Node.js: diez fallos, cuatro de gravedad alta. El peor (CVE-2026-111497) es una escritura fuera de límites en el descompresor Brotli que permite ejecutar código. Hay que pasar a 26.12.1, 24.22.1 o 22.23.4.

PHP: qué ha pasado

La historia tiene su miga. Los detalles de los fallos se filtraron el 20 de octubre, antes de que hubiera parche, y circularon con el nombre de "php2shell". Ese mismo día el equipo de PHP confirmó dos vulnerabilidades críticas y anunció la release para el 21 a las 14:00 UTC (las 16:00 en España).

Según el aviso oficial de php.net:

  • CVE-2026-109618 — ejecución de código por corrupción tras quedarse sin memoria. Si PHP se queda sin memoria a mitad de preparar una petición, puede interrumpirse con datos internos a medio inicializar, y la limpieza posterior los trata como válidos.
  • CVE-2026-109619 — ejecución de código por estado global "caducado". Datos internos que pertenecen a una petición pueden sobrevivir después de liberarse su memoria. La siguiente petición que atiende el mismo proceso puede usarlos antes de que se reinicien.

A quién afecta

PHP lo dice sin rodeos: todas las instalaciones de PHP que sirven peticiones web, incluidas PHP-FPM, Apache con mod_php, php-cgi, FrankenPHP y LiteSpeed. Considera que el riesgo es mayor con mod_php, donde hay un exploit demostrado en el que una petición sin autenticar desencadena el ataque antes de que se ejecute una sola línea de tu aplicación.

Eso último es importante: da igual lo bien hecha que esté tu web, tu WordPress o tu framework. El fallo está en PHP, no en tu código.

¿Y las versiones antiguas? PHP 8.1 y anteriores ya no reciben actualizaciones del proyecto. El aviso de php.net no detalla las ramas afectadas, pero Cloudflare, que participó en la respuesta coordinada, habla de todos los servidores con PHP 5.4 o posterior. El equipo de seguridad sí ha publicado parches mínimos para 7.4, 8.0 y 8.1 para quien compile desde el código fuente, y algunas distribuciones y proveedores de soporte extendido los portan a sus paquetes. Si tu servidor va con un PHP fuera de soporte, asume que te afecta mientras no demuestres lo contrario.

¿Se está explotando?

Aquí hay que ser precisos, porque circula mucho titular:

  • Hadrian informa de explotación a gran escala desde la mañana del 21, antes incluso del parche, sobre todo a través de la función de progreso de subida de sesiones (session.upload_progress).
  • watchTowr dice haber visto intentos de explotación de los dos fallos en su red de señuelos.
  • CISA, en su alerta, decía no haber observado explotación en el momento de publicarla, y los dos CVE no estaban en su catálogo de vulnerabilidades explotadas (KEV) a última hora del 21.

Traducción: hay intentos reales y la ventana entre "sale el parche" y "lo usan contra ti" se mide en horas. No esperes a la confirmación oficial para parchear.

PHP: qué tienes que hacer hoy

1. Mira qué versión corre de verdad

php -v
php-fpm8.3 -v   # o la versión que tengas instalada

Ojo: php -v te dice la versión de la línea de comandos, que no tiene por qué ser la que sirve tu web. Si tienes PHP-FPM o mod_php, compruébalo también ahí (una página con phpinfo() temporal, que borras al momento, o el propio binario de FPM).

En Docker:

docker exec <contenedor> php -v

2. Actualiza

  • Debian / Ubuntu con los paquetes de la distribución: sudo apt update && sudo apt upgrade. Las distribuciones suelen portar el parche a su propia versión sin cambiar el número grande, así que no busques "8.3.36" en php -v: busca el aviso de seguridad de tu distribución (Debian Security Tracker, Ubuntu Security Notices) y confirma que el paquete instalado es el corregido.
  • Repositorios de terceros (Ondřej Surý, Remi…): actualiza igual y comprueba que llegas a la versión parcheada.
  • Docker con etiqueta flotante (php:8.4-fpm, php:8.3-apache…): las imágenes oficiales ya están actualizadas. Hay que reconstruir bajando la imagen nueva:
    docker compose build --pull
    docker compose up -d
    
  • Docker con versión fija (php:8.4.14-apache, por ejemplo): reconstruir no sirve de nada. Hay que cambiar el Dockerfile a la versión parcheada de esa rama.
  • No te olvides del phpMyAdmin y similares: también llevan PHP dentro. Si va en contenedor, baja la imagen nueva y recrea el contenedor (y, de paso, pregúntate si tiene que estar abierto a internet).

3. Reinicia los procesos de PHP

Esto no es opcional. Uno de los dos fallos vive precisamente en el estado que sobrevive entre peticiones dentro del mismo proceso. Hasta que no reinicias PHP-FPM o Apache, los procesos viejos siguen ahí.

sudo systemctl restart php8.3-fpm   # tu versión
sudo systemctl restart apache2      # si usas mod_php

Y después, vuelve a comprobar la versión. Lo que no se comprueba no está hecho.

4. Si hoy no puedes actualizar

PHP publica medidas temporales que no sustituyen al parche:

  • Para CVE-2026-109619: session.upload_progress.enabled = 0 y reiniciar los procesos. Es además la vía que más se está usando en los ataques. En PHP 8.5, también fatal_error_backtraces = 0. Ojo: el propio PHP aclara que lo primero bloquea las vías de ataque confirmadas, pero no otras variantes, y lo segundo solo la vía confirmada.
  • Para CVE-2026-109618: ajustes de límites de memoria y de tamaño de las peticiones que detalla el propio aviso. Varios investigadores advierten de que esta parte nunca fue un arreglo completo, así que no te quedes ahí.

PHP lo resume así: no hay mitigaciones completas, actualizar es la única opción segura.

5. Si tu web pasa por Cloudflare, ya tienes un escudo (con condiciones)

Cloudflare se adelantó: desde las 03:02 UTC del 21 de octubre, unas nueve horas antes de la divulgación pública, protege por defecto contra php2shell a todos los clientes con su cortafuegos web (WAF), incluido el plan gratuito. En el plan Free las reglas están en el Cloudflare Managed Free Ruleset con el nombre "Generic Rules - Anomalous Execution" y no hay que activar nada; en los planes de pago van en el Cloudflare Managed Ruleset.

Lo interesante es cómo lo hacen. Mirar solo la petición no bastaba para distinguir un ataque de tráfico legítimo, así que han estrenado una función nueva que analiza la petición y la respuesta de tu servidor juntas, y puede bloquear la respuesta antes de que llegue al atacante. Además cuentan que los atacantes iban modificando el ataque para esquivar las reglas y que ellos las han ido ajustando sobre la marcha.

Ahora, las condiciones, que son las que hacen que esto sirva o no:

  • El dominio tiene que ir con la nube naranja (tráfico pasando por Cloudflare). Si el registro DNS está en gris, Cloudflare no ve nada.
  • Tu servidor no debe aceptar conexiones directas a su IP. Si alguien conoce la IP real y ataca directamente, se salta Cloudflare entero. Lo suyo es que el cortafuegos del servidor solo deje entrar el tráfico de los rangos de Cloudflare.
  • No sustituye al parche. El propio Cloudflare lo dice: es una capa más mientras actualizas, no la solución.

Y vigila si algún proceso de PHP (php-fpm, apache2, httpd) lanza una shell o herramientas de descarga como curl o wget. Si pasa, trátalo como un servidor comprometido: aíslalo, guarda los registros y busca webshells, tareas cron nuevas y usuarios nuevos.

Actualización del 22 de octubre: ¿se han saltado el parche?

Desde ayer corre por redes que el parche de PHP "ya se lo han saltado". Lo hemos comprobado y, a día de hoy, no hay ninguna prueba de eso. Ni php.net ni los equipos que siguen el caso de cerca (watchTowr, el NCSC de Países Bajos, los blogs en directo de varias empresas de seguridad) han publicado un fallo en el parche, y php.net no ha sacado ninguna versión nueva: las últimas siguen siendo 8.5.12, 8.4.27, 8.3.36 y 8.2.35.

Lo que sí se han saltado, y de ahí viene seguramente la confusión, son tres cosas que no son el parche:

  • Las medidas temporales. Antes de que saliera el parche, mucha gente desactivó session.upload_progress y lo dio por resuelto. PHP rectificó: eso cierra las vías de ataque que se conocían, no las variantes. Quien se quedó solo con ese ajuste sigue expuesto.
  • Algunas reglas de cortafuegos. Los atacantes han ido retocando las peticiones para esquivar las reglas de los WAF. Por ejemplo, una revisión anterior de algunas reglas comprobaba el tamaño de la petición mirando una cabecera, y se la saltaban enviando la petición troceada, sin esa cabecera. Los proveedores van ajustando las reglas, pero un cortafuegos es una capa más, no el arreglo.
  • Los exploits públicos. Han aparecido más de cien repositorios en GitHub con pruebas de concepto, entre ellas una variante que esquiva una de las protecciones de memoria del sistema (ASLR). Eso hace el ataque más fácil contra un PHP sin parchear. Contra un PHP actualizado, no hay nada publicado que funcione.

Por qué hay servidores "actualizados" que siguen siendo vulnerables

Esto sí está pasando, y es lo que puede hacer creer que el parche no sirve:

  • No se ha reiniciado PHP. Se instala el paquete nuevo pero PHP-FPM o Apache siguen con los procesos viejos en memoria. Uno de los dos fallos vive justo ahí.
  • La distribución todavía no tenía el paquete corregido cuando se actualizó, o lo tiene con un número de versión que no "parece" el nuevo. Comprueba el aviso de seguridad de tu distribución y busca los CVE en el registro de cambios del paquete, no el número de php -v.
  • La imagen de Docker se reconstruyó demasiado pronto, antes de que la etiqueta apuntase a la versión corregida. Vuelve a hacer docker compose build --pull y comprueba la versión dentro del contenedor.
  • El PHP está fuera de soporte. PHP 8.1 y anteriores no tienen versión oficial: solo parches mínimos para compilar a mano en 7.4, 8.0 y 8.1, y nada para PHP 5.
  • El PHP viene dentro de otro producto: un panel, un appliance, una imagen de un tercero. Ese PHP no lo actualiza tu apt upgrade; depende de que el fabricante saque su versión.

Una ayuda para hacer inventario: el repositorio del NCSC de Países Bajos

El Centro Nacional de Ciberseguridad de Países Bajos (NCSC-NL) ha publicado en GitHub un repositorio gratuito, NCSC-NL/php2shell, con información operativa sobre los dos fallos. Lo más útil:

  • Material de detección y mitigación, para saber si te están atacando y qué aplicar mientras actualizas.
  • Listas de programas y productos que llevan PHP dentro. Es justo lo que hace falta para el último punto de arriba: saber si algo que usas trae su propio PHP y hay que esperar (o reclamar) la actualización del fabricante.
  • Sus recomendaciones coinciden con las nuestras: empezar por lo que está expuesto a internet, actualizar o aplicar el parche de la distribución, revisar aparte el PHP que va dentro de imágenes y appliances, y vigilar los registros.

El propio NCSC avisa de que el repositorio no está completo y lo van ampliando, así que merece la pena volver a mirarlo en los próximos días.

Node.js: qué ha pasado

El mismo día, el proyecto Node.js publicó parches para las tres ramas con soporte: 26.x, 24.x y 22.x. Corrigen diez vulnerabilidades: cuatro altas, tres medias y tres bajas. Las altas:

  • CVE-2026-111497: escritura fuera de límites en el descompresor Brotli que permite ejecutar código. Afecta a las tres ramas.
  • CVE-2026-105483 y CVE-2026-106069: dos formas de saltarse la comprobación del nombre en un certificado TLS (la primera, solo en 26.x y 24.x).
  • CVE-2026-105482: dns.resolve corta los nombres que contienen un carácter nulo.

La release también actualiza dependencias con fallos públicos (c-ares, OpenSSL, SQLite, Undici) y retira la confianza en un certificado intermedio de eMudhra tras el compromiso de esa autoridad de certificación.

A quién afecta de verdad lo de Brotli

El riesgo serio aparece cuando tu aplicación descomprime Brotli que viene de fuera: llamadas a zlib.brotliDecompress, cuerpos de petición comprimidos que acepte tu servidor o respuestas que recibes con fetch de servidores ajenos. Un Node que no recibe nada de internet y solo habla con servicios tuyos tiene un riesgo mucho menor. Menor no es cero: actualiza igual.

Un detalle que mucha gente pasa por alto: tener nginx delante no te protege. Nginx reenvía la petición y Node la recibe igual.

Las ramas sin soporte no reciben parche

Node.js lo recuerda en cada aviso: las versiones fuera de soporte están siempre afectadas cuando sale una release de seguridad. Si sigues en Node 18 o 20, no hay parche que poner: hay que subir de rama.

Node.js: qué tienes que hacer hoy

1. Mira qué versión corre

node -v
pm2 jlist | grep -o '"node_version":"[^"]*"' | sort -u   # si usas PM2
docker exec <contenedor> node -v                          # si va en Docker

2. Actualiza a la versión corregida de tu rama

  • 26.x → 26.12.1
  • 24.x → 24.22.1
  • 22.x → 22.23.4

Con nvm, nvm install 22.23.4 (o tu rama) y reinicia la aplicación. Con los paquetes de NodeSource, sudo apt update && sudo apt upgrade nodejs. En Docker, igual que con PHP: si la etiqueta es flotante (node:22-bookworm-slim), docker compose build --pull y up -d; si es fija, cambia el Dockerfile.

3. Reinicia y comprueba

Node no se actualiza en caliente: el proceso que está corriendo sigue siendo el viejo hasta que lo reinicias (pm2 restart, systemctl restart o recrear el contenedor). Después, node -v dentro del mismo entorno en el que corre la aplicación.

Cómo lo enfocamos nosotros

Un día así se gana o se pierde antes de que salga el parche. Lo que más tiempo ahorra es tener inventario: saber qué servidores tienen PHP o Node, con qué versión exacta, si va en Docker con etiqueta flotante o fija, y si es mod_php o PHP-FPM. Con eso delante, "¿me afecta?" se contesta en minutos, y el parche se convierte en una lista de tareas en vez de una tarde de SSH a ciegas.

La otra lección es la de siempre: los PHP fuera de soporte. Un 7.2 o un 7.4 que "funciona bien" no recibe el parche oficial. Hoy es php2shell; mañana será otro. Si tienes uno de esos, el día de planificar la migración era ayer.

Si no sabes qué versión de PHP o de Node corre en tus servidores, o tienes alguno que ya no tiene soporte y no sabes por dónde empezar, hablamos.

Referencias

¿Hablamos de tu caso?

Cuéntanos qué necesitas y te respondemos en menos de 24 horas con una propuesta clara.

Pedir presupuesto