[INCIDENCIA MAYOR] PHP2Shell, Node.js y Java: lo que no cuentan los titulares y cómo verificar el parche

Carlos Frias

Carlos Frias

1
Ro
Verificación en dos pasos activada
Verificado por Binance
Suscripción a IA
portada.webp

Una semana, tres frentes de seguridad
PHP2Shell · Node.js · Java
Diagnóstico, mitigación y verificación · Corte: 25 de octubre de 2026​

Pasé dos jornadas interviniendo servidores de mi empresa y de clientes por PHP2Shell; se sumaron los avisos de Node.js y Java. Encontré un problema repetido: instalar una actualización y dar por cerrado un servicio sin comprobar qué sigue ejecutándose.

Esta guía cubre hosting compartido, VPS, paneles, contenedores y aplicaciones Java: diagnóstico, mitigaciones, reparación y evidencia para informar al cliente.

Por qué lo trato como incidencia mayor: coinciden fallos graves en runtimes muy utilizados. Es una prioridad operativa; no implica un exploit compartido, idéntica gravedad ni compromiso de cualquier servidor.

Lectura: hosting compartido, apartado 8; administradores, inventario y frente correspondiente. Identifica servicio, cuenta y runtime antes de actuar. No pruebes exploits en producción.

1. El mapa de lo ocurrido

FrenteQué revisarObjetivo
PHP2ShellPHP de cada webParche y workers renovados
Node.jsRuntime y decodificaciónVersión corregida en cada aplicación
JavaJDK/JRE y confianza TLSBuild y truststore efectivos

El 20 de octubre Oracle publicó su actualización trimestral. El 21 llegaron las correcciones principales de PHP y Node.js, y otra alerta de Oracle sobre certificados. El 23 PHP añadió un aviso específico de sesiones. El 24 Oracle publicó otra alerta de certificados. Esa secuencia importa: una revisión hecha el día 21 puede necesitar comprobaciones adicionales el día 25.

2. Lo que no te cuentan los titulares

Paquete nuevo no equivale a proceso renovado. Vi ejecutables actualizados con procesos anteriores en memoria. Comprueba rutas y arranque después de renovar los afectados.

La consola puede mostrar otro runtime. Cruza dominio o servicio → proceso → ejecutable → paquete o imagen → revisión corregida. Incluye instalaciones privadas, por usuario y contenedores.

Un backport puede conservar el número base. En CloudLinux y otras distribuciones, contrasta la revisión y el aviso del fabricante; PHP_VERSION por sí solo no demuestra corrección ni vulnerabilidad.

El WAF filtra determinadas peticiones. No acredita el parche, no garantiza cubrir todas las vías y no elimina persistencia previa.

«No encontré indicios» tiene alcance. Documenta fechas, registros y sistemas revisados; no equivale a demostrar que nunca pasó nada.

3. Primero: saber qué ejecutas

Conserva una foto de sitios y servicios, configuración, respaldos y recuperación viable. Anota la hora. Si hay indicios de intrusión, preserva registros y archivos antes de modificarlos.

En Linux, un primer inventario de procesos sin volcar argumentos completos:

Bash:
ps -eo pid,user,lstart,comm
ss -lntp

Luego identifica el PID que realmente atiende el servicio. Este bloque pide uno, valida que sea numérico y solo consulta:

Bash:
read -r -p 'PID del proceso que vas a revisar: ' runtime_pid
case "$runtime_pid" in
  ''|*[!0-9]*) printf '%s\n' 'PID inválido'; exit 1 ;;
esac
readlink "/proc/$runtime_pid/exe"
ps -p "$runtime_pid" -o pid,user,lstart,comm

«(deleted)» tras actualizar puede señalar un ejecutable anterior todavía en uso; su ausencia no certifica el parche. Revisa bibliotecas y resuelve las rutas en el namespace real del proceso.

No publiques salidas con datos de clientes o infraestructura privada.

4. PHP2Shell: parche y configuración

CVE-2026-109618 y CVE-2026-109619 afectan al manejo de memoria y estado de peticiones. Correcciones iniciales: 8.2.35, 8.3.36, 8.4.27 y 8.5.12. Contrasta los backports del proveedor; para ramas antiguas exige cobertura explícita o migra a una rama con soporte. [1][2][3]

Comprueba el PHP de cada dominio, no solo «php -v». Un diagnóstico mínimo, colocado únicamente en un acceso privado y restringido de la aplicación, puede mostrar el contexto de una petición:

PHP:
<?php
header('Content-Type: application/json; charset=utf-8');
echo json_encode([
    'version' => PHP_VERSION,
    'sapi' => PHP_SAPI,
    'binario' => PHP_BINARY,
    'ini' => php_ini_loaded_file(),
    'pid' => getmypid(),
], JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES);

No muestra automáticamente la revisión RPM ni acredita todos los workers. Evita exposición al acabar y verifica cada nodo, pool y réplica.

Como ejemplo para FPM de EasyApache, PHP 8.3, el administrador puede identificar el paquete del ejecutable y consultar su historial:

Bash:
rpm -qf /opt/cpanel/ea-php83/root/usr/sbin/php-fpm
rpm -q --changelog ea-php83-php-fpm | grep -E 'CVE-2026-(109618|109619)'

Adapta binario y paquete a LiteSpeed, alt-php o tu distribución. Un grep sin coincidencias exige contrastar revisión y aviso; no da un veredicto. Con panel, utiliza primero sus mecanismos oficiales.

Si todavía no puedes parchear: las medidas del advisory reducen vías concretas; no hay un bloque de configuración que sustituya la corrección completa. En php.ini, aplicado antes de procesar peticiones:

INI:
session.upload_progress.enabled = Off

; Solo para PHP 8.5
fatal_error_backtraces = Off

En un pool FPM la sintaxis administrativa es distinta:

INI:
php_admin_flag[session.upload_progress.enabled] = off

; Solo para pools de PHP 8.5
php_admin_flag[fatal_error_backtraces] = off

No confíes en .user.ini ni ini_set() para un camino anterior al script. Conserva la configuración, valida con el FPM correcto, reinicia los workers y verifica. Desactivar progreso de subida puede afectar a quien lo utilice. [2][3][4]

memory_limit = -1 es temporal. Elimina el límite controlable de PHP, no todos los fallos de asignación; puede agotar recursos. RLIMIT_AS/DATA pueden provocar la ruta vulnerable y no sirven como sustitutos. Con cgroups comprueba qué mataría un OOM: agrupar master y workers puede tumbar el servicio. No asumas que «LVE/cgroups» basta. [2]

Limita entradas en el frontend según el advisory y la aplicación. Bloquear multipart rompe las subidas que lo necesiten; no sustituye actualizar.

Aviso del 23: mantener desactivado el progreso de subida cubre otro escenario, CVE-2026-115560: cambiar el serializador php_binary/php_serialize a php durante la ejecución antes de session_start(), con esa función activa. Consulta condiciones y próxima corrección. [1]

5. Node.js: no basta con npm update

Releases corregidas: 22.23.4, 24.22.1 y 26.12.1, según rama. Valida compatibilidad; no saltes de rama mayor a ciegas. Si está fuera de soporte, planifica migración y cobertura. [5]

CVE-2026-111497, HIGH: Brotli malformado que la aplicación descomprime con node:zlib puede corromper memoria, con posible caída, filtración o ejecución de código. Revisa entradas y respuestas externas que alcancen ese decodificador. No implica RCE automático en todo Node expuesto. [5]

CVE-2026-ÁreaRamas
105482DNS y NUL22/24/26
105483Validación TLS24/26
106069IP no canónica y TLS22/24/26
106072SAN DNS frente a IP22/24/26
105481Respuesta HTTP y keep-alive22/24/26
106074Entropía en snapshots/SEA22/24/26
106070Validación ZIP26
106071Permisos y comodines26
106073Permisos y realpathSync22/24/26
Consulta condiciones y gravedad individual en el aviso: los diez problemas no afectan igual a todas las ramas ni a todas las aplicaciones. Las releases también actualizan dependencias y certificados. [5]

Para identificar el Node que invoca tu consola:

Bash:
node -p 'JSON.stringify({version:process.version,exe:process.execPath,openssl:process.versions.openssl},null,2)'

La consulta anterior no interroga tu aplicación viva: crúzala con PID, usuario, servicio e intérprete. npm update no sustituye Node. nvm puede dejar rutas antiguas fijadas; con PM2 revisa y renueva la aplicación concreta, no todos los clientes.

Reparación: respalda y prueba compatibilidad; instala la release corregida por el canal oficial; actualiza la ruta persistente, reconstruye y renueva procesos; comprueba runtime y funcionamiento. Reconstruye también snapshots y ejecutables SEA: actualizar el host no modifica esos artefactos.

Mientras actualizas: evita que Brotli no confiable alcance el decodificador vulnerable, incluidas respuestas externas. Desactivar compresión de salida en nginx no desactiva la descompresión dentro de Node. Tamaños máximos y WAF no parchean corrupción de memoria. No desactives validación TLS para arreglar conexiones.

6. Docker: el host no es el contenedor

Un inventario inicial, con permisos del entorno:

Bash:
docker ps --format '{{.Names}}\t{{.Image}}\t{{.Ports}}'
read -r -p 'Nombre del contenedor Node que vas a consultar: ' runtime_container
docker exec "$runtime_container" node -p 'process.version + " | " + process.execPath'
docker inspect --format '{{.Id}} {{.Image}}' "$runtime_container"

docker exec crea otro proceso: muestra el runtime disponible, no el que sigue cargado en la aplicación antigua. Comprueba también el proceso principal.

Corrige la imagen y el despliegue: actualiza la base o imagen del fabricante, reconstruye si es propia y recrea el servicio. docker cp puede perderse al recrearlo; reiniciar conserva la imagen anterior.

Con Compose, después de fijar y revisar la imagen corregida en el archivo del proyecto, un ejemplo delimitado a un servicio es:

Bash:
read -r -p 'Servicio Compose que vas a actualizar: ' runtime_service
docker compose pull "$runtime_service"
docker compose up -d --no-deps "$runtime_service"

Comprueba cada paso antes de continuar. El ejemplo utiliza imagen publicada; una propia requiere reconstrucción. Revisa volúmenes, compatibilidad, secretos y recuperación. En Swarm/Kubernetes revisa todas las réplicas con su despliegue declarativo. No purgues imágenes ni volúmenes. [6]

7. Java: build, JVM y confianza TLS

Aquí hay que distinguir tres publicaciones. El CPU de Oracle del 20 de octubre incorpora 55 parches de Java SE; su matriz señala 49 vulnerabilidades potencialmente explotables por red sin autenticación, bajo sus respectivas condiciones. No son 49 RCE universales contra cualquier Spring o Tomcat. [7]

El 21 Oracle publicó CVE-2026-91403 para retirar confianza de intermediarios relacionados con eMudhra. El 24 publicó CVE-2026-114820 para retirar determinadas raíces de confianza. Son alertas de JSSE/TLS, con impacto en confidencialidad e integridad; no las describiría como una webshell remota en cada JVM. [8][9]

La trampa del número corto: 21.0.13 fue parte del CPU, pero después hubo revisiones adicionales. Para Oracle JDK, la baseline publicada el 24 es:

FamiliaBuild Oracle del 24/10
81.8.0_511-b33
1111.0.33.0.3+1
1717.0.21.0.3+1
2121.0.13.0.3+1
2525.0.5.0.3+1

Estas builds son de Oracle: Temurin, Corretto, Zulu y distribuciones tienen revisiones y plazos propios. Contrasta proveedor y plataforma; para GraalVM u otra familia, su matriz. Valida compatibilidad y licencia. [10]

Desde la consola:

Bash:
java -version
read -r -p 'PID de la JVM de la aplicación: ' runtime_java_pid
jcmd "$runtime_java_pid" VM.version
jcmd "$runtime_java_pid" VM.system_properties | grep -E '^(java.home|javax.net.ssl.trustStore|javax.net.ssl.trustStoreType)='

jcmd requiere el contexto y permisos adecuados, normalmente el mismo usuario efectivo y JDK compatible; resuelve namespaces en contenedores. Un attach fallido no es evidencia de seguridad. No publiques todas las propiedades. [11]

Verifica el truststore efectivo. Puede ser cacerts, uno privado mediante javax.net.ssl.trustStore o una configuración de la biblioteca. Actualizar el JDK no cambia necesariamente una copia privada. Que la propiedad no aparezca no prueba qué usa cada biblioteca.

La corrección preferente es el build actualizado del proveedor, revisar los almacenes privados y reiniciar las JVM que lo usan. Si todavía no puedes instalarlo, Oracle documenta opciones temporales: copia del keystore antes de retirar las raíces indicadas, o comprobación de revocación. No borres todas las CA ni desactives la verificación de certificados para resolver un error TLS. [12]

Para aplicaciones TLS donde corresponda la alternativa oficial de revocación, las propiedades de arranque son:

Insertar CODE, HTML o PHP:
-Dcom.sun.net.ssl.checkRevocation=true
-Dcom.sun.security.enableCRLDP=true

Verifica que la aplicación aplica esa política, alcanza los servicios de revocación y conserva conexiones legítimas. No corrige el resto del CPU. Oracle ofrece CheckCerts.java: revisa el programa oficial antes de ejecutarlo y comprueba cada runtime y almacén. [12]

8. Si estás en hosting compartido

Pide evidencia referida a tu cuenta y nodo. Puedes adaptar este texto:

Necesito confirmar la corrección de las vulnerabilidades aplicables al runtime que ejecuta mi dominio o aplicación. Por favor, indiquen la rama y handler, nombre y revisión completa del paquete o build, referencia oficial que acredita el arreglo y renovación de sus procesos. Si existe backport, necesito la revisión del proveedor, no solo el número base. Para Java, confirmen también los avisos de certificados del 21 y 24 de octubre y el truststore utilizado. Si alguna medida sigue siendo temporal, indiquen su alcance y el siguiente paso.

No pidas datos de otros clientes. No cambies todas las webs de rama mayor sin compatibilidad ni declares vulnerable un backport por su versión base.

9. La parte forense: buscar una intrusión previa

El parche no elimina una intrusión anterior. Trabaja con línea de tiempo, originales conservados, hora, zona y cobertura de cada fuente.

  • Peticiones y WAF: fecha, ruta, método, regla, respuesta y cuerpo disponible. Un 403 acredita ese rechazo, no todos los intentos. Un 200 puede ser la portada normal; hay que seguir la evidencia.
  • Procesos y errores: caídas, errores de memoria, hijos inesperados y conexiones nuevas. No atribuyas un crash al exploit sin correlación y diagnóstico.
  • Archivos: cambios y propietarios comparados con despliegues y fuentes fiables. Un plugin actualizado hoy o una firma de antivirus que contiene código sospechoso no son automáticamente malware.
  • Persistencia: crons, timers, unidades, claves autorizadas, tareas de aplicación y arranques de contenedores. Compara con el estado conocido, sin borrar por heurística.
  • Accesos y secretos: administradores, contraseñas de aplicación y cambios de permisos. Si hay compromiso, contiene y limpia la causa antes de rotar credenciales desde un entorno fiable.

Para un WordPress, con su cuenta y desde su carpeta, una comprobación limitada útil es:

Bash:
wp core verify-checksums --include-root
wp plugin verify-checksums --all
wp user list --role=administrator --fields=ID,user_login,user_registered

Los checksums necesitan referencia de versión y procedencia: un plugin comercial puede no tenerla. Analiza archivos adicionales; estos comandos no auditan el host. [13]

En mi intervención no encontré evidencia de explotación exitosa en lo revisado. Reservo las identidades y datos de clientes: lo útil es el método y las pruebas.

10. Cuándo dar el trabajo por terminado

  • Inventario de dominios, servicios, runtimes privados, contenedores y réplicas reconciliado.
  • Versión completa o backport contrastado con el fabricante; descargas y firmas verificadas por su procedimiento.
  • Procesos renovados y arranques persistentes apuntando al runtime previsto.
  • Configuración efectiva comprobada, incluidas sesiones PHP y almacenes TLS de Java cuando apliquen.
  • Pruebas funcionales de las webs y aplicaciones: login, subida, tareas, API y conexiones externas pertinentes.
  • Revisión de indicios con fechas y límites documentados; errores previos separados de los cambios introducidos.
  • Respaldo recuperable y plan de reversión conservados. Una mitigación pendiente sigue figurando como pendiente.

Si algo falla tras actualizar, diagnostica la incompatibilidad. No desactives controles ni vuelvas silenciosamente a una versión vulnerable; valora aislamiento y una alternativa controlada.

Actualizar, mitigar y comprobar son trabajos distintos. Cuando se documentan los tres, se puede informar al cliente con algo más sólido que una captura del panel.

Fuentes primarias y documentación

  1. PHP: avisos del 21 y 23 de octubre, versiones y condiciones
  2. PHP: CVE-2026-109618, OOM y límites de la mitigación
  3. PHP: CVE-2026-109619, ciclo de vida y auditoría
  4. PHP-FPM: configuración administrativa de pools
  5. Node.js: diez avisos, ramas y descargas corregidas
  6. Docker: recreación de servicios con Compose
  7. Oracle: CPU de octubre y matriz de Java SE
  8. Oracle: alerta del 21 de octubre, intermediarios
  9. Oracle: alerta del 24 de octubre, raíces
  10. Oracle: builds y baseline del 24 de octubre
  11. Oracle: requisitos y comandos de jcmd
  12. Oracle: almacenes de confianza, alternativas y CheckCerts
  13. WordPress: documentación oficial de WP-CLI

Información contrastada al 25 de octubre de 2026. Las nuevas releases y revisiones de los fabricantes pueden cambiar las recomendaciones; conserva siempre la referencia y la fecha de tu comprobación.

Nos seguimos leyendo 🙂

CF
 
¿Te sirvió? Únete a la conversación

Con tu cuenta gratis puedes responder, escribirle al autor por mensaje privado y comprar con Saldo retenido: el pago se libera cuando recibes lo acordado.

Toma 30 segundos · vuelves a este tema al terminar
Muchas gracias por este aporte tan detallado y técnico. Tienes mucha razón al señalar que la vulnerabilidad de Node.js no ha recibido la misma difusión que la de PHP, de hecho esa ni me paso por la cabeza, igual voy a dar una revisada a mis servicios por pura precaución.
 
Muchas gracias, una info excelente.
 
Atrás
Arriba