El 21 de octubre de 2026 PHP publicó 8.5.12, 8.4.27, 8.3.36 y 8.2.35 para corregir PHP2Shell: CVE-2026-109618 y CVE-2026-109619, dos fallos de seguridad de memoria en el núcleo de PHP, ambos con CVSS v4.0 9.2, que permiten ejecución remota de código sin autenticación. Viven por debajo de tu framework, así que actualizar WordPress, Drupal o Laravel no cambia nada. Amazon vio un primer intento de explotación el 17 de octubre, cuatro días antes del parche.
La parte de noticia está en mi resumen del día de seguridad del 21 de octubre. Este post es la parte práctica: encontrar el PHP que de verdad atiende tus peticiones, parchearlo según el entorno, mitigar si todavía no podés y buscar en tus logs. Cada comando y directiva sale de los advisories, de la documentación de los proveedores o de mis propias revisiones de los índices de paquetes del 26 de octubre.
1. El Problema: Dos Fallos por Debajo de Tu Código
El advisory de php.net es directo: está en riesgo toda instalación de PHP que sirva peticiones web, incluidos PHP-FPM, Apache mod_php, php-cgi, FrankenPHP y LiteSpeed. El riesgo es mayor en mod_php, donde una petición sin autenticar puede disparar el ataque antes de que se ejecute código de la aplicación.
Para decidir bien esta semana te bastan cuatro conceptos. Mantengo la mecánica del exploit al nivel que publican los advisories.
CVE-2026-109618: RCE por corrupción en OOM
GHSA-w8hw-w9fx-j79w · CVSS v4.0 9.2
PHP maneja los errores de falta de memoria con longjmp(). Si la memoria se agota mientras los datos de la petición están a medio inicializar, el cierre de la petición trata después esos datos a medio construir como válidos. El advisory validó RCE completo por HTTP contra mod_php con los límites por defecto; FPM es susceptible según el análisis del código, sin un exploit completo demostrado para FPM.
CVE-2026-109619: RCE por estado global obsoleto
GHSA-6wmf-4rv5-p3rp · CVSS v4.0 9.2
Un worker conserva estado global que apunta a memoria de una petición concreta. Tras un error fatal, como un OOM o un ‘Maximum execution time exceeded’, esa memoria se libera, y una petición posterior en el mismo worker puede usar ese estado obsoleto antes de que la inicialización normal lo reinicie. Entre los consumidores tempranos confirmados están los diagnósticos de INI y el progreso de subida de sesión.
CVE-2026-115560: acotado y todavía sin parche
Advisory informativo de php.net · 23 oct
Necesita una configuración poco habitual: session.serialize_handler en php_binary o php_serialize en la configuración, cambiado a php con ini_set() antes de session_start(), y con el progreso de subida activo. Las versiones del 21 de octubre no lo corrigen; el advisory completo llegará con la próxima versión regular.
Por qué importa la reutilización de workers
PHP-FPM, mod_php, FrankenPHP, LiteSpeed
Los workers de larga vida atienden muchas peticiones, así que una petición maliciosa puede envenenar la siguiente. El advisory dice que la petición que produce el estado y la que lo consume deben caer en el mismo worker; tener varios workers y reciclarlos baja la probabilidad por intento, pero no elimina la condición.
Exposición por SAPI, según php.net y los advisories GHSA
| Cómo sirve PHP las peticiones | Exposición según los advisories | Qué reiniciar tras parchear |
|---|---|---|
| Apache mod_php | La más alta: RCE demostrado con límites por defecto, antes de que corra código de la app | apache2 / httpd |
| PHP-FPM (nginx, proxy de Apache) | Susceptible según el análisis del código; sin exploit completo para FPM en CVE-2026-109618 | php8.x-fpm / php-fpm, cada pool |
| FrankenPHP, LiteSpeed (LSAPI), php-cgi | En riesgo según php.net; FrankenPHP y LSAPI ‘probablemente susceptibles’ según el GHSA | El propio servidor (FrankenPHP 1.13.2+), lsphp |
| CLI (cron, colas, Artisan) | No es punto de entrada HTTP, pero es el mismo motor: parchealo también | Workers de colas, Horizon, Octane, procesos de Supervisor |
Cronología (fechas tal como las publica cada fuente)
Un resumen popular de una línea mezcla dos fallos
Algunas guías de parcheo describen PHP2Shell como ‘una petición que choca con memory_limit en el peor momento y deja memoria obsoleta para la siguiente’. Eso mezcla los dos CVE. CVE-2026-109618 corrompe la petición que se quedó sin memoria; CVE-2026-109619 es estado obsoleto que reutiliza una petición posterior, y entre sus disparadores están los timeouts de ejecución, no solo la memoria. Importa para mitigar: memory_limit=-1 apunta al primero y desactivar el progreso de subida cierra caminos confirmados del segundo.
2. Paso 1: Encontrá el PHP que de Verdad Atiende Peticiones
En un servidor típico encuentro tres PHP: el CLI del PATH, uno o más pools de php-fpm y, a veces, un mod_php que nadie recuerda haber activado. Pueden ser paquetes distintos en versiones distintas, y solo los que responden HTTP deciden si estás expuesto.
Builds corregidos que verifiqué (26 de octubre de 2026)
| Fuente | Versión o revisión de paquete corregida | Nota |
|---|---|---|
| php.net 8.5 / 8.4 / 8.3 / 8.2 | 8.5.12 · 8.4.27 · 8.3.36 · 8.2.35 | El soporte de seguridad de 8.2 termina el 31-12-2026 |
| Debian 13 trixie (php8.4) | 8.4.27-1~deb13u1 | DSA-6574-1 |
| Debian 12 bookworm (php8.2) | 8.2.35-1~deb12u1 | DLA-4848-1 (Debian LTS) |
| Ubuntu 26.04 LTS (php8.5) | 8.5.4-0ubuntu1.5 | USN-8948-1, backport |
| Ubuntu 24.04 LTS (php8.3) | 8.3.6-0ubuntu0.24.04.13 | USN-8948-1: php -v sigue diciendo 8.3.6 |
| Ubuntu 22.04 LTS (php8.1) | 8.1.2-1ubuntu2.28 | USN-8948-1: 8.1 parcheado |
| Repo / PPA de Surý, ramas antiguas | 8.1.34-9 · 1:8.0.30-25 · 1:7.4.33-31 | Backports compilados el 21 oct; mismo php -v que antes |
| Imagen oficial php de Docker | php:8.5.12-*, 8.4.27-*, 8.3.36-*, 8.2.35-* | Sin tag php:8.1 parcheado (última actualización dic 2025) |
| FrankenPHP | 1.13.2 | Imágenes y binarios estáticos recompilados el 21 oct |
| Remi (Fedora, EL 8+) | 8.5.12 · 8.4.27 · 8.3.36 · 8.2.35 | remi-modular y remi-safe (SCL), 22 oct |
Inventario: cada PHP de la máquina y el paquete que lo respalda
Correlo en cada host y dentro de cada contenedor. Lo que demuestra un backport es la revisión del paquete, no la cadena de versión.
# 1. Qué ramas están instaladas (estructura de Debian/Ubuntu)
ls /etc/php/
php -v # solo el CLI: el primer binario de tu PATH
# 2. Los binarios que sirven peticiones web
php-fpm8.4 -v # Debian/Ubuntu: un php-fpmX.Y por rama
php-fpm -v # RHEL, Alma, Rocky, streams de módulo de Remi
apachectl -M 2>/dev/null | grep -i php # php_module = mod_php (httpd -M en RHEL)
# 3. Revisiones de paquete: lo que cuenta cuando el arreglo es un backport
dpkg -l 'php*' 'libapache2-mod-php*' | awk '/^ii/ {print $2, $3}'
rpm -qa 'php*' | sort
# 4. Contenedores: lo que está corriendo, no a dónde apunta hoy el tag
docker exec <contenedor> php -v
docker run --rm --pull=always php:8.4-fpm php -v
# 5. Desde fuera, solo si expose_php está activo
curl -sI https://example.com | grep -i '^x-powered-by'Qué corre FPM de verdad, sin publicar una página phpinfo()
El boletín de Red Hat advierte que php -i solo muestra la configuración del CLI. Esto le pregunta directamente al socket de FPM, así que no exponés nada por el servidor web, y luego lista los procesos que siguen mapeando un binario o módulo de PHP viejo tras actualizar.
# cgi-fcgi viene en libfcgi-bin (Debian/Ubuntu) o fcgi (EPEL)
sudo tee /var/www/php2shell-check.php >/dev/null <<'EOF'
<?php
header('Content-Type: text/plain');
echo PHP_VERSION, ' ', PHP_SAPI, PHP_EOL;
foreach (['session.upload_progress.enabled', 'memory_limit',
'post_max_size', 'fatal_error_backtraces'] as $k) {
echo $k, ' = ', var_export(ini_get($k), true), PHP_EOL;
}
EOF
sudo env SCRIPT_FILENAME=/var/www/php2shell-check.php REQUEST_METHOD=GET \
cgi-fcgi -bind -connect /run/php/php8.4-fpm.sock # RHEL: /run/php-fpm/www.sock
sudo rm /var/www/php2shell-check.php
# Tras apt/dnf: procesos que siguen corriendo un binario o módulo de PHP reemplazado
sudo grep -l 'php.*(deleted)' /proc/[0-9]*/maps 2>/dev/nullCómo se ve ‘parcheado’
php-fpmX.Y -v (o el chequeo de FPM de arriba) muestra una versión corregida o, en backports, una revisión de paquete corregida; el módulo que carga Apache viene de un paquete corregido; y el grep en /proc no devuelve nada. Si aparece un PID ahí, ese proceso sigue corriendo el código viejo.
3. Paso 2: Parcheá Según el Entorno
El objetivo es el mismo en todas partes: poner un build corregido debajo del proceso que responde HTTP y reiniciarlo. Lo que cambia es cómo te llega ese build.
Debian y Ubuntu (distro o Surý)
DSA-6574-1 · DLA-4848-1 · USN-8948-1 · packages.sury.org
Debian corrigió php8.4 en trixie y php8.2 en bookworm; Ubuntu publicó USN-8948-1 el 21 de octubre para 22.04, 24.04, 26.04 y 26.10. Si usás el repositorio o el PPA de Ondřej Surý, su índice tiene builds corregidos con fecha 21 de octubre para cada rama de 7.4 a 8.5. Laravel Forge recuerda que unattended-upgrades solo toma el repositorio de seguridad de Ubuntu, así que los repos de PHP de terceros no se parchean solos. Repetí para cada rama instalada, aunque no la uses.
sudo apt-get update
apt-cache policy php8.4-fpm # ¿el Candidate es la versión o revisión corregida?
sudo apt-get install --only-upgrade -y \
-o Dpkg::Options::="--force-confold" \
$(dpkg -l 'php8.4*' | awk '/^ii/ {print $2}')
sudo systemctl restart php8.4-fpm # mod_php: sudo systemctl restart apache2RHEL, Alma, Rocky (AppStream o Remi)
RHSB-2026-013 · Remi, 22 oct
El boletín de Red Hat lista RHEL 8, 9 y 10 como afectados (RHEL 7 solo por CVE-2026-109619) y, en su actualización del 23 de octubre, dice que algunas correcciones ya salieron y otras están en curso. Remi publicó 8.5.12, 8.4.27, 8.3.36 y 8.2.35 el 22 de octubre en remi-modular y como Software Collections en remi-safe. Si tu stream aún no tiene arreglo, aplicá hoy el paso 3.
sudo dnf upgrade 'php*' # stream de AppStream o remi-modular de Remi sudo dnf upgrade 'php84*' # Software Collections de Remi (remi-safe) rpm -q --changelog php-fpm | grep -m2 'CVE-2026-10961' # si tu proveedor lista los CVE sudo systemctl restart php-fpm httpd # SCL: php84-php-fpm
Imágenes oficiales de Docker
Reconstruí, no reinicies · fijá tag + digest
Un reinicio reutiliza la misma imagen, así que un contenedor en marcha conserva el PHP con el que se construyó. Los tags oficiales de php para 8.5.12, 8.4.27, 8.3.36 y 8.2.35 estaban en Docker Hub la noche del 21 de octubre (UTC) y se han recompilado desde entonces. Fijá el tag exacto del parche más su digest para que los builds sean reproducibles, y dejá que Renovate o Dependabot lo suban. Si construís FROM una imagen de PHP de terceros, revisá el changelog de ese proveedor.
# Obtené el digest del tag corregido y fijá ambos en el Dockerfile docker buildx imagetools inspect php:8.4.27-fpm | grep -m1 Digest # FROM php:8.4.27-fpm@sha256:<digest> # Reconstruí sin capas base en caché y recrea los contenedores docker compose build --pull --no-cache docker compose up -d --force-recreate docker compose exec app php -v
Hosting compartido y cPanel
El proveedor parchea; vos verificás
Acá no podés parchear PHP vos. En cPanel, MultiPHP Manager cambia qué versión usa un dominio, no el nivel de parche de esa versión. Tanium informa que EasyApache 4 v25.91 trae el arreglo; no encontré la nota de cPanel ni un estado confirmado para alt-php de CloudLinux. Mandale a tu proveedor tres preguntas precisas:
Asunto: PHP2Shell (CVE-2026-109618 / CVE-2026-109619) 1. ¿Qué build de PHP sirve mi cuenta (ea-phpXX, alt-php, lsphp) y en qué revisión de paquete? 2. ¿Incluye los arreglos del 21-10-2026 y se reiniciaron los workers de PHP-FPM / LiteSpeed? 3. ¿Está session.upload_progress.enabled desactivado hasta la próxima versión de PHP (CVE-2026-115560)?
WordPress y Drupal
Actualizar core y plugins no arregla PHP
El fallo está en PHP, así que actualizar el core o los plugins no hace nada; el boletín de Vercel dice lo mismo del código de aplicación. Wiz afirma que confirmó RCE sin autenticación contra Drupal y WordPress durante su investigación. Sin SSH, abrí Herramientas → Salud del sitio → Información → Servidor: ahí ves la versión de PHP y la SAPI. En hosting gestionado, pedí la revisión del paquete, no solo ‘estamos en 8.3’.
Laravel (Forge, colas, Octane)
Advisory de Laravel Forge, oct 2026
Las actualizaciones de seguridad automáticas de Forge no parchean PHP: actualizá cada versión desde la pestaña PHP del servidor o por SSH. Los procesos CLI de larga vida conservan el binario viejo hasta que se reinician: workers de colas, Horizon, Octane, Reverb. Si Octane corre sobre FrankenPHP, actualizá el propio FrankenPHP a 1.13.2 o superior.
php artisan queue:restart php artisan horizon:terminate php artisan octane:reload
FrankenPHP, Windows y AWS
FrankenPHP 1.13.2 · builds -1 de php.net · AWS 2026-143
FrankenPHP 1.13.2 (21 de octubre) recompiló sus imágenes y binarios estáticos con las versiones de PHP corregidas. En Windows, usá los builds de php.net; los rebuilds -1 del 26 de octubre además actualizan Brotli por un fallo distinto en la descompresión de cURL. En AWS, Elastic Beanstalk tiene versiones de plataforma actualizadas, Lightsail requiere instancias nuevas desde blueprints actualizados, y los runtimes personalizados de Lambda o Bref hay que reconstruirlos y volver a desplegarlos.
4. Paso 3: Mitigá si Hoy No Podés Parchear
php.net lista medidas que reducen la exposición a caminos de ataque concretos ‘pero no hacen segura una instalación’. Ponelas donde PHP las lee antes de parsear la petición: php.ini, el pool de FPM o la configuración de Apache. php.net es explícito: ini_set() y el .user.ini de FPM no sirven.
Pool de PHP-FPM: ajustes que una app no puede sobrescribir
Sale directo del advisory de php.net y de GHSA-6wmf-4rv5-p3rp. php_admin_value y php_admin_flag no se pueden cambiar después con ini_set().
; /etc/php/8.4/fpm/pool.d/www.conf (RHEL: /etc/php-fpm.d/www.conf) php_admin_flag[session.upload_progress.enabled] = off ; -1 solo junto con un tope de memoria de cgroup o contenedor (abajo) php_admin_value[memory_limit] = -1 ; 8M si la app no recibe subidas, 32M si las recibe php_admin_value[post_max_size] = 8M php_admin_value[upload_max_filesize] = 6M ; Solo PHP 8.5, las ramas anteriores no conocen esta directiva: ; php_admin_flag[fatal_error_backtraces] = off ; Último recurso si el rendimiento no importa (GHSA-6wmf-4rv5-p3rp): ; pm.max_requests = 1 # Ningún otro pool, archivo de conf.d o vhost debe devolver un límite finito grep -rn 'memory_limit\|upload_progress' /etc/php/8.4/ sudo systemctl restart php8.4-fpm
Apache mod_php, más el tope de cgroup que necesita memory_limit=-1
php.net pide un límite de memoria externo que mate solo al worker afectado. MemoryMax= de systemd pone el tope; OOMPolicy=continue mantiene el servicio arriba cuando el kernel mata un proceso (la política por defecto detiene toda la unidad). Ajustá el tope a tu máquina.
# /etc/apache2/conf-available/php2shell.conf (RHEL: /etc/httpd/conf.d/)
<IfModule php_module>
php_admin_flag session.upload_progress.enabled off
php_admin_value memory_limit -1
php_admin_value post_max_size 8M
php_admin_value upload_max_filesize 6M
</IfModule>
sudo a2enconf php2shell && sudo systemctl restart apache2
# sudo systemctl edit php8.4-fpm (o apache2 / httpd)
[Service]
MemoryMax=2G
OOMPolicy=continuePuentes alrededor de la configuración
- WAF como puente: Cloudflare (todos los planes con WAF, incluido Free, según la cobertura de su anuncio), el grupo de reglas gestionadas de PHP de AWS WAF (las versiones fijadas hay que actualizarlas) y el WAF de Vercel publicaron reglas. Solo ven el tráfico que pasa por ellos, así que restringí el origen a los rangos de IP del proxy.
- Bloqueá multipart donde puedas: Amazon sugiere bloquear las subidas multipart en despliegues de PHP que aún no podés parchear, después de medir el impacto en tu app. Como mínimo, limitá el tamaño de la petición en el proxy (client_max_body_size en nginx, LimitRequestBody en Apache); php.net también pide límites de campos, partes multipart y cabeceras.
- Reciclá workers, como último recurso: el advisory de CVE-2026-109619 sugiere pm.max_requests=1 ‘si el rendimiento no es un factor’. Baja la tasa de éxito por intento; no elimina la condición.
- Corregí tus propios errores fatales: php.net pide corregir los errores fatales y timeouts de ejecución que un atacante pueda provocar, y quitar ajustes por petición inválidos u obsoletos que emitan diagnósticos. Ocultarlos con error_reporting, display_errors o @ no ayuda.
CVE-2026-115560: no lo corrigen las versiones del 21 de octubre
El advisory informativo de php.net del 23 de octubre cubre un tercer vector de RCE, acotado; el advisory completo saldrá con la próxima versión regular. Requiere session.serialize_handler en php_binary o php_serialize en la configuración y cambiado a php con ini_set() antes de session_start(), con el progreso de subida activo. La mitigación es la misma línea de arriba, session.upload_progress.enabled=0, y php.net dice que las apps que nunca cambian el handler pueden mantener la función. Mi opinión: desactivala salvo que muestres barras de progreso de subida, porque también cierra caminos confirmados de CVE-2026-109619, y el GHSA considera prudente desactivarla incluso tras parchear. Chequeo rápido: grep -rn serialize_handler en tu código y en la configuración de PHP.
Mitigaciones que pueden salir caras
memory_limit=-1 sin un tope externo convierte un intento de explotación en una caída por agotamiento de memoria, y php.net desaconseja RLIMIT_AS o RLIMIT_DATA, que pueden provocar justo el fallo de asignación que querés evitar. Poner fatal_error_backtraces por debajo de PHP 8.5 añade una directiva desconocida, el tipo de ajuste inválido que el advisory pide quitar. Y reiniciá cada worker, como dice php.net: hasta que se reinicia, un worker conserva los ajustes viejos.
5. Paso 4: Detectá lo que Ya Te Llegó
Ninguna firma pública detecta PHP2Shell de forma fiable, y el advisory de CVE-2026-109619 avisa que un log limpio no prueba que estés a salvo. Lo que dan las fuentes es un conjunto de señales para correlacionar, empezando el 17 de octubre, no el 21.
Señales que nombran las fuentes
- Wiz: peticiones multipart inusuales seguidas de errores de límite de memoria o respuestas HTTP 500 repetidas, cookies PHPSESSID de respuesta inesperadamente grandes o malformadas, y rotación de workers de PHP sin explicación.
- Amazon: peticiones POST con la cadena PHP_SESSION_UPLOAD_PROGRESS en subidas de formularios. Esa cadena va en el cuerpo de la petición, así que solo la verá un WAF o un log del cuerpo.
- Advisory de PHP: ‘Maximum execution time exceeded’, errores de parseo, compilación y no capturados, warnings o deprecations repetidos antes de que corran tus scripts, y diagnósticos durante la limpieza.
- IPs de Amazon: seis direcciones de infraestructura de anonimización compartida. Amazon dice que investigues las coincidencias en lugar de solo bloquearlas.
Búsqueda en logs de solo lectura (rutas de Debian/Ubuntu; ajustalas en RHEL)
Todo lo de abajo solo lee logs. zgrep y zcat -f también leen los .gz rotados.
# 1. Errores fatales que actúan como disparadores
sudo zgrep -hE 'Allowed memory size of [0-9]+ bytes exhausted|Maximum execution time of [0-9]+ seconds? exceeded' \
/var/log/php*-fpm.log* /var/log/apache2/error.log* /var/log/nginx/error.log* 2>/dev/null | tail -50
# 2. Rotación de workers: hijos de FPM que mueren, hijos de Apache que fallan
sudo zgrep -hE 'exited on signal|exited with code [1-9]' /var/log/php*-fpm.log* | tail -50
sudo zgrep -h 'exit signal' /var/log/apache2/error.log* | tail -20
# 3. Ráfagas de 500 en POST, por IP de cliente y minuto (formato combined)
sudo zcat -f /var/log/nginx/access.log* | \
awk '$6=="\"POST" && $9==500 {split($4,t,":"); print $1, t[1]":"t[2]":"t[3]}' | \
sort | uniq -c | sort -rn | head -20
# 4. Las IPs que publicó Amazon (infraestructura compartida: investigá, no solo bloquees)
sudo zgrep -hE '^(103\.216\.220\.92|31\.223\.184\.166|37\.19\.200\.5|134\.209\.159\.64|103\.114\.163\.188|95\.217\.98\.37) ' \
/var/log/nginx/access.log* /var/log/apache2/access.log* 2>/dev/nullRegistrá lo que los formatos por defecto no guardan, durante unas semanas
El formato combined no guarda ni el Content-Type ni las cookies de respuesta. Estos formatos añaden ambos. Los valores de Set-Cookie son IDs de sesión vivos: restringí el acceso a este log y borralo cuando termines.
# nginx (dentro de http {})
log_format php2shell '$remote_addr [$time_local] "$request" $status '
'$request_length "$content_type" "$sent_http_set_cookie"';
access_log /var/log/nginx/php2shell.log php2shell;
# Apache (necesita mod_logio para %I)
LogFormat "%h %t \"%r\" %>s %I \"%{Content-Type}i\" \"%{Set-Cookie}o\"" php2shell
CustomLog ${APACHE_LOG_DIR}/php2shell.log php2shell
# Valores de PHPSESSID mucho más largos que tu session.sid_length (por defecto 32)
grep -ohE 'PHPSESSID=[^;" ]+' /var/log/nginx/php2shell.log | awk 'length($0) > 80' | sort | uniq -c | headSi encontrás una coincidencia
Tratá el host como comprometido hasta demostrar lo contrario. El código corre con los privilegios del worker web, así que asumí expuesto todo lo que ese usuario pueda leer (archivos .env, credenciales de base de datos, API keys). Buscá procesos inesperados y archivos modificados bajo la raíz web, como recomienda Amazon, rotá esos secretos desde una máquina limpia y, cuando puedas, reconstruí en lugar de limpiar en el sitio.
6. Atascado en PHP 8.1 o Anterior
php.net no publica nuevas versiones de 8.1, 8.0 ni 7.4, pero ‘sin versión oficial’ no es lo mismo que ‘sin arreglo’. Esto es lo que existe, en el orden en que yo lo usaría.
- 1. Backports empaquetados: Ubuntu 22.04 parcheó su php8.1 (8.1.2-1ubuntu2.28). Surý publica 8.1.34-9, 1:8.0.30-25 y 1:7.4.33-31, y el changelog de 8.1 dice ‘Backported from 8.2.35 [CVE-2026-109618, CVE-2026-109619]’. php -v muestra lo mismo antes y después, así que fijate la revisión con dpkg -l.
- 2. Backports de código fuente: el equipo de seguridad de PHP publicó backports mínimos para 7.4, 8.0 y 8.1, pensados para quien compila desde el código o no tiene un proveedor LTS.
- 3. Docker: los tags oficiales php:8.1 se actualizaron por última vez en diciembre de 2025. No hay imagen oficial de 8.1 parcheada: construí sobre un paquete de distro que traiga el backport, o subí de versión.
- 4. Mitigá y mantenelo: el boletín de AWS indica a las ramas sin soporte aplicar los controles provisionales de CVE-2026-109619 y reiniciar los workers. En estas ramas el paso 3 no es temporal.
- 5. Subí a 8.4 u 8.5, no a 8.2: el soporte de seguridad de 8.2 termina el 31 de diciembre de 2026, así que te da dos meses. 8.3 llega al 31 de diciembre de 2027, 8.4 a 2028 y 8.5 a 2029.
7. Errores Comunes que Revisaría
Cada uno deja un servidor vulnerable mientras el panel dice ‘parcheado’.
- ✗ Fiarte de php -v en el CLI: el CLI, FPM y mod_php son paquetes separados y pueden estar en versiones distintas. Revisá php-fpmX.Y -v y el módulo que carga Apache.
- ✗ Leer versiones de distro como versiones upstream: el PHP parcheado de Ubuntu 24.04 sigue diciendo 8.3.6, y el 8.1 parcheado de Surý sigue diciendo 8.1.34. Juzgá por la revisión del paquete o el aviso del proveedor.
- ✗ Actualizar sin reiniciar: un paquete nuevo en disco no hace nada por un proceso maestro que sigue corriendo el binario viejo. El chequeo de /proc del paso 1 los encuentra, workers de colas incluidos.
- ✗ Reiniciar un contenedor en vez de reconstruirlo: o correr docker run php:8.4-fpm contra una imagen vieja en caché local. Hacé pull, reconstruí con --no-cache y recreá.
- ✗ Poner las mitigaciones donde PHP las lee tarde: ini_set(), .user.ini o php_value en lugar de php_admin_value en el pool o en la configuración del servidor.
- ✗ Tratar el WAF como la solución: todos los proveedores que publicaron reglas las llaman un parche provisional, y no hacen nada por el tráfico que llega directo al origen.
- ✗ Empezar la investigación el 21 de octubre: Amazon vio el primer intento el día 17.
8. Qué Está Confirmado y Qué No (Revisado el 26 de Octubre de 2026)
‘Confirmado’ significa una fuente primaria (php.net, un advisory GHSA, un boletín de distro o proveedor, un índice de paquetes) más al menos otra. Todo lo demás va redactado como ‘según’.
Versiones corregidas y alcance
php.net, los dos advisories GHSA, AWS, Debian, Ubuntu, Remi y el índice de Surý coinciden: 8.5.12, 8.4.27, 8.3.36 y 8.2.35, con todas las versiones anteriores de esas ramas afectadas. Wiz dice que casi todas las versiones de PHP desde la 5.4 sufren al menos uno de los dos.
Explotación
Amazon reporta un intento previo a la divulgación el 17 de octubre y explotación amplia desde entonces; Cloudflare, watchTowr y otros reportaron intentos alrededor de la divulgación. La CISA dijo al publicar que no había observado explotación. No encontré ningún compromiso exitoso confirmado públicamente, lo que es ausencia de evidencia, no evidencia de ausencia.
Severidad
PHP puntúa ambos con CVSS v4.0 9.2. Red Hat califica CVE-2026-109618 como Important (CVSS 3.1 8.1), con el argumento de que las instalaciones por defecto de RHEL usan FPM y son más difíciles de explotar. Parcheá igual.
Indicadores en logs
Las señales de PHPSESSID y HTTP 500 vienen del informe de Wiz, no de los advisories de PHP; la cadena del progreso de subida viene de Amazon. Tratalas todas como pistas de búsqueda, no como firmas.
Quién lo encontró y el ángulo de la IA
Wiz dice que usó Wiz Atlas, Gemini 4 Argon y GPT-5.6 Sol; el GHSA acredita a cuatro personas, y Reuters informa que Calif encontró los fallos con un modelo de lenguaje el 1 de agosto. ‘Varios equipos, con ayuda de IA’ es el resumen preciso.
Texto de la NSA y estado de cPanel
nsa.gov rechazó mi descarga, así que la indicación de la NSA de ‘actualizar o desconectar los sistemas’ es la que reportan TechCrunch, Defense One y AFP. El arreglo de EasyApache de cPanel descansa solo en el informe de Tanium.
Regla de oro
Parcheá el binario que sirve HTTP, demostralo con la revisión del paquete y el chequeo de /proc, reiniciá cada worker y recién entonces creete el número de versión.
Conclusión
PHP2Shell es ese fallo raro en el que tu aplicación casi no importa: en mod_php el ataque puede dispararse antes de que corra una sola línea de tu código, y actualizar WordPress o Laravel no cambia nada. El trabajo es operativo: encontrar cada PHP que responde HTTP, parchearlo como exige tu entorno y demostrar que el proceso en marcha es el nuevo.
Si hoy podés parchear, hacelo y dejá el progreso de subida desactivado hasta que la próxima versión cierre CVE-2026-115560. Si no podés, combiná las mitigaciones de php.net con un WAF, buscá en los logs desde el 17 de octubre y meté la salida de 8.1 y 8.2 en el plan de este trimestre.
Esta semana en una pantalla
Revisar
- • php-fpmX.Y -v, no php -v
- • Revisión del paquete en backports
- • /proc maps con (deleted)
Parchear
- • Paquetes o imagen reconstruida
- • Reiniciar FPM, Apache, workers
- • 8.1 o anterior: backport o migrar
Vigilar
- • Progreso de subida off (115560)
- • Logs desde el 17 de octubre
- • WAF solo como puente
Fuentes
- php.net — Archivo de noticias 2026 (advisory del 21 oct, CVE-2026-115560 el 23 oct, builds de Windows el 26 oct)
- GitHub — GHSA-w8hw-w9fx-j79w, RCE por corrupción en OOM (CVE-2026-109618)
- GitHub — GHSA-6wmf-4rv5-p3rp, RCE por estado global obsoleto (CVE-2026-109619)
- Wiz Research — PHP2Shell: la IA descubre vulnerabilidades RCE críticas
- AWS Security Blog — Amazon Threat Intelligence detecta explotación de PHP2Shell antes de la divulgación
- AWS Security Bulletin 2026-143-AWS — runtimes web de PHP
- Red Hat — RHSB-2026-013
- Ubuntu — USN-8948-1
- Debian security tracker — CVE-2026-109618
- Laravel Forge — advisory de seguridad de PHP (CVE-2026-109618, CVE-2026-109619)
- Repositorio RPM de Remi — PHP 8.2.35, 8.3.36, 8.4.27 y 8.5.12
- FrankenPHP — versión de seguridad v1.13.2
- Docker Hub — tags de la imagen oficial php
- php.net — Versiones con soporte
- TechCrunch — The internet is having a very bad cybersecurity day



